https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
AdjointSolve Class Reference

The solve object is responsible for solving the adjoint version of a forward model. More...

#include <AdjointSolve.h>

Inheritance diagram for AdjointSolve:
[legend]

Public Types

typedef DataFileName DataFileParameterType
 

Public Member Functions

 AdjointSolve (Executioner &ex)
 
virtual bool solve () override
 Solve the adjoint system with the following procedure:
 
virtual void initialSetup ()
 
virtual void setInnerSolve (SolveObject &solve)
 
virtual bool enabled () const
 
std::shared_ptr< MooseObject > getSharedPtr ()
 
std::shared_ptr< const MooseObject > getSharedPtr () const
 
bool isKokkosObject () const
 
MooseApp & getMooseApp () const
 
const std::string & type () const
 
const std::string & name () const
 
std::string typeAndName () const
 
MooseObjectParameterName uniqueParameterName (const std::string &parameter_name) const
 
MooseObjectName uniqueName () const
 
const InputParameters & parameters () const
 
const hit::Node * getHitNode () const
 
bool hasBase () const
 
const std::string & getBase () const
 
const T & getParam (const std::string &name) const
 
std::vector< std::pair< T1, T2 > > getParam (const std::string &param1, const std::string &param2) const
 
const T * queryParam (const std::string &name) const
 
const T & getRenamedParam (const std::string &old_name, const std::string &new_name) const
 
T getCheckedPointerParam (const std::string &name, const std::string &error_string="") const
 
bool isParamValid (const std::string &name) const
 
bool isParamSetByUser (const std::string &name) const
 
void connectControllableParams (const std::string &parameter, const std::string &object_type, const std::string &object_name, const std::string &object_parameter) const
 
void paramError (const std::string &param, Args... args) const
 
void paramWarning (const std::string &param, Args... args) const
 
void paramWarning (const std::string &param, Args... args) const
 
void paramInfo (const std::string &param, Args... args) const
 
std::string messagePrefix (const bool hit_prefix=true) const
 
std::string errorPrefix (const std::string &) const
 
void mooseError (Args &&... args) const
 
void mooseDocumentedError (const std::string &repo_name, const unsigned int issue_num, Args &&... args) const
 
void mooseErrorNonPrefixed (Args &&... args) const
 
void mooseWarning (Args &&... args) const
 
void mooseWarning (Args &&... args) const
 
void mooseWarningNonPrefixed (Args &&... args) const
 
void mooseWarningNonPrefixed (Args &&... args) const
 
void mooseDeprecated (Args &&... args) const
 
void mooseDeprecated (Args &&... args) const
 
void mooseDeprecatedNoTrace (Args &&... args) const
 
void mooseInfo (Args &&... args) const
 
void callMooseError (std::string msg, const bool with_prefix, const hit::Node *node=nullptr, const bool show_trace=true) const
 
std::string getDataFileName (const std::string &param) const
 
std::string getDataFileNameByName (const std::string &relative_path) const
 
std::string getDataFilePath (const std::string &relative_path) const
 
PerfGraph & perfGraph ()
 
bool isDefaultPostprocessorValue (const std::string &param_name, const unsigned int index=0) const
 
bool hasPostprocessor (const std::string &param_name, const unsigned int index=0) const
 
bool hasPostprocessorByName (const PostprocessorName &name) const
 
std::size_t coupledPostprocessors (const std::string &param_name) const
 
const PostprocessorName & getPostprocessorName (const std::string &param_name, const unsigned int index=0) const
 
const PostprocessorValue & getPostprocessorValue (const std::string &param_name, const unsigned int index=0) const
 
const PostprocessorValue & getPostprocessorValue (const std::string &param_name, const unsigned int index=0) const
 
const PostprocessorValue & getPostprocessorValueOld (const std::string &param_name, const unsigned int index=0) const
 
const PostprocessorValue & getPostprocessorValueOld (const std::string &param_name, const unsigned int index=0) const
 
const PostprocessorValue & getPostprocessorValueOlder (const std::string &param_name, const unsigned int index=0) const
 
const PostprocessorValue & getPostprocessorValueOlder (const std::string &param_name, const unsigned int index=0) const
 
virtual const PostprocessorValue & getPostprocessorValueByName (const PostprocessorName &name) const
 
virtual const PostprocessorValue & getPostprocessorValueByName (const PostprocessorName &name) const
 
const PostprocessorValue & getPostprocessorValueOldByName (const PostprocessorName &name) const
 
const PostprocessorValue & getPostprocessorValueOldByName (const PostprocessorName &name) const
 
const PostprocessorValue & getPostprocessorValueOlderByName (const PostprocessorName &name) const
 
const PostprocessorValue & getPostprocessorValueOlderByName (const PostprocessorName &name) const
 
const Parallel::Communicator & comm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Static Public Member Functions

static InputParameters validParams ()
 
static void callMooseError (MooseApp *const app, const InputParameters &params, std::string msg, const bool with_prefix, const hit::Node *node, const bool show_trace=true)
 

Public Attributes

 usingCombinedWarningSolutionWarnings
 
const ConsoleStream _console
 

Static Public Attributes

static const std::string type_param
 
static const std::string name_param
 
static const std::string unique_name_param
 
static const std::string app_param
 
static const std::string moose_base_param
 
static const std::string kokkos_object_param
 

Protected Member Functions

void checkIntegrity ()
 Checks whether the forward and adjoint systems are consistent.
 
virtual void assembleAdjointSystem (SparseMatrix< Number > &matrix, const NumericVector< Number > &solution, NumericVector< Number > &rhs)
 Assembles adjoint system.
 
void applyNodalBCs (SparseMatrix< Number > &matrix, const NumericVector< Number > &solution, NumericVector< Number > &rhs)
 Helper function for applying nodal BCs to the adjoint matrix and RHS.
 
void flagInvalidSolutionInternal (const InvalidSolutionID invalid_solution_id) const
 
InvalidSolutionID registerInvalidSolutionInternal (const std::string &message, const bool warning) const
 
PerfID registerTimedSection (const std::string &section_name, const unsigned int level) const
 
PerfID registerTimedSection (const std::string &section_name, const unsigned int level, const std::string &live_message, const bool print_dots=true) const
 
std::string timedSectionName (const std::string &section_name) const
 
virtual void addPostprocessorDependencyHelper (const PostprocessorName &) const
 

Protected Attributes

const unsigned int _forward_sys_num
 The number of the nonlinear system representing the forward model.
 
const unsigned int _adjoint_sys_num
 The number of the nonlinear system representing the adjoint model.
 
NonlinearSystemBase & _nl_forward
 The nonlinear system representing the forward model.
 
NonlinearSystemBase & _nl_adjoint
 The nonlinear system representing the adjoint model.
 
Executioner & _executioner
 
FEProblemBase & _problem
 
DisplacedProblem * _displaced_problem
 
MooseMesh & _mesh
 
MooseMesh * _displaced_mesh
 
SystemBase & _solver_sys
 
AuxiliarySystem & _aux
 
SolveObject * _inner_solve
 
const bool & _enabled
 
MooseApp & _app
 
Factory & _factory
 
ActionFactory & _action_factory
 
const std::string & _type
 
const std::string & _name
 
const InputParameters & _pars
 
MooseApp & _pg_moose_app
 
const std::string _prefix
 
const Parallel::Communicator & _communicator
 

Private Member Functions

const PostprocessorName & getPostprocessorNameInternal (const std::string &param_name, const unsigned int index, const bool allow_default_value=true) const
 
bool isDefaultPostprocessorValueByName (const PostprocessorName &name) const
 
PostprocessorValue getDefaultPostprocessorValueByName (const PostprocessorName &name) const
 
void checkParam (const std::string &param_name, const unsigned int index=std::numeric_limits< unsigned int >::max()) const
 
bool postprocessorsAdded () const
 
const PostprocessorValue & getPostprocessorValueInternal (const std::string &param_name, unsigned int index, std::size_t t_index) const
 
const PostprocessorValue & getPostprocessorValueInternal (const std::string &param_name, unsigned int index, std::size_t t_index) const
 
const PostprocessorValue & getPostprocessorValueByNameInternal (const PostprocessorName &name, std::size_t t_index) const
 
const PostprocessorValue & getPostprocessorValueByNameInternal (const PostprocessorName &name, std::size_t t_index) const
 

Static Private Member Functions

static const hit::Node * getHitNode (const InputParameters &params)
 
static std::string messagePrefix (const InputParameters &params, const bool hit_prefix)
 

Private Attributes

const ParallelParamObject & _parent
 
const MooseBase & _si_moose_base
 
const FEProblemBase * _si_problem
 
const MooseObject & _ppi_moose_object
 
const InputParameters & _ppi_params
 
const FEProblemBase & _ppi_feproblem
 
std::map< PostprocessorName, std::unique_ptr< PostprocessorValue > > _default_values
 

Detailed Description

The solve object is responsible for solving the adjoint version of a forward model.

It does this by solving a linear system with a transposed matrix and a source. The matrix is evaluated from the forward model's Jacobian, using the converged solution. The source is computed by evaluating the residual of a secondary nonlinear-system representing the adjoint system, in which the adjoint solution is 0.

Definition at line 31 of file AdjointSolve.h.

Constructor & Destructor Documentation

◆ AdjointSolve()

AdjointSolve::AdjointSolve ( Executioner &  ex)

Definition at line 40 of file AdjointSolve.C.

41 : SolveObject(ex),
43 _problem.nlSysNum(getParam<std::vector<SolverSystemName>>("forward_system")[0])),
44 _adjoint_sys_num(_problem.nlSysNum(getParam<NonlinearSystemName>("adjoint_system"))),
47{
48 // Disallow vectors of systems
49 if (getParam<std::vector<SolverSystemName>>("forward_system").size() != 1)
50 paramError("forward_system",
51 "Multiple nonlinear forward systems is not supported at the moment");
52
53 // These should never be hit, but just in case
54 if (!dynamic_cast<NonlinearSystem *>(&_nl_forward))
55 paramError("forward_system", "Forward system does not appear to be a 'NonlinearSystem'.");
56 if (!dynamic_cast<NonlinearSystem *>(&_nl_adjoint))
57 paramError("adjoint_system", "Adjoint system does not appear to be a 'NonlinearSystem'.");
58 // Adjoint system should never perform its own automatic scaling. Scaling factors from the forward
59 // system are applied.
61
62 // Set the solver options for the adjoint system
63 mooseAssert(_problem.numSolverSystems() > 1,
64 "We should have forward and adjoint systems as evidenced by our initialization list");
65 const auto prefix = _nl_adjoint.prefix();
68 // Set solver parameter prefix
69 auto & solver_params = _problem.solverParams(_nl_adjoint.number());
70 solver_params._prefix = prefix;
71 solver_params._solver_sys_num = _nl_adjoint.number();
72}
const unsigned int _forward_sys_num
The number of the nonlinear system representing the forward model.
NonlinearSystemBase & _nl_forward
The nonlinear system representing the forward model.
const unsigned int _adjoint_sys_num
The number of the nonlinear system representing the adjoint model.
NonlinearSystemBase & _nl_adjoint
The nonlinear system representing the adjoint model.
virtual std::size_t numSolverSystems() const override
SolverParams & solverParams(unsigned int solver_sys_num=0)
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
void paramError(const std::string &param, Args... args) const
const T & getParam(const std::string &name) const
FEProblemBase & _problem
std::string _prefix
bool automaticScaling() const
std::string prefix() const
unsigned int number() const
void setConvergedReasonFlags(FEProblemBase &fe_problem, std::string prefix)
void storePetscOptions(FEProblemBase &fe_problem, const std::string &prefix, const ParallelParamObject &param_object)

Member Function Documentation

◆ applyNodalBCs()

void AdjointSolve::applyNodalBCs ( SparseMatrix< Number > &  matrix,
const NumericVector< Number > &  solution,
NumericVector< Number > &  rhs 
)
protected

Helper function for applying nodal BCs to the adjoint matrix and RHS.

Say there is a BC setting the d-th DoF to a dirichlet condition on the forward problem. This basically sets the d-th column of the matrix to zero, the d-th entry of the matrix diagonal to one, and the d-th entry of the RHS to the solution passed in.

Parameters
matrixThe matrix whose columns are set to 0
solutionThe solution to replace the entries of the RHS
rhsThe RHS to to replace with the solution

Definition at line 179 of file AdjointSolve.C.

182{
183 std::vector<dof_id_type> nbc_dofs;
184 auto & nbc_warehouse = _nl_forward.getNodalBCWarehouse();
185 if (nbc_warehouse.hasActiveObjects())
186 {
187 for (const auto & bnode : *_mesh.getBoundaryNodeRange())
188 {
189 BoundaryID boundary_id = bnode->_bnd_id;
190 Node * node = bnode->_node;
191
192 if (!nbc_warehouse.hasActiveBoundaryObjects(boundary_id) ||
193 node->processor_id() != processor_id())
194 continue;
195
196 for (const auto & bc : nbc_warehouse.getActiveBoundaryObjects(boundary_id))
197 if (bc->shouldApply())
198 for (unsigned int c = 0; c < bc->variable().count(); ++c)
199 nbc_dofs.push_back(node->dof_number(_forward_sys_num, bc->variable().number() + c, 0));
200 }
201
202 // Petsc has a nice interface for zeroing rows and columns, so we'll use it
203 auto petsc_matrix = dynamic_cast<PetscMatrix<Number> *>(&matrix);
204 auto petsc_solution = dynamic_cast<const PetscVector<Number> *>(&solution);
205 auto petsc_rhs = dynamic_cast<PetscVector<Number> *>(&rhs);
206 if (petsc_matrix && petsc_solution && petsc_rhs)
207 LibmeshPetscCall(MatZeroRowsColumns(petsc_matrix->mat(),
208 cast_int<PetscInt>(nbc_dofs.size()),
209 libMesh::numeric_petsc_cast(nbc_dofs.data()),
210 1.0,
211 petsc_solution->vec(),
212 petsc_rhs->vec()));
213 else
214 mooseError("Using PETSc matrices and vectors is required for applying homogenized boundary "
215 "conditions.");
216 }
217}
boundary_id_type BoundaryID
for(PetscInt i=0;i< nvars;++i)
void ErrorVector unsigned int
void mooseError(Args &&... args) const
const MooseObjectTagWarehouse< NodalBCBase > & getNodalBCWarehouse() const
MooseMesh & _mesh
processor_id_type processor_id() const
if(subdm)
PetscInt * numeric_petsc_cast(const numeric_index_type *p)

Referenced by solve().

◆ assembleAdjointSystem()

void AdjointSolve::assembleAdjointSystem ( SparseMatrix< Number > &  matrix,
const NumericVector< Number > &  solution,
NumericVector< Number > &  rhs 
)
protectedvirtual

Assembles adjoint system.

Parameters
matrixUn-transposed matrix (will be transposed later in solver)
solutionAdjoint solution (basically the initial guess for the solver)
rhsThe adjoint source (i.e. -residual)

Reimplemented in AdjointTransientSolve.

Definition at line 165 of file AdjointSolve.C.

168{
169
171
174 rhs.close();
175 rhs.scale(-1.0);
176}
virtual void computeJacobian(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, const unsigned int nl_sys_num)
void setCurrentNonlinearSystem(const unsigned int nl_sys_num)
virtual void computeResidualTag(const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual, TagID tag)
TagID nonTimeVectorTag() const override
virtual const NumericVector< Number > *const & currentSolution() const override final
virtual void close()=0
virtual void scale(const T factor)=0

Referenced by AdjointTransientSolve::assembleAdjointSystem(), and solve().

◆ checkIntegrity()

void AdjointSolve::checkIntegrity ( )
protected

Checks whether the forward and adjoint systems are consistent.

Definition at line 220 of file AdjointSolve.C.

221{
222 const auto adj_vars = _nl_adjoint.getVariables(0);
223 for (const auto & adj_var : adj_vars)
224 // If the user supplies any scaling factors for individual variables the
225 // adjoint system won't be consistent.
226 if (!libMesh::absolute_fuzzy_equals(adj_var->scalingFactor(), 1.0))
228 "User cannot supply scaling factors for adjoint variables. Adjoint system is scaled "
229 "automatically by the forward system.");
230
231 // Main thing is that the number of dofs in each system is the same
234 "The forward and adjoint systems do not seem to be the same size. This could be due to (1) "
235 "the number of variables added to each system is not the same, (2) variables do not have "
236 "consistent family/order, (3) variables do not have the same block restriction.");
237}
virtual libMesh::System & system() override
const std::vector< MooseVariableFieldBase * > & getVariables(THREAD_ID tid)
dof_id_type n_dofs() const
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
bool absolute_fuzzy_equals(const T &var1, const T2 &var2, const Real tol=TOLERANCE *TOLERANCE)

Referenced by solve().

◆ solve()

bool AdjointSolve::solve ( )
overridevirtual

Solve the adjoint system with the following procedure:

  1. Call the _inner_solve
  2. Execute user-objects, auxkernels, and multiapps on ADJOINT_TIMESTEP_BEGIN
  3. Assemble the adjoint system: 3a. Evaluate forward system Jacobian 3b. Evaluate adjoint system residual
  4. Solve adjoint system by calling libMesh::linearSolver::adjoint_solve
  5. Execute user-objects, auxkernels, and multiapps on ADJOINT_TIMESTEP_END
Returns
true Inner solve, multiapps, and adjoint solve all converged
false Inner solve, multiapps, or adjoint solve did not converge

Implements SolveObject.

Reimplemented in AdjointTransientSolve.

Definition at line 75 of file AdjointSolve.C.

76{
77 TIME_SECTION("execute", 1, "Executing adjoint problem", false);
78
79 mooseAssert(!_inner_solve,
80 "I don't see any code path in which this class winds up with an inner solve");
81
82 // enforce PETSc options are passed to the adjoint solve as well, as set in the user file
83 auto & petsc_options = _problem.getPetscOptions();
84 auto & pars = _problem.solverParams(_nl_adjoint.number());
85 Moose::PetscSupport::petscSetOptions(petsc_options, pars);
86
88
90 {
91 _console << "MultiApps failed to converge on ADJOINT_TIMESTEP_BEGIN!" << std::endl;
92 return false;
93 }
94 // Output results between the forward and adjoint solve.
96
98
99 // Convenient references
100 // Adjoint matrix, solution, and right-hand-side
101 auto & matrix = cast_ref<ImplicitSystem &>(_nl_forward.system()).get_system_matrix();
102 auto & solution = _nl_adjoint.solution();
104 // Linear solver parameters
105 auto & es = _problem.es();
106 const auto tol = es.parameters.get<Real>("linear solver tolerance");
107 const auto maxits = es.parameters.get<unsigned int>("linear solver maximum iterations");
108 // Linear solver for adjoint system
109 auto & solver = *cast_ref<ImplicitSystem &>(_nl_adjoint.system()).get_linear_solver();
110
111 // Assemble adjoint system by evaluating the forward Jacobian, computing the adjoint
112 // residual/source, and homogenizing nodal BCs
113 assembleAdjointSystem(matrix, solution, rhs);
114 applyNodalBCs(matrix, solution, rhs);
115
116 // Solve the adjoint system
117 solver.adjoint_solve(matrix, solution, rhs, tol, maxits);
118
119 // The forward Jacobian has its rows scaled by the variable scaling factors S, so the transposed
120 // solve returns mu with (S J)^T mu = -g. The adjoint is therefore lambda = S mu.
121 const auto & dof_map = _nl_forward.dofMap();
122 auto scaling = solution.zero_clone();
123 std::vector<dof_id_type> dof_indices;
124 const auto fill_scaling = [&](const MooseVariableBase & var)
125 {
126 const auto & factors = var.arrayScalingFactor();
127 for (const auto i : make_range(var.count()))
128 {
129 dof_map.local_variable_indices(dof_indices, _mesh.getMesh(), var.number() + i);
130 for (const auto dof : dof_indices)
131 scaling->set(dof, factors[i]);
132 }
133 };
134 for (const auto * const var : _nl_forward.getVariables(0))
135 fill_scaling(*var);
136 for (const auto * const var : _nl_forward.getScalarVariables(0))
137 fill_scaling(*var);
138 scaling->close();
139 solution *= *scaling;
140
141 // Hanging-node (and other DofMap) constraints are not applied by the raw transpose solve above,
142 // which leaves constrained dofs at zero, so back-substitute them here. The vector being
143 // constrained belongs to the adjoint system, not the forward system that owns the matrix.
145
147 if (solver.get_converged_reason() < 0)
148 {
149 _console << "Adjoint solve failed to converge with reason: "
150 << Utility::enum_to_string(solver.get_converged_reason()) << std::endl;
151 return false;
152 }
153
156 {
157 _console << "MultiApps failed to converge on ADJOINT_TIMESTEP_END!" << std::endl;
158 return false;
159 }
160
161 return true;
162}
const double tol
unsigned int count
void applyNodalBCs(SparseMatrix< Number > &matrix, const NumericVector< Number > &solution, NumericVector< Number > &rhs)
Helper function for applying nodal BCs to the adjoint matrix and RHS.
virtual void assembleAdjointSystem(SparseMatrix< Number > &matrix, const NumericVector< Number > &solution, NumericVector< Number > &rhs)
Assembles adjoint system.
void checkIntegrity()
Checks whether the forward and adjoint systems are consistent.
const ConsoleStream _console
virtual libMesh::EquationSystems & es() override
bool execMultiApps(ExecFlagType type, bool auto_advance=true)
virtual void execute(const ExecFlagType &exec_type)
Moose::PetscSupport::PetscOptions & getPetscOptions()
virtual void outputStep(ExecFlagType type)
MeshBase & getMesh()
NumericVector< Number > & getResidualNonTimeVector()
SolveObject * _inner_solve
virtual libMesh::DofMap & dofMap()
NumericVector< Number > & solution()
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
void local_variable_indices(T &idx, const MeshBase &mesh, unsigned int var_num) const
const T & get(std::string_view) const
const DofMap & get_dof_map() const
void petscSetOptions(const PetscOptions &po, const SolverParams &solver_params, FEProblemBase *const problem=nullptr)
const ExecFlagType EXEC_ADJOINT_TIMESTEP_END
const ExecFlagType EXEC_ADJOINT_TIMESTEP_BEGIN
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)

Referenced by SteadyAndAdjoint::execute(), and AdjointTransientSolve::solve().

◆ validParams()

InputParameters AdjointSolve::validParams ( )
static

Definition at line 28 of file AdjointSolve.C.

29{
31 params.addRequiredParam<std::vector<SolverSystemName>>(
32 "forward_system",
33 "Name of the nonlinear system representing the forward problem. Multiple and linear solver "
34 "systems are not currently supported.");
35 params.addRequiredParam<NonlinearSystemName>(
36 "adjoint_system", "Name of the system representing the adjoint problem.");
37 return params;
38}
InputParameters emptyInputParameters()
void addRequiredParam(const std::string &name, const std::string &doc_string)

Referenced by AdjointTransientSolve::validParams(), and SteadyAndAdjoint::validParams().

Member Data Documentation

◆ _adjoint_sys_num

const unsigned int AdjointSolve::_adjoint_sys_num
protected

The number of the nonlinear system representing the adjoint model.

Definition at line 88 of file AdjointSolve.h.

Referenced by assembleAdjointSystem().

◆ _forward_sys_num

const unsigned int AdjointSolve::_forward_sys_num
protected

The number of the nonlinear system representing the forward model.

Definition at line 86 of file AdjointSolve.h.

Referenced by applyNodalBCs(), assembleAdjointSystem(), and AdjointTransientSolve::evaluateTimeResidual().

◆ _nl_adjoint

NonlinearSystemBase& AdjointSolve::_nl_adjoint
protected

◆ _nl_forward

NonlinearSystemBase& AdjointSolve::_nl_forward
protected

The documentation for this class was generated from the following files: