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)
139 std::pair<unsigned int, Real>
143 LOG_SCOPE(
"sensitivity_solve()",
"ImplicitSystem");
163 std::pair<unsigned int, Real> solver_params =
165 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
171 std::pair<unsigned int, Real> rval =
175 double(solver_params.second),
176 solver_params.first);
178 totalrval.first += rval.first;
179 totalrval.second += rval.second;
183 #ifdef LIBMESH_ENABLE_CONSTRAINTS 195 std::pair<unsigned int, Real>
199 LOG_SCOPE(
"adjoint_solve()",
"ImplicitSystem");
216 std::pair<unsigned int, Real> solver_params =
218 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
223 const std::pair<unsigned int, Real> rval =
226 double(solver_params.second),
227 solver_params.first);
229 totalrval.first += rval.first;
230 totalrval.second += rval.second;
234 #ifdef LIBMESH_ENABLE_CONSTRAINTS 246 std::pair<unsigned int, Real>
249 const QoISet & qoi_indices)
252 LOG_SCOPE(
"weighted_sensitivity_adjoint_solve()",
"ImplicitSystem");
268 #ifdef LIBMESH_ENABLE_DIRICHLET 280 std::vector<std::unique_ptr<NumericVector<Number>>> temprhs(this->
n_qois());
298 weights.
deep_copy(parameterperturbation);
299 parameterperturbation *= delta_p;
300 parameters_vec += parameterperturbation;
318 *(temprhs[i]) *= -1.0;
322 parameterperturbation *= -1.0;
323 parameters_vec += parameterperturbation;
338 *(temprhs[i]) /= (2.0*delta_p);
361 std::pair<unsigned int, Real> solver_params =
363 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
368 const std::pair<unsigned int, Real> rval =
371 double(solver_params.second),
372 solver_params.first);
374 totalrval.first += rval.first;
375 totalrval.second += rval.second;
379 #ifdef LIBMESH_ENABLE_CONSTRAINTS 392 std::pair<unsigned int, Real>
397 LOG_SCOPE(
"weighted_sensitivity_solve()",
"ImplicitSystem");
423 weights.
deep_copy(parameterperturbation);
424 parameterperturbation *= delta_p;
425 parameters_vec += parameterperturbation;
430 std::unique_ptr<NumericVector<Number>> temprhs = this->
rhs->
clone();
433 parameterperturbation *= -1.0;
434 parameters_vec += parameterperturbation;
439 *temprhs -= *(this->
rhs);
440 *temprhs /= (2.0*delta_p);
453 std::pair<unsigned int, Real> solver_params =
456 const std::pair<unsigned int, Real> rval =
459 double(solver_params.second),
460 solver_params.first);
463 #ifdef LIBMESH_ENABLE_CONSTRAINTS 479 const unsigned int Np = cast_int<unsigned int>
480 (parameters_vec.
size());
482 for (
unsigned int p=0; p != Np; ++p)
489 Number old_parameter = *parameters_vec[p];
492 TOLERANCE * std::max(std::abs(old_parameter), 1e-3);
494 *parameters_vec[p] -= delta_p;
499 sensitivity_rhs = *this->
rhs;
501 *parameters_vec[p] = old_parameter + delta_p;
507 sensitivity_rhs -= *this->
rhs;
508 sensitivity_rhs /= (2*delta_p);
509 sensitivity_rhs.
close();
511 *parameters_vec[p] = old_parameter;
524 const unsigned int Np = cast_int<unsigned int>
525 (parameters_vec.
size());
526 const unsigned int Nq = this->
n_qois();
549 sensitivities.
allocate_data(qoi_indices, *
this, parameters_vec);
583 for (
unsigned int j=0; j != Np; ++j)
590 Number old_parameter = *parameters_vec[j];
593 TOLERANCE * std::max(std::abs(old_parameter), 1e-3);
595 *parameters_vec[j] = old_parameter - delta_p;
601 *parameters_vec[j] = old_parameter + delta_p;
605 std::vector<Number> partialq_partialp(Nq, 0);
606 for (
unsigned int i=0; i != Nq; ++i)
608 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p);
611 *parameters_vec[j] = old_parameter;
613 for (
unsigned int i=0; i != Nq; ++i)
615 sensitivities[i][j] = partialq_partialp[i] +
616 neg_partialR_partialp.
dot(this->get_adjoint_solution(i));
634 const unsigned int Np = cast_int<unsigned int>
635 (parameters_vec.
size());
636 const unsigned int Nq = this->
n_qois();
654 sensitivities.
allocate_data(qoi_indices, *
this, parameters_vec);
672 for (
unsigned int j=0; j != Np; ++j)
678 Number old_parameter = *parameters_vec[j];
681 TOLERANCE * std::max(std::abs(old_parameter), 1e-3);
683 *parameters_vec[j] = old_parameter - delta_p;
687 *parameters_vec[j] = old_parameter + delta_p;
691 std::vector<Number> partialq_partialp(Nq, 0);
692 for (
unsigned int i=0; i != Nq; ++i)
694 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p);
697 *parameters_vec[j] = old_parameter;
699 for (
unsigned int i=0; i != Nq; ++i)
701 sensitivities[i][j] = partialq_partialp[i] +
729 std::unique_ptr<NumericVector<Number>> tempvec = this->
solution->zero_clone();
731 const unsigned int Np = cast_int<unsigned int>
732 (parameters_vec.
size());
733 const unsigned int Nq = this->
n_qois();
760 sensitivities.
allocate_data(qoi_indices, *
this, parameters_vec);
773 for (
unsigned int k=0; k != Np; ++k)
790 parameterperturbation *= delta_p;
791 parameters_vec += parameterperturbation;
793 Number old_parameter = *parameters_vec[k];
795 *parameters_vec[k] = old_parameter + delta_p;
800 std::vector<Number> partial2R_term(this->
n_qois());
801 for (
unsigned int i=0; i != Nq; ++i)
803 partial2R_term[i] = this->
rhs->
dot(this->get_adjoint_solution(i));
805 *parameters_vec[k] = old_parameter - delta_p;
809 for (
unsigned int i=0; i != Nq; ++i)
817 parameterperturbation *= -1.0;
818 parameters_vec += parameterperturbation;
821 old_parameter = *parameters_vec[k];
823 *parameters_vec[k] = old_parameter + delta_p;
827 for (
unsigned int i=0; i != Nq; ++i)
834 *parameters_vec[k] = old_parameter - delta_p;
838 for (
unsigned int i=0; i != Nq; ++i)
845 for (
unsigned int i=0; i != Nq; ++i)
848 partial2q_term[i] /= (4. * delta_p * delta_p);
849 partial2R_term[i] /= (4. * delta_p * delta_p);
852 for (
unsigned int i=0; i != Nq; ++i)
854 sensitivities[i][k] = partial2q_term[i] - partial2R_term[i];
872 *parameters_vec[k] = old_parameter + delta_p;
882 for (
unsigned int i=0; i != Nq; ++i)
891 *parameters_vec[k] = old_parameter - delta_p;
901 for (
unsigned int i=0; i != Nq; ++i)
933 std::unique_ptr<NumericVector<Number>> tempvec = this->
solution->zero_clone();
937 std::unique_ptr<NumericVector<Number>> oldsolution = this->
solution->clone();
939 const unsigned int Np = cast_int<unsigned int>
940 (parameters_vec.
size());
941 const unsigned int Nq = this->
n_qois();
973 for (
unsigned int k=0; k != Np; ++k)
975 Number old_parameterk = *parameters_vec[k];
981 for (
unsigned int l=0; l != k+1; ++l)
994 Number old_parameterl = *parameters_vec[l];
996 *parameters_vec[k] += delta_p;
997 *parameters_vec[l] += delta_p;
1002 std::vector<Number> partial2R_term(this->
n_qois());
1003 for (
unsigned int i=0; i != Nq; ++i)
1005 partial2R_term[i] = this->
rhs->
dot(this->get_adjoint_solution(i));
1007 *parameters_vec[l] -= 2.*delta_p;
1011 for (
unsigned int i=0; i != Nq; ++i)
1018 *parameters_vec[k] -= 2.*delta_p;
1022 for (
unsigned int i=0; i != Nq; ++i)
1029 *parameters_vec[l] += 2.*delta_p;
1033 for (
unsigned int i=0; i != Nq; ++i)
1038 partial2q_term[i] /= (4. * delta_p * delta_p);
1039 partial2R_term[i] /= (4. * delta_p * delta_p);
1042 for (
unsigned int i=0; i != Nq; ++i)
1045 Number current_terms = partial2q_term[i] - partial2R_term[i];
1052 *parameters_vec[l] = old_parameterl;
1053 *parameters_vec[k] = old_parameterk;
1069 *parameters_vec[k] = old_parameterk + delta_p;
1076 for (
unsigned int l=0; l != Np; ++l)
1079 for (
unsigned int i=0; i != Nq; ++i)
1095 *parameters_vec[k] = old_parameterk - delta_p;
1102 for (
unsigned int l=0; l != Np; ++l)
1105 for (
unsigned int i=0; i != Nq; ++i)
1122 *parameters_vec[k] = old_parameterk;
1152 for (
unsigned int l=0; l != k+1; ++l)
1155 for (
unsigned int i=0; i != Nq; ++i)
1181 for (
unsigned int l=0; l != k+1; ++l)
1184 for (
unsigned int i=0; i != Nq; ++i)
1239 return std::make_pair(
1241 ?
parameters.
get<
unsigned int>(
"linear solver maximum iterations")
1242 : this->get_equation_systems().parameters.get<
unsigned int>(
1243 "linear solver maximum iterations"),
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 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