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)
139std::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
195std::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
246std::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
392std::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)
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)
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")
1243 "linear solver maximum iterations"),
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.
bool has_adjoint_dirichlet_boundaries(unsigned int q) const
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 ...
This is the EquationSystems class.
Parameters parameters
Data structure holding arbitrary parameters.
Manages consistently variables, degrees of freedom, and coefficient vectors for explicit systems.
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...
virtual void clear() override
Clear all the data structures associated with the system.
virtual void assemble_qoi(const QoISet &qoi_indices=QoISet()) override
Prepares qoi for quantity of interest assembly, then calls user qoi function.
NumericVector< Number > * rhs
The system matrix.
virtual void assemble() override
Prepares matrix and rhs for system assembly, then calls user assembly function.
ImplicitSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
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 > 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::pair< unsigned int, Real > get_linear_solve_parameters() const
const SparseMatrix< Number > & get_system_matrix() const
StaticCondensation * _sc_system_matrix
The system matrix for static condensation problems.
void create_static_condensation_system_matrix()
Create the static condensation system matrix.
StaticCondensation & get_static_condensation()
virtual LinearSolver< Number > * get_linear_solver() const
virtual void assemble_residual_derivatives(const ParameterVector ¶meters) override
Residual parameter derivative function.
SparseMatrix< Number > * matrix
The system matrix.
virtual void clear() override
Clear all the data structures associated with the system.
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...
virtual void disable_cache() override
Avoids use of any cached data that might affect any solve result.
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...
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...
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)),...
virtual ~ImplicitSystem()
virtual void create_static_condensation() override
Request that static condensation be performed for this system.
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...
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...
void setup_static_condensation_preconditioner(T &solver)
Sets up the static condensation preconditioner for the supplied solver.
virtual void assembly(bool, bool, bool=false, bool=false)
Assembles a residual in rhs and/or a jacobian in matrix, as requested.
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
virtual void add_matrices() override
Adds the system matrix.
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...
This base class can be inherited from to provide interfaces to linear solvers from different packages...
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 reuse_preconditioner(bool)
Set the same_preconditioner flag, which indicates if we reuse the same preconditioner for subsequent ...
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...
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.
This base class can be inherited from to provide interfaces to nonlinear solvers from different packa...
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
virtual T dot(const NumericVector< T > &v) const =0
virtual bool initialized() const
virtual void zero()=0
Set all entries to zero.
virtual std::unique_ptr< NumericVector< T > > clone() const =0
virtual std::unique_ptr< NumericVector< T > > zero_clone() const =0
const Parallel::Communicator & comm() const
Data structure for specifying which Parameters should be independent variables in a parameter sensiti...
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 value_copy(ParameterVector &target) const
Value copy method: the target, which should already have as many parameters as I do,...
bool have_parameter(std::string_view) const
const T & get(std::string_view) const
Data structure for specifying which Quantities of Interest should be calculated in an adjoint or a pa...
bool has_index(std::size_t) const
Return whether or not this index is in the set to be calculated.
Data structure for holding completed parameter sensitivity calculations.
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.
const Number & second_derivative(unsigned int qoi_index, unsigned int parameter_index1, unsigned int parameter_index2) const
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 close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
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 bool initialized() const
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.
virtual void zero()=0
Set all entries to 0.
virtual void get_transpose(SparseMatrix< T > &dest) const =0
Copies the transpose of the matrix into dest, which may be *this.
StaticCondensationPreconditioner & get_preconditioner()
Get the preconditioning wrapper.
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.
NumericVector< Number > & add_weighted_sensitivity_adjoint_solution(unsigned int i=0)
const SparseMatrix< Number > & get_matrix(std::string_view mat_name) const
bool prefix_with_name() const
NumericVector< Number > & get_weighted_sensitivity_adjoint_solution(unsigned int i=0)
virtual void create_static_condensation()
Request that static condensation be performed for this system.
NumericVector< Number > & add_sensitivity_rhs(unsigned int i=0)
bool assemble_before_solve
Flag which tells the system to whether or not to call the user assembly function during each call to ...
unsigned int n_matrices() const
virtual void assemble()
Prepares matrix and _dof_map for matrix assembly.
Number get_qoi_value(unsigned int qoi_index) const
std::vector< Number > get_qoi_values() const
Returns a copy of qoi, not a reference.
NumericVector< Number > & add_sensitivity_solution(unsigned int i=0)
NumericVector< Number > & get_sensitivity_solution(unsigned int i=0)
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.
unsigned int n_qois() const
Number of currently active quantities of interest.
NumericVector< Number > & get_sensitivity_rhs(unsigned int i=0)
NumericVector< Number > & add_adjoint_solution(unsigned int i=0)
virtual void update()
Update the local values to reflect the solution on neighboring processors.
bool has_static_condensation() const
Parameters parameters
Parameters for the system. If a parameter is not provided, it should be retrieved from the EquationSy...
bool is_adjoint_already_solved() const
Accessor for the adjoint_already_solved boolean.
NumericVector< Number > & get_weighted_sensitivity_solution()
std::string prefix() const
NumericVector< Number > & add_weighted_sensitivity_solution()
const DofMap & get_dof_map() const
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
const EquationSystems & get_equation_systems() const
const MeshBase & get_mesh() const
const SparseMatrix< Number > * request_matrix(std::string_view mat_name) const
NumericVector< Number > & get_adjoint_rhs(unsigned int i=0)
The libMesh namespace provides an interface to certain functionality in the library.
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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...