PolyFEM
Loading...
Searching...
No Matches
AdjointForm.cpp
Go to the documentation of this file.
2
11
12#include <Eigen/Core>
13
14#include <algorithm>
15#include <cassert>
16#include <memory>
17#include <string>
18
19namespace polyfem::solver
20{
22 std::shared_ptr<const varform::DifferentiableVarForm> varform,
23 std::shared_ptr<const DiffCache> diff_cache, const json &args)
24 : AdjointForm(variables),
25 varform_(std::move(varform)),
26 diff_cache_(std::move(diff_cache)),
27 dimensions_(args["dimensions"].get<std::vector<int>>())
28 {
29 }
30
31 double HomogenizedDispGradForm::value_unweighted(const Eigen::VectorXd &variables) const
32 {
33 return diff_cache_->disp_grad()(dimensions_[0], dimensions_[1]);
34 }
35
36 Eigen::MatrixXd HomogenizedDispGradForm::compute_reduced_adjoint_rhs(const Eigen::VectorXd &variables,
37 const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
38 {
39 if (&varform != varform_.get())
40 {
41 return AdjointForm::compute_reduced_adjoint_rhs(variables, varform, diff_cache);
42 }
43
44 const auto problem = std::static_pointer_cast<NLHomoProblem>(varform.solve_data()->nl_problem);
45 const int dimension = varform.get_mesh().dimension();
46 // Differentiate G_ij in extended coordinates, then apply the symmetry and fixed-component reduction.
47 Eigen::VectorXd extended = Eigen::VectorXd::Zero(problem->full_size() + dimension * dimension);
48 extended(problem->full_size() + dimensions_[0] + dimension * dimensions_[1]) = weight();
49 return problem->extended_to_reduced_grad(extended);
50 }
51
52 double AdjointForm::value(const Eigen::VectorXd &x) const
53 {
54 double val = Form::value(x);
56 {
57 adjoint_logger().debug("[{}] {}", print_energy_keyword_, val);
59 }
60 return val;
61 }
62
63 void AdjointForm::enable_energy_print(const std::string &print_energy_keyword)
64 {
65 print_energy_keyword_ = print_energy_keyword;
67 }
68
74
75 void AdjointForm::second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const
76 {
77 log_and_throw_adjoint_error("[{}] Second derivatives not implemented", name());
78 }
79
80 Eigen::MatrixXd AdjointForm::compute_reduced_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
81 {
82 Eigen::MatrixXd rhs = compute_adjoint_rhs(x, varform, diff_cache);
83 // Only for homogenization
84 if (!varform.get_problem().is_time_dependent() && varform.is_homogenization() && varform.solve_data()->nl_problem) // nonlinear static solve only
85 {
86 Eigen::MatrixXd reduced;
87 for (int i = 0; i < rhs.cols(); i++)
88 {
89 Eigen::VectorXd reduced_vec = varform.solve_data()->nl_problem->full_to_reduced_grad(rhs.col(i));
90 if (i == 0)
91 reduced.setZero(reduced_vec.rows(), rhs.cols());
92 reduced.col(i) = reduced_vec;
93 }
94 return reduced;
95 }
96 else
97 return rhs;
98 }
99
100 void AdjointForm::first_derivative(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
101 {
102 Eigen::VectorXd partial_grad;
103 compute_partial_gradient(x, partial_grad);
104 gradv = variable_to_simulations_.compute_adjoint_term(x) + partial_grad;
105 }
106
107 void AdjointForm::first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
108 {
109 log_and_throw_adjoint_error("first_derivative_unweighted cannot be defined for adjoint forms!");
110 }
111
112 void AdjointForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
113 {
114 gradv = Eigen::VectorXd::Zero(x.size());
115 }
116
117 Eigen::MatrixXd AdjointForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
118 {
119 return Eigen::MatrixXd::Zero(varform.primary_space().ndof(), diff_cache.size());
120 }
121
122 void AdjointForm::update_quantities(const double t, const Eigen::VectorXd &x)
123 {
124 }
125 void AdjointForm::init_lagging(const Eigen::VectorXd &x)
126 {
127 }
128 void AdjointForm::update_lagging(const Eigen::VectorXd &x, const int iter_num)
129 {
130 }
131
132 double StaticForm::value_unweighted(const Eigen::VectorXd &x) const
133 {
134 return value_unweighted_step(0, x);
135 }
136
137 void StaticForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
138 {
140 }
141
142 Eigen::VectorXd StaticForm::compute_adjoint_rhs_step_prev(const int time_step, const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
143 {
144 return Eigen::MatrixXd::Zero(varform.primary_space().ndof(), 1);
145 }
146
147 Eigen::MatrixXd StaticForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
148 {
149 assert(!depends_on_step_prev());
150 Eigen::MatrixXd term = Eigen::MatrixXd::Zero(varform.primary_space().ndof(), diff_cache.size());
151 term.col(0) = compute_adjoint_rhs_step(0, x, varform, diff_cache);
152
153 return term;
154 }
155
156 void StaticForm::solution_changed(const Eigen::VectorXd &new_x)
157 {
159 solution_changed_step(0, new_x);
160 }
161
162 double MaxStressForm::value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const
163 {
164 const double t = varform_->get_problem().is_time_dependent() ? time_step * varform_->get_args()["time"]["dt"].get<double>() + varform_->get_args()["time"]["t0"].get<double>() : 0;
165 Eigen::VectorXd max_stress;
166 max_stress.setZero(varform_->primary_space().basis_list().size());
167 utils::maybe_parallel_for(varform_->primary_space().basis_list().size(), [&](int start, int end, int thread_id) {
168 Eigen::MatrixXd local_vals;
169 assembler::ElementAssemblyValues vals;
170 for (int e = start; e < end; e++)
171 {
172 if (interested_ids_.size() != 0 && interested_ids_.find(varform_->get_mesh().get_body_id(e)) == interested_ids_.end())
173 continue;
174
175 varform_->assembly_cache().compute(e, varform_->get_mesh().is_volume(), varform_->primary_space().basis_list()[e], varform_->primary_space().geometry_basis_list()[e], vals);
176 // std::vector<assembler::Assembler::NamedMatrix> result;
177 // varform_->primary_assembler().compute_tensor_value(e, varform_->primary_space().basis_list()[e], varform_->primary_space().geometry_basis_list()[e], vals.quadrature.points, varform_->diff_cached.u(time_step), result);
178 dynamic_cast<const assembler::ElasticityAssembler &>(varform_->primary_assembler()).compute_stress_tensor(assembler::OutputData(t, e, varform_->primary_space().basis_list()[e], varform_->primary_space().geometry_basis_list()[e], vals.quadrature.points, diff_cache_->u(time_step)), ElasticityTensorType::PK1, local_vals);
179
180 Eigen::VectorXd stress_norms = local_vals.rowwise().norm();
181 max_stress(e) = std::max(max_stress(e), stress_norms.maxCoeff());
182 }
183 });
184
185 return max_stress.maxCoeff();
186 }
187 Eigen::VectorXd MaxStressForm::compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
188 {
189 log_and_throw_adjoint_error("[{}] Not differentiable!", name());
190 return Eigen::VectorXd();
191 }
192 void MaxStressForm::compute_partial_gradient_step(const int time_step, const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
193 {
194 log_and_throw_adjoint_error("[{}] Not differentiable!", name());
195 }
196} // namespace polyfem::solver
double val
Definition Assembler.cpp:90
int x
Storage for additional data required by differntial code.
Definition DiffCache.hpp:22
int size() const
Definition DiffCache.hpp:46
virtual bool is_time_dependent() const
Definition Problem.hpp:64
int dimension() const
utily for dimension
Definition Mesh.hpp:138
virtual void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const final override
Compute the first derivative of the value wrt x.
virtual void solution_changed(const Eigen::VectorXd &new_x) override
Update cached fields upon a change in the solution.
virtual Eigen::MatrixXd compute_reduced_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
virtual void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const final override
Compute the second derivative of the value wrt x.
virtual void init_lagging(const Eigen::VectorXd &x) final override
Initialize lagged fields TODO: more than one step.
virtual void first_derivative(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const final override
Compute the first derivative of the value wrt x multiplied with the weigth.
double value(const Eigen::VectorXd &x) const override
Compute the value of the form multiplied with the weigth.
virtual Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
virtual void update_lagging(const Eigen::VectorXd &x, const int iter_num) final override
Update lagged fields.
virtual void compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
virtual void update_quantities(const double t, const Eigen::VectorXd &x) final override
Update time-dependent fields.
void enable_energy_print(const std::string &print_energy_keyword)
virtual std::string name() const override
const VariableToSimulationGroup variable_to_simulations_
virtual double value(const Eigen::VectorXd &x) const
Compute the value of the form multiplied with the weigth.
Definition Form.hpp:26
virtual double weight() const
Get the form's multiplicative constant weight.
Definition Form.hpp:128
HomogenizedDispGradForm(const VariableToSimulationGroup &variables, std::shared_ptr< const varform::DifferentiableVarForm > varform, std::shared_ptr< const DiffCache > diff_cache, const json &args)
std::shared_ptr< const varform::DifferentiableVarForm > varform_
std::shared_ptr< const DiffCache > diff_cache_
double value_unweighted(const Eigen::VectorXd &variables) const override
Compute the value of the form.
Eigen::MatrixXd compute_reduced_adjoint_rhs(const Eigen::VectorXd &variables, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const override
std::shared_ptr< const varform::DifferentiableVarForm > varform_
double value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const override
std::shared_ptr< solver::NLProblem > nl_problem
virtual void compute_partial_gradient_step(const int time_step, const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const =0
Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const final override
virtual Eigen::VectorXd compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const =0
virtual Eigen::VectorXd compute_adjoint_rhs_step_prev(const int time_step, const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
virtual void solution_changed_step(const int time_step, const Eigen::VectorXd &new_x)
void compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const final override
double value_unweighted(const Eigen::VectorXd &x) const final override
Compute the value of the form.
virtual double value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const =0
virtual bool depends_on_step_prev() const final
virtual void solution_changed(const Eigen::VectorXd &new_x) final override
Update cached fields upon a change in the solution.
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const
Optimization-facing interface implemented by differentiated VarForm adapters.
virtual const mesh::Mesh & get_mesh() const =0
virtual solver::SolveData * solve_data()=0
virtual assembler::Problem & get_problem()=0
virtual const FESpace & primary_space() const =0
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
spdlog::logger & adjoint_logger()
Retrieves the current logger for adjoint.
Definition Logger.cpp:30
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24