21 #include "libmesh/dof_map.h" 22 #include "libmesh/equation_systems.h" 23 #include "libmesh/implicit_system.h" 24 #include "libmesh/int_range.h" 25 #include "libmesh/libmesh_logging.h" 26 #include "libmesh/linear_solver.h" 27 #include "libmesh/mesh_base.h" 28 #include "libmesh/numeric_vector.h" 29 #include "libmesh/parameters.h" 30 #include "libmesh/parameter_vector.h" 31 #include "libmesh/qoi_set.h" 32 #include "libmesh/sensitivity_data.h" 33 #include "libmesh/sparse_matrix.h" 34 #include "libmesh/diagonal_matrix.h" 35 #include "libmesh/utility.h" 36 #include "libmesh/static_condensation.h" 37 #include "libmesh/static_condensation_preconditioner.h" 38 #include "libmesh/nonlinear_solver.h" 44 const std::string & name_in,
45 const unsigned int number_in) :
47 Parent (es, name_in, number_in),
49 zero_out_matrix_and_rhs(true)
135 std::pair<unsigned int, Real>
139 LOG_SCOPE(
"sensitivity_solve()",
"ImplicitSystem");
159 std::pair<unsigned int, Real> solver_params =
161 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
167 std::pair<unsigned int, Real> rval =
171 double(solver_params.second),
172 solver_params.first);
174 totalrval.first += rval.first;
175 totalrval.second += rval.second;
179 #ifdef LIBMESH_ENABLE_CONSTRAINTS 191 std::pair<unsigned int, Real>
195 LOG_SCOPE(
"adjoint_solve()",
"ImplicitSystem");
212 std::pair<unsigned int, Real> solver_params =
214 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
219 const std::pair<unsigned int, Real> rval =
222 double(solver_params.second),
223 solver_params.first);
225 totalrval.first += rval.first;
226 totalrval.second += rval.second;
230 #ifdef LIBMESH_ENABLE_CONSTRAINTS 242 std::pair<unsigned int, Real>
245 const QoISet & qoi_indices)
248 LOG_SCOPE(
"weighted_sensitivity_adjoint_solve()",
"ImplicitSystem");
264 #ifdef LIBMESH_ENABLE_DIRICHLET 276 std::vector<std::unique_ptr<NumericVector<Number>>> temprhs(this->
n_qois());
294 weights.
deep_copy(parameterperturbation);
295 parameterperturbation *= delta_p;
296 parameters_vec += parameterperturbation;
314 *(temprhs[i]) *= -1.0;
318 parameterperturbation *= -1.0;
319 parameters_vec += parameterperturbation;
334 *(temprhs[i]) /= (2.0*delta_p);
357 std::pair<unsigned int, Real> solver_params =
359 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
364 const std::pair<unsigned int, Real> rval =
367 double(solver_params.second),
368 solver_params.first);
370 totalrval.first += rval.first;
371 totalrval.second += rval.second;
375 #ifdef LIBMESH_ENABLE_CONSTRAINTS 388 std::pair<unsigned int, Real>
393 LOG_SCOPE(
"weighted_sensitivity_solve()",
"ImplicitSystem");
419 weights.
deep_copy(parameterperturbation);
420 parameterperturbation *= delta_p;
421 parameters_vec += parameterperturbation;
426 std::unique_ptr<NumericVector<Number>> temprhs = this->
rhs->
clone();
429 parameterperturbation *= -1.0;
430 parameters_vec += parameterperturbation;
435 *temprhs -= *(this->
rhs);
436 *temprhs /= (2.0*delta_p);
449 std::pair<unsigned int, Real> solver_params =
452 const std::pair<unsigned int, Real> rval =
455 double(solver_params.second),
456 solver_params.first);
459 #ifdef LIBMESH_ENABLE_CONSTRAINTS 475 const unsigned int Np = cast_int<unsigned int>
476 (parameters_vec.
size());
478 for (
unsigned int p=0; p != Np; ++p)
485 Number old_parameter = *parameters_vec[p];
488 TOLERANCE * std::max(std::abs(old_parameter), 1e-3);
490 *parameters_vec[p] -= delta_p;
495 sensitivity_rhs = *this->
rhs;
497 *parameters_vec[p] = old_parameter + delta_p;
503 sensitivity_rhs -= *this->
rhs;
504 sensitivity_rhs /= (2*delta_p);
505 sensitivity_rhs.
close();
507 *parameters_vec[p] = old_parameter;
520 const unsigned int Np = cast_int<unsigned int>
521 (parameters_vec.
size());
522 const unsigned int Nq = this->
n_qois();
545 sensitivities.
allocate_data(qoi_indices, *
this, parameters_vec);
579 for (
unsigned int j=0; j != Np; ++j)
586 Number old_parameter = *parameters_vec[j];
589 TOLERANCE * std::max(std::abs(old_parameter), 1e-3);
591 *parameters_vec[j] = old_parameter - delta_p;
597 *parameters_vec[j] = old_parameter + delta_p;
601 std::vector<Number> partialq_partialp(Nq, 0);
602 for (
unsigned int i=0; i != Nq; ++i)
604 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p);
607 *parameters_vec[j] = old_parameter;
609 for (
unsigned int i=0; i != Nq; ++i)
611 sensitivities[i][j] = partialq_partialp[i] +
612 neg_partialR_partialp.
dot(this->get_adjoint_solution(i));
630 const unsigned int Np = cast_int<unsigned int>
631 (parameters_vec.
size());
632 const unsigned int Nq = this->
n_qois();
650 sensitivities.
allocate_data(qoi_indices, *
this, parameters_vec);
668 for (
unsigned int j=0; j != Np; ++j)
674 Number old_parameter = *parameters_vec[j];
677 TOLERANCE * std::max(std::abs(old_parameter), 1e-3);
679 *parameters_vec[j] = old_parameter - delta_p;
683 *parameters_vec[j] = old_parameter + delta_p;
687 std::vector<Number> partialq_partialp(Nq, 0);
688 for (
unsigned int i=0; i != Nq; ++i)
690 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p);
693 *parameters_vec[j] = old_parameter;
695 for (
unsigned int i=0; i != Nq; ++i)
697 sensitivities[i][j] = partialq_partialp[i] +
725 std::unique_ptr<NumericVector<Number>> tempvec = this->
solution->zero_clone();
727 const unsigned int Np = cast_int<unsigned int>
728 (parameters_vec.
size());
729 const unsigned int Nq = this->
n_qois();
756 sensitivities.
allocate_data(qoi_indices, *
this, parameters_vec);
769 for (
unsigned int k=0; k != Np; ++k)
786 parameterperturbation *= delta_p;
787 parameters_vec += parameterperturbation;
789 Number old_parameter = *parameters_vec[k];
791 *parameters_vec[k] = old_parameter + delta_p;
796 std::vector<Number> partial2R_term(this->
n_qois());
797 for (
unsigned int i=0; i != Nq; ++i)
799 partial2R_term[i] = this->
rhs->
dot(this->get_adjoint_solution(i));
801 *parameters_vec[k] = old_parameter - delta_p;
805 for (
unsigned int i=0; i != Nq; ++i)
813 parameterperturbation *= -1.0;
814 parameters_vec += parameterperturbation;
817 old_parameter = *parameters_vec[k];
819 *parameters_vec[k] = old_parameter + delta_p;
823 for (
unsigned int i=0; i != Nq; ++i)
830 *parameters_vec[k] = old_parameter - delta_p;
834 for (
unsigned int i=0; i != Nq; ++i)
841 for (
unsigned int i=0; i != Nq; ++i)
844 partial2q_term[i] /= (4. * delta_p * delta_p);
845 partial2R_term[i] /= (4. * delta_p * delta_p);
848 for (
unsigned int i=0; i != Nq; ++i)
850 sensitivities[i][k] = partial2q_term[i] - partial2R_term[i];
868 *parameters_vec[k] = old_parameter + delta_p;
878 for (
unsigned int i=0; i != Nq; ++i)
887 *parameters_vec[k] = old_parameter - delta_p;
897 for (
unsigned int i=0; i != Nq; ++i)
929 std::unique_ptr<NumericVector<Number>> tempvec = this->
solution->zero_clone();
933 std::unique_ptr<NumericVector<Number>> oldsolution = this->
solution->clone();
935 const unsigned int Np = cast_int<unsigned int>
936 (parameters_vec.
size());
937 const unsigned int Nq = this->
n_qois();
969 for (
unsigned int k=0; k != Np; ++k)
971 Number old_parameterk = *parameters_vec[k];
977 for (
unsigned int l=0; l != k+1; ++l)
990 Number old_parameterl = *parameters_vec[l];
992 *parameters_vec[k] += delta_p;
993 *parameters_vec[l] += delta_p;
998 std::vector<Number> partial2R_term(this->
n_qois());
999 for (
unsigned int i=0; i != Nq; ++i)
1001 partial2R_term[i] = this->
rhs->
dot(this->get_adjoint_solution(i));
1003 *parameters_vec[l] -= 2.*delta_p;
1007 for (
unsigned int i=0; i != Nq; ++i)
1014 *parameters_vec[k] -= 2.*delta_p;
1018 for (
unsigned int i=0; i != Nq; ++i)
1025 *parameters_vec[l] += 2.*delta_p;
1029 for (
unsigned int i=0; i != Nq; ++i)
1034 partial2q_term[i] /= (4. * delta_p * delta_p);
1035 partial2R_term[i] /= (4. * delta_p * delta_p);
1038 for (
unsigned int i=0; i != Nq; ++i)
1041 Number current_terms = partial2q_term[i] - partial2R_term[i];
1048 *parameters_vec[l] = old_parameterl;
1049 *parameters_vec[k] = old_parameterk;
1065 *parameters_vec[k] = old_parameterk + delta_p;
1072 for (
unsigned int l=0; l != Np; ++l)
1075 for (
unsigned int i=0; i != Nq; ++i)
1091 *parameters_vec[k] = old_parameterk - delta_p;
1098 for (
unsigned int l=0; l != Np; ++l)
1101 for (
unsigned int i=0; i != Nq; ++i)
1118 *parameters_vec[k] = old_parameterk;
1148 for (
unsigned int l=0; l != k+1; ++l)
1151 for (
unsigned int i=0; i != Nq; ++i)
1177 for (
unsigned int l=0; l != k+1; ++l)
1180 for (
unsigned int i=0; i != Nq; ++i)
1235 return std::make_pair(
1237 ?
parameters.
get<
unsigned int>(
"linear solver maximum iterations")
1238 : this->get_equation_systems().parameters.get<
unsigned int>(
1239 "linear solver maximum iterations"),
1247 #ifdef LIBMESH_ENABLE_DEPRECATED 1255 libmesh_deprecated();
1257 #endif // LIBMESH_ENABLE_DEPRECATED virtual bool initialized() const
This is the EquationSystems class.
virtual void qoi_parameter_hessian_vector_product(const QoISet &qoi_indices, const ParameterVector ¶meters, const ParameterVector &vector, SensitivityData &product) override
For each of the system's quantities of interest q in qoi[qoi_indices], and for a vector of parameters...
bool have_parameter(std::string_view) const
virtual void create_static_condensation()
Request that static condensation be performed for this system.
void deep_copy(ParameterVector &target) const
Deep copy constructor: the target will now own new copies of all the parameter values I'm pointing to...
void create_static_condensation_system_matrix()
Create the static condensation system matrix.
NumericVector< Number > & add_adjoint_solution(unsigned int i=0)
Data structure for specifying which Parameters should be independent variables in a parameter sensiti...
static std::unique_ptr< LinearSolver< T > > build(const libMesh::Parallel::Communicator &comm_in, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a LinearSolver using the linear solver package specified by solver_package.
virtual void create_static_condensation() override
Request that static condensation be performed for this system.
static constexpr Real TOLERANCE
void vector_mult(NumericVector< T > &dest, const NumericVector< T > &arg) const
Multiplies the matrix by the NumericVector arg and stores the result in NumericVector dest...
virtual std::pair< unsigned int, Real > get_linear_solve_parameters() const
Data structure for specifying which Quantities of Interest should be calculated in an adjoint or a pa...
Number get_qoi_value(unsigned int qoi_index) const
void allocate_hessian_data(const QoISet &qoi_indices, const System &sys, const ParameterVector ¶meter_vector)
Given QoISet and ParameterVector, allocates space for all required second derivative data...
unsigned int n_qois() const
Number of currently active quantities of interest.
virtual bool initialized() const
virtual std::pair< unsigned int, Real > weighted_sensitivity_solve(const ParameterVector ¶meters, const ParameterVector &weights) override
Assembles & solves the linear system(s) (dR/du)*u_w = sum(w_p*-dR/dp), for those parameters p contain...
virtual std::unique_ptr< NumericVector< T > > zero_clone() const =0
NumericVector< Number > & get_sensitivity_solution(unsigned int i=0)
NumericVector< Number > & get_sensitivity_rhs(unsigned int i=0)
const EquationSystems & get_equation_systems() const
virtual void assemble()
Prepares matrix and _dof_map for matrix assembly.
virtual void clear() override
Clear all the data structures associated with the system.
NumericVector< Number > * rhs
The system matrix.
virtual ~ImplicitSystem()
const Parallel::Communicator & comm() const
virtual std::unique_ptr< NumericVector< T > > clone() const =0
virtual LinearSolver< Number > * get_linear_solver() const
virtual std::pair< unsigned int, Real > sensitivity_solve(const ParameterVector ¶meters) override
Assembles & solves the linear system(s) (dR/du)*u_p = -dR/dp, for those parameters contained within p...
NumericVector< Number > & add_sensitivity_rhs(unsigned int i=0)
bool has_static_condensation() const
The libMesh namespace provides an interface to certain functionality in the library.
virtual T dot(const NumericVector< T > &v) const =0
bool zero_out_matrix_and_rhs
By default, the system will zero out the matrix and the right hand side.
virtual std::pair< unsigned int, Real > adjoint_solve(const QoISet &qoi_indices=QoISet()) override
Assembles & solves the linear system (dR/du)^T*z = dq/du, for those quantities of interest q specifie...
StaticCondensation * _sc_system_matrix
The system matrix for static condensation problems.
NumericVector< Number > & add_weighted_sensitivity_solution()
const SparseMatrix< Number > * request_matrix(std::string_view mat_name) const
Parameters parameters
Parameters for the system. If a parameter is not provided, it should be retrieved from the EquationSy...
const MeshBase & get_mesh() const
void setup_static_condensation_preconditioner(T &solver)
Sets up the static condensation preconditioner for the supplied solver.
NumericVector< Number > & get_weighted_sensitivity_solution()
virtual void release_linear_solver(LinearSolver< Number > *) const
Currently a no-op.
virtual void zero()=0
Set all entries to zero.
void enforce_adjoint_constraints_exactly(NumericVector< Number > &v, unsigned int q) const
Heterogeneously constrains the numeric vector v, which represents an adjoint solution defined on the ...
NumericVector< Number > & add_weighted_sensitivity_adjoint_solution(unsigned int i=0)
virtual void forward_qoi_parameter_sensitivity(const QoISet &qoi_indices, const ParameterVector ¶meters, SensitivityData &sensitivities) override
Solves for the derivative of each of the system's quantities of interest q in qoi[qoi_indices] with r...
bool has_index(std::size_t) const
Return whether or not this index is in the set to be calculated.
void allocate_data(const QoISet &qoi_indices, const System &sys, const ParameterVector ¶meter_vector)
Given QoISet and ParameterVector, allocates space for all required first derivative data...
virtual void assembly(bool, bool, bool=false, bool=false)
Assembles a residual in rhs and/or a jacobian in matrix, as requested.
const T & get(std::string_view) const
virtual void zero()=0
Set all entries to 0.
bool has_adjoint_dirichlet_boundaries(unsigned int q) const
Data structure for holding completed parameter sensitivity calculations.
StaticCondensationDofMap & get_static_condensation()
std::string prefix() const
virtual void adjoint_qoi_parameter_sensitivity(const QoISet &qoi_indices, const ParameterVector ¶meters, SensitivityData &sensitivities) override
Solves for the derivative of each of the system's quantities of interest q in qoi[qoi_indices] with r...
Manages consistently variables, degrees of freedom, and coefficient vectors.
virtual void add_matrices()
Insertion point for adding matrices in derived classes before init_matrices() is called.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
virtual void disable_cache() override
Avoids use of any cached data that might affect any solve result.
virtual std::pair< unsigned int, Real > solve(SparseMatrix< T > &, NumericVector< T > &, NumericVector< T > &, const std::optional< double > tol=std::nullopt, const std::optional< unsigned int > m_its=std::nullopt)=0
This function calls the solver _solver_type preconditioned with the _preconditioner_type precondition...
unsigned int n_matrices() const
bool is_adjoint_already_solved() const
Accessor for the adjoint_already_solved boolean.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
virtual void clear() override
Clear all the data structures associated with the system.
ImplicitSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
virtual void update()
Update the local values to reflect the solution on neighboring processors.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void add_matrices() override
Adds the system matrix.
virtual void reuse_preconditioner(bool)
Set the same_preconditioner flag, which indicates if we reuse the same preconditioner for subsequent ...
void vector_mult_add(NumericVector< T > &dest, const NumericVector< T > &arg) const
Multiplies the matrix by the NumericVector arg and adds the result to the NumericVector dest...
const Number & second_derivative(unsigned int qoi_index, unsigned int parameter_index1, unsigned int parameter_index2) const
SparseMatrix< Number > * matrix
The system matrix.
virtual void get_transpose(SparseMatrix< T > &dest) const =0
Copies the transpose of the matrix into dest, which may be *this.
virtual void assemble_qoi(const QoISet &qoi_indices=QoISet()) override
Prepares qoi for quantity of interest assembly, then calls user qoi function.
virtual void assemble_residual_derivatives(const ParameterVector ¶meters) override
Residual parameter derivative function.
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
virtual void assemble_qoi_derivative(const QoISet &qoi_indices=QoISet(), bool include_liftfunc=true, bool apply_constraints=true) override
Prepares adjoint_rhs for quantity of interest derivative assembly, then calls user qoi derivative fun...
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
Parameters parameters
Data structure holding arbitrary parameters.
virtual void assemble() override
Prepares matrix and rhs for system assembly, then calls user assembly function.
NumericVector< Number > & add_sensitivity_solution(unsigned int i=0)
virtual std::pair< unsigned int, Real > adjoint_solve(SparseMatrix< T > &, NumericVector< T > &, NumericVector< T > &, const std::optional< double > tol=std::nullopt, const std::optional< unsigned int > m_its=std::nullopt)
Function to solve the adjoint system.
bool assemble_before_solve
Flag which tells the system to whether or not to call the user assembly function during each call to ...
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
SparseMatrix< Number > & add_matrix(std::string_view mat_name, ParallelType type=PARALLEL, MatrixBuildType mat_build_type=MatrixBuildType::AUTOMATIC)
Adds the additional matrix mat_name to this system.
const DofMap & get_dof_map() const
virtual void qoi_parameter_hessian(const QoISet &qoi_indices, const ParameterVector ¶meters, SensitivityData &hessian) override
For each of the system's quantities of interest q in qoi[qoi_indices], and for a vector of parameters...
const SparseMatrix< Number > & get_matrix(std::string_view mat_name) const
virtual std::pair< unsigned int, Real > weighted_sensitivity_adjoint_solve(const ParameterVector ¶meters, const ParameterVector &weights, const QoISet &qoi_indices=QoISet()) override
Assembles & solves the linear system(s) (dR/du)^T*z_w = sum(w_p*(d^2q/dudp - d^2R/dudp*z)), for those parameters p contained within parameters, weighted by the values w_p found within weights.
const SparseMatrix< Number > & get_system_matrix() const
void value_copy(ParameterVector &target) const
Value copy method: the target, which should already have as many parameters as I do, will now have those parameters set to my values.
StaticCondensationPreconditioner & get_preconditioner()
Get the preconditioning wrapper.
NumericVector< Number > & get_weighted_sensitivity_adjoint_solution(unsigned int i=0)
std::vector< Number > get_qoi_values() const
Returns a copy of qoi, not a reference.
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
Constrains the numeric vector v, which represents a solution defined on the mesh. ...
NumericVector< Number > & get_adjoint_rhs(unsigned int i=0)
bool prefix_with_name() const