Go to the documentation of this file.
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/utility.h"
42 const std::string & name_in,
43 const unsigned int number_in) :
45 Parent (es, name_in, number_in),
47 zero_out_matrix_and_rhs(true),
48 _can_add_matrices (true)
161 pr.second->attach_dof_map (dof_map);
206 libmesh_error_msg(
"ERROR: Too late. Cannot add matrices to the system after initialization"
207 <<
"\n any more. You should have done this earlier.");
215 _matrices.insert (std::make_pair (mat_name, buf));
264 return *(libmesh_map_find(
_matrices, mat_name));
271 return *(libmesh_map_find(
_matrices, mat_name));
300 std::pair<unsigned int, Real>
304 LOG_SCOPE(
"sensitivity_solve()",
"ImplicitSystem");
324 std::pair<unsigned int, Real> solver_params =
326 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
332 std::pair<unsigned int, Real> rval =
336 double(solver_params.second),
337 solver_params.first);
339 totalrval.first += rval.first;
340 totalrval.second += rval.second;
344 #ifdef LIBMESH_ENABLE_CONSTRAINTS
358 std::pair<unsigned int, Real>
362 LOG_SCOPE(
"adjoint_solve()",
"ImplicitSystem");
379 std::pair<unsigned int, Real> solver_params =
381 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
386 const std::pair<unsigned int, Real> rval =
389 double(solver_params.second),
390 solver_params.first);
392 totalrval.first += rval.first;
393 totalrval.second += rval.second;
399 #ifdef LIBMESH_ENABLE_CONSTRAINTS
411 std::pair<unsigned int, Real>
414 const QoISet & qoi_indices)
417 LOG_SCOPE(
"weighted_sensitivity_adjoint_solve()",
"ImplicitSystem");
423 const_cast<ParameterVector &>(parameters_in);
433 #ifdef LIBMESH_ENABLE_DIRICHLET
445 std::vector<std::unique_ptr<NumericVector<Number>>> temprhs(this->
n_qois());
463 weights.
deep_copy(parameterperturbation);
464 parameterperturbation *= delta_p;
465 parameters += parameterperturbation;
483 *(temprhs[i]) *= -1.0;
487 parameterperturbation *= -1.0;
488 parameters += parameterperturbation;
503 *(temprhs[i]) /= (2.0*delta_p);
526 std::pair<unsigned int, Real> solver_params =
528 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0);
533 const std::pair<unsigned int, Real> rval =
536 double(solver_params.second),
537 solver_params.first);
539 totalrval.first += rval.first;
540 totalrval.second += rval.second;
546 #ifdef LIBMESH_ENABLE_CONSTRAINTS
559 std::pair<unsigned int, Real>
564 LOG_SCOPE(
"weighted_sensitivity_solve()",
"ImplicitSystem");
570 const_cast<ParameterVector &>(parameters_in);
590 weights.
deep_copy(parameterperturbation);
591 parameterperturbation *= delta_p;
592 parameters += parameterperturbation;
597 std::unique_ptr<NumericVector<Number>> temprhs = this->
rhs->
clone();
600 parameterperturbation *= -1.0;
601 parameters += parameterperturbation;
606 *temprhs -= *(this->
rhs);
607 *temprhs /= (2.0*delta_p);
620 std::pair<unsigned int, Real> solver_params =
623 const std::pair<unsigned int, Real> rval =
626 double(solver_params.second),
627 solver_params.first);
632 #ifdef LIBMESH_ENABLE_CONSTRAINTS
646 const_cast<ParameterVector &>(parameters_in);
648 const unsigned int Np = cast_int<unsigned int>
651 for (
unsigned int p=0; p != Np; ++p)
658 Number old_parameter = *parameters[p];
663 *parameters[p] -= delta_p;
668 sensitivity_rhs = *this->
rhs;
670 *parameters[p] = old_parameter + delta_p;
676 sensitivity_rhs -= *this->
rhs;
677 sensitivity_rhs /= (2*delta_p);
678 sensitivity_rhs.
close();
680 *parameters[p] = old_parameter;
691 const_cast<ParameterVector &>(parameters_in);
693 const unsigned int Np = cast_int<unsigned int>
695 const unsigned int Nq = this->
n_qois();
752 for (
unsigned int j=0; j != Np; ++j)
759 Number old_parameter = *parameters[j];
764 *parameters[j] = old_parameter - delta_p;
766 std::vector<Number> qoi_minus = this->
qoi;
770 *parameters[j] = old_parameter + delta_p;
772 std::vector<Number> & qoi_plus = this->
qoi;
774 std::vector<Number> partialq_partialp(Nq, 0);
775 for (
unsigned int i=0; i != Nq; ++i)
777 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p);
780 *parameters[j] = old_parameter;
782 for (
unsigned int i=0; i != Nq; ++i)
784 sensitivities[i][j] = partialq_partialp[i] +
785 neg_partialR_partialp.
dot(this->get_adjoint_solution(i));
801 const_cast<ParameterVector &>(parameters_in);
803 const unsigned int Np = cast_int<unsigned int>
805 const unsigned int Nq = this->
n_qois();
841 for (
unsigned int j=0; j != Np; ++j)
847 Number old_parameter = *parameters[j];
852 *parameters[j] = old_parameter - delta_p;
854 std::vector<Number> qoi_minus = this->
qoi;
856 *parameters[j] = old_parameter + delta_p;
858 std::vector<Number> & qoi_plus = this->
qoi;
860 std::vector<Number> partialq_partialp(Nq, 0);
861 for (
unsigned int i=0; i != Nq; ++i)
863 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p);
866 *parameters[j] = old_parameter;
868 for (
unsigned int i=0; i != Nq; ++i)
870 sensitivities[i][j] = partialq_partialp[i] +
895 const_cast<ParameterVector &>(parameters_in);
898 std::unique_ptr<NumericVector<Number>> tempvec = this->
solution->zero_clone();
900 const unsigned int Np = cast_int<unsigned int>
902 const unsigned int Nq = this->
n_qois();
942 for (
unsigned int k=0; k != Np; ++k)
959 parameterperturbation *= delta_p;
960 parameters += parameterperturbation;
962 Number old_parameter = *parameters[k];
964 *parameters[k] = old_parameter + delta_p;
968 std::vector<Number> partial2q_term = this->
qoi;
969 std::vector<Number> partial2R_term(this->
n_qois());
970 for (
unsigned int i=0; i != Nq; ++i)
972 partial2R_term[i] = this->
rhs->
dot(this->get_adjoint_solution(i));
974 *parameters[k] = old_parameter - delta_p;
978 for (
unsigned int i=0; i != Nq; ++i)
981 partial2q_term[i] -= this->
qoi[i];
986 parameterperturbation *= -1.0;
987 parameters += parameterperturbation;
990 old_parameter = *parameters[k];
992 *parameters[k] = old_parameter + delta_p;
996 for (
unsigned int i=0; i != Nq; ++i)
999 partial2q_term[i] -= this->
qoi[i];
1003 *parameters[k] = old_parameter - delta_p;
1007 for (
unsigned int i=0; i != Nq; ++i)
1010 partial2q_term[i] += this->
qoi[i];
1014 for (
unsigned int i=0; i != Nq; ++i)
1017 partial2q_term[i] /= (4. * delta_p * delta_p);
1018 partial2R_term[i] /= (4. * delta_p * delta_p);
1021 for (
unsigned int i=0; i != Nq; ++i)
1023 sensitivities[i][k] = partial2q_term[i] - partial2R_term[i];
1041 *parameters[k] = old_parameter + delta_p;
1051 for (
unsigned int i=0; i != Nq; ++i)
1060 *parameters[k] = old_parameter - delta_p;
1070 for (
unsigned int i=0; i != Nq; ++i)
1099 const_cast<ParameterVector &>(parameters_in);
1102 std::unique_ptr<NumericVector<Number>> tempvec = this->
solution->zero_clone();
1106 std::unique_ptr<NumericVector<Number>> oldsolution = this->
solution->clone();
1108 const unsigned int Np = cast_int<unsigned int>
1109 (parameters.
size());
1110 const unsigned int Nq = this->
n_qois();
1142 for (
unsigned int k=0; k != Np; ++k)
1144 Number old_parameterk = *parameters[k];
1150 for (
unsigned int l=0; l != k+1; ++l)
1163 Number old_parameterl = *parameters[l];
1165 *parameters[k] += delta_p;
1166 *parameters[l] += delta_p;
1170 std::vector<Number> partial2q_term = this->
qoi;
1171 std::vector<Number> partial2R_term(this->
n_qois());
1172 for (
unsigned int i=0; i != Nq; ++i)
1174 partial2R_term[i] = this->
rhs->
dot(this->get_adjoint_solution(i));
1176 *parameters[l] -= 2.*delta_p;
1180 for (
unsigned int i=0; i != Nq; ++i)
1183 partial2q_term[i] -= this->
qoi[i];
1187 *parameters[k] -= 2.*delta_p;
1191 for (
unsigned int i=0; i != Nq; ++i)
1194 partial2q_term[i] += this->
qoi[i];
1198 *parameters[l] += 2.*delta_p;
1202 for (
unsigned int i=0; i != Nq; ++i)
1205 partial2q_term[i] -= this->
qoi[i];
1207 partial2q_term[i] /= (4. * delta_p * delta_p);
1208 partial2R_term[i] /= (4. * delta_p * delta_p);
1211 for (
unsigned int i=0; i != Nq; ++i)
1214 Number current_terms = partial2q_term[i] - partial2R_term[i];
1221 *parameters[l] = old_parameterl;
1222 *parameters[k] = old_parameterk;
1238 *parameters[k] = old_parameterk + delta_p;
1245 for (
unsigned int l=0; l != Np; ++l)
1248 for (
unsigned int i=0; i != Nq; ++i)
1264 *parameters[k] = old_parameterk - delta_p;
1271 for (
unsigned int l=0; l != Np; ++l)
1274 for (
unsigned int i=0; i != Nq; ++i)
1291 *parameters[k] = old_parameterk;
1321 for (
unsigned int l=0; l != k+1; ++l)
1324 for (
unsigned int i=0; i != Nq; ++i)
1350 for (
unsigned int l=0; l != k+1; ++l)
1353 for (
unsigned int i=0; i != Nq; ++i)
1391 libmesh_deprecated();
1401 new_solver->
init((this->
name()+
"_").c_str());
1412 return std::make_pair(this->
get_equation_systems().parameters.get<
unsigned int>(
"linear solver maximum iterations"),
1421 libmesh_deprecated();
virtual void reuse_preconditioner(bool)
Set the same_preconditioner flag, which indicates if we reuse the same preconditioner for subsequent ...
virtual void assemble_residual_derivatives(const ParameterVector ¶meters) override
Residual parameter derivative function.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
Manages consistently variables, degrees of freedom, and coefficient vectors.
const SparseMatrix< Number > * request_matrix(const std::string &mat_name) const
virtual void zero()=0
Set all entries to zero.
void compute_sparsity(const MeshBase &)
Computes the sparsity pattern for the matrices corresponding to proc_id and sends that data to Linear...
const EquationSystems & get_equation_systems() const
bool is_attached(SparseMatrix< Number > &matrix)
Matrices should not be attached more than once.
virtual void reinit()
Reinitializes degrees of freedom and other required data on the current mesh.
NumericVector< Number > & get_sensitivity_rhs(unsigned int i=0)
NumericVector< Number > * rhs
The system matrix.
virtual std::pair< unsigned int, Real > get_linear_solve_parameters() const
NumericVector< Number > & add_adjoint_solution(unsigned int i=0)
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 > solve(SparseMatrix< T > &, NumericVector< T > &, NumericVector< T > &, const double, const unsigned int)=0
This function calls the solver _solver_type preconditioned with the _preconditioner_type precondition...
bool has_index(std::size_t) const
Return whether or not this index is in the set to be calculated.
bool has_adjoint_dirichlet_boundaries(unsigned int q) const
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
NumericVector< Number > & get_weighted_sensitivity_adjoint_solution(unsigned int i=0)
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 void reinit() override
Reinitializes the member data fields associated with the system, so that, e.g., assemble() may be use...
The libMesh namespace provides an interface to certain functionality in the library.
NumericVector< Number > & add_sensitivity_solution(unsigned int i=0)
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
virtual bool initialized() const
SparseMatrix< Number > & add_matrix(const std::string &mat_name)
Adds the additional matrix mat_name to this system.
virtual void assemble() override
Prepares matrix and rhs for system assembly, then calls user assembly function.
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.
static const Real TOLERANCE
std::map< std::string, SparseMatrix< Number > * > _matrices
Some systems need an arbitrary number of matrices.
const Parallel::Communicator & comm() const
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...
NumericVector< Number > & get_adjoint_rhs(unsigned int i=0)
Data structure for holding completed parameter sensitivity calculations.
virtual std::unique_ptr< NumericVector< T > > clone() const =0
virtual LinearSolver< Number > * get_linear_solver() const
void value_copy(ParameterVector &target) const
Value copy method: the target, which should already have as many parameters as I do,...
bool is_adjoint_already_solved() const
Accessor for the adjoint_already_solved boolean.
virtual void init(const char *name=nullptr)=0
Initialize data structures if not done so already.
std::map< std::string, SparseMatrix< Number > * >::const_iterator const_matrices_iterator
NumericVector< Number > & get_weighted_sensitivity_solution()
virtual void assemble()
Prepares matrix and _dof_map for matrix assembly.
unsigned int n_qois() const
Number of currently active quantities of interest.
void enforce_adjoint_constraints_exactly(NumericVector< Number > &v, unsigned int q) const
Heterogenously constrains the numeric vector v, which represents an adjoint solution defined on the m...
bool assemble_before_solve
Flag which tells the system to whether or not to call the user assembly function during each call to ...
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...
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
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 ~ImplicitSystem()
Destructor.
MetaPhysicL::DualNumber< T, D > abs(const MetaPhysicL::DualNumber< T, D > &in)
std::vector< Number > qoi
Values of the quantities of interest.
Data structure for specifying which Quantities of Interest should be calculated in an adjoint or a pa...
virtual void clear() override
Clear all the data structures associated with the system.
virtual bool initialized() const
bool _can_add_matrices
true when additional matrices may still be added, false otherwise.
virtual void assembly(bool, bool, bool=false, bool=false)
Assembles a residual in rhs and/or a jacobian in matrix, as requested.
const MeshBase & get_mesh() const
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.
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...
NumericVector< Number > & get_sensitivity_solution(unsigned int i=0)
virtual void init_matrices()
Initializes the matrices associated with this system.
SparseMatrix< Number > * matrix
The system matrix.
Data structure for specifying which Parameters should be independent variables in a parameter sensiti...
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 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...
bool have_matrix(const std::string &mat_name) const
virtual void assemble_qoi(const QoISet &qoi_indices=QoISet()) override
Prepares qoi for quantity of interest assembly, then calls user qoi function.
std::map< std::string, SparseMatrix< Number > * >::iterator matrices_iterator
Matrix iterator typedefs.
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.
virtual void release_linear_solver(LinearSolver< Number > *) const
Releases a pointer to a linear solver acquired by this->get_linear_solver()
This is the EquationSystems class.
void attach_matrix(SparseMatrix< Number > &matrix)
Additional matrices may be handled with this DofMap.
virtual std::pair< unsigned int, Real > adjoint_solve(SparseMatrix< T > &, NumericVector< T > &, NumericVector< T > &, const double, const unsigned int)
Function to solve the adjoint system.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
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...
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
ImplicitSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
This class handles the numbering of degrees of freedom on a mesh.
const std::string & name() const
void clear_sparsity()
Clears the sparsity pattern.
virtual void init_data()
Initializes the data for the system.
const Number & second_derivative(unsigned int qoi_index, unsigned int parameter_index1, unsigned int parameter_index2) const
void remove_matrix(const std::string &mat_name)
Removes the additional matrix mat_name from this system.
bool on_command_line(std::string arg)
virtual void clear() override
Clear all the data structures associated with the system.
const DofMap & get_dof_map() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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...
virtual void get_transpose(SparseMatrix< T > &dest) const =0
Copies the transpose of the matrix into dest, which may be *this.
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)),...
bool zero_out_matrix_and_rhs
By default, the system will zero out the matrix and the right hand side.
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
NumericVector< Number > & add_weighted_sensitivity_solution()
NumericVector< Number > & add_weighted_sensitivity_adjoint_solution(unsigned int i=0)
const T & get(const std::string &) const
const SparseMatrix< Number > & get_matrix(const std::string &mat_name) const
void add_system_matrix()
Add the system matrix to the _matrices data structure.
virtual void update()
Update the local values to reflect the solution on neighboring processors.
virtual void zero()=0
Set all entries to 0.
NumericVector< Number > & add_sensitivity_rhs(unsigned int i=0)
virtual std::unique_ptr< NumericVector< T > > zero_clone() const =0
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...
virtual T dot(const NumericVector< T > &v) const =0
virtual void disable_cache() override
Avoids use of any cached data that might affect any solve result.
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...
Parameters parameters
Data structure holding arbitrary parameters.