PolyFEM
Loading...
Searching...
No Matches
AdjointForm.cpp
Go to the documentation of this file.
2
3#include <polyfem/State.hpp>
11
12#include <Eigen/Core>
13
14#include <algorithm>
15#include <cassert>
16#include <memory>
17#include <string>
18
19namespace polyfem::solver
20{
21 double AdjointForm::value(const Eigen::VectorXd &x) const
22 {
23 double val = Form::value(x);
25 {
26 adjoint_logger().debug("[{}] {}", print_energy_keyword_, val);
28 }
29 return val;
30 }
31
32 void AdjointForm::enable_energy_print(const std::string &print_energy_keyword)
33 {
34 print_energy_keyword_ = print_energy_keyword;
36 }
37
43
44 void AdjointForm::second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const
45 {
46 log_and_throw_adjoint_error("[{}] Second derivatives not implemented", name());
47 }
48
49 Eigen::MatrixXd AdjointForm::compute_reduced_adjoint_rhs(const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
50 {
51 Eigen::MatrixXd rhs = compute_adjoint_rhs(x, state, diff_cache);
52 // Only for homogenization
53 if (!state.problem->is_time_dependent() && state.is_homogenization() && state.solve_data.nl_problem) // nonlinear static solve only
54 {
55 Eigen::MatrixXd reduced;
56 for (int i = 0; i < rhs.cols(); i++)
57 {
58 Eigen::VectorXd reduced_vec = state.solve_data.nl_problem->full_to_reduced_grad(rhs.col(i));
59 if (i == 0)
60 reduced.setZero(reduced_vec.rows(), rhs.cols());
61 reduced.col(i) = reduced_vec;
62 }
63 return reduced;
64 }
65 else
66 return rhs;
67 }
68
69 void AdjointForm::first_derivative(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
70 {
71 Eigen::VectorXd partial_grad;
72 compute_partial_gradient(x, partial_grad);
73 gradv = variable_to_simulations_.compute_adjoint_term(x) + partial_grad;
74 }
75
76 void AdjointForm::first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
77 {
78 log_and_throw_adjoint_error("first_derivative_unweighted cannot be defined for adjoint forms!");
79 }
80
81 void AdjointForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
82 {
83 gradv = Eigen::VectorXd::Zero(x.size());
84 }
85
86 Eigen::MatrixXd AdjointForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
87 {
88 return Eigen::MatrixXd::Zero(state.ndof(), diff_cache.size());
89 }
90
91 void AdjointForm::update_quantities(const double t, const Eigen::VectorXd &x)
92 {
93 }
94 void AdjointForm::init_lagging(const Eigen::VectorXd &x)
95 {
96 }
97 void AdjointForm::update_lagging(const Eigen::VectorXd &x, const int iter_num)
98 {
99 }
100
101 double StaticForm::value_unweighted(const Eigen::VectorXd &x) const
102 {
103 return value_unweighted_step(0, x);
104 }
105
106 void StaticForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
107 {
109 }
110
111 Eigen::VectorXd StaticForm::compute_adjoint_rhs_step_prev(const int time_step, const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
112 {
113 return Eigen::MatrixXd::Zero(state.ndof(), 1);
114 }
115
116 Eigen::MatrixXd StaticForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
117 {
118 assert(!depends_on_step_prev());
119 Eigen::MatrixXd term = Eigen::MatrixXd::Zero(state.ndof(), diff_cache.size());
120 term.col(0) = compute_adjoint_rhs_step(0, x, state, diff_cache);
121
122 return term;
123 }
124
125 void StaticForm::solution_changed(const Eigen::VectorXd &new_x)
126 {
128 solution_changed_step(0, new_x);
129 }
130
131 double MaxStressForm::value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const
132 {
133 const double t = state_->problem->is_time_dependent() ? time_step * state_->args["time"]["dt"].get<double>() + state_->args["time"]["t0"].get<double>() : 0;
134 Eigen::VectorXd max_stress;
135 max_stress.setZero(state_->bases.size());
136 utils::maybe_parallel_for(state_->bases.size(), [&](int start, int end, int thread_id) {
137 Eigen::MatrixXd local_vals;
138 assembler::ElementAssemblyValues vals;
139 for (int e = start; e < end; e++)
140 {
141 if (interested_ids_.size() != 0 && interested_ids_.find(state_->mesh->get_body_id(e)) == interested_ids_.end())
142 continue;
143
144 state_->ass_vals_cache.compute(e, state_->mesh->is_volume(), state_->bases[e], state_->geom_bases()[e], vals);
145 // std::vector<assembler::Assembler::NamedMatrix> result;
146 // state_->assembler->compute_tensor_value(e, state_->bases[e], state_->geom_bases()[e], vals.quadrature.points, state_->diff_cached.u(time_step), result);
147 std::dynamic_pointer_cast<assembler::ElasticityAssembler>(state_->assembler)->compute_stress_tensor(assembler::OutputData(t, e, state_->bases[e], state_->geom_bases()[e], vals.quadrature.points, diff_cache_->u(time_step)), ElasticityTensorType::PK1, local_vals);
148
149 Eigen::VectorXd stress_norms = local_vals.rowwise().norm();
150 max_stress(e) = std::max(max_stress(e), stress_norms.maxCoeff());
151 }
152 });
153
154 return max_stress.maxCoeff();
155 }
156 Eigen::VectorXd MaxStressForm::compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
157 {
158 log_and_throw_adjoint_error("[{}] Not differentiable!", name());
159 return Eigen::VectorXd();
160 }
161 void MaxStressForm::compute_partial_gradient_step(const int time_step, const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
162 {
163 log_and_throw_adjoint_error("[{}] Not differentiable!", name());
164 }
165} // namespace polyfem::solver
double val
Definition Assembler.cpp:86
int x
Storage for additional data required by differntial code.
Definition DiffCache.hpp:21
int size() const
Definition DiffCache.hpp:47
main class that contains the polyfem solver and all its state
Definition State.hpp:113
bool is_homogenization() const
Definition State.hpp:811
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
Definition State.hpp:202
int ndof() const
Definition State.hpp:309
solver::SolveData solve_data
timedependent stuff cached
Definition State.hpp:375
virtual Eigen::MatrixXd compute_reduced_adjoint_rhs(const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
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 void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const final override
Compute the second derivative of the value wrt x.
virtual Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
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 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
Eigen::VectorXd compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const override
std::shared_ptr< const State > state_
std::string name() const override
double value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const override
void compute_partial_gradient_step(const int time_step, const Eigen::VectorXd &x, Eigen::VectorXd &gradv) 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
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
Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const final override
double value_unweighted(const Eigen::VectorXd &x) const final override
Compute the value of the form.
virtual Eigen::VectorXd compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const =0
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.
virtual Eigen::VectorXd compute_adjoint_rhs_step_prev(const int time_step, const Eigen::VectorXd &x, const State &state, const DiffCache &diff_cache) const
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const
Computes the sum of adjoint terms for all VariableToSimulation.
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
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24