PolyFEM
Loading...
Searching...
No Matches
AdjointForm.cpp
Go to the documentation of this file.
1#include "AdjointForm.hpp"
5#include <polyfem/State.hpp>
7
8namespace polyfem::solver
9{
10 double AdjointForm::value(const Eigen::VectorXd &x) const
11 {
12 double val = Form::value(x);
14 {
15 adjoint_logger().debug("[{}] {}", print_energy_keyword_, val);
17 }
18 return val;
19 }
20
21 void AdjointForm::enable_energy_print(const std::string &print_energy_keyword)
22 {
23 print_energy_keyword_ = print_energy_keyword;
25 }
26
32
33 void AdjointForm::second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const
34 {
35 log_and_throw_adjoint_error("[{}] Second derivatives not implemented", name());
36 }
37
38 Eigen::MatrixXd AdjointForm::compute_reduced_adjoint_rhs(const Eigen::VectorXd &x, const State &state) const
39 {
40 Eigen::MatrixXd rhs = compute_adjoint_rhs(x, state);
41 if (!state.problem->is_time_dependent() && !state.lin_solver_cached) // nonlinear static solve only
42 {
43 Eigen::MatrixXd reduced;
44 for (int i = 0; i < rhs.cols(); i++)
45 {
46 Eigen::VectorXd reduced_vec = state.solve_data.nl_problem->full_to_reduced_grad(rhs.col(i));
47 if (i == 0)
48 reduced.setZero(reduced_vec.rows(), rhs.cols());
49 reduced.col(i) = reduced_vec;
50 }
51 return reduced;
52 }
53 else
54 return rhs;
55 }
56
57 void AdjointForm::first_derivative(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
58 {
59 Eigen::VectorXd partial_grad;
60 compute_partial_gradient(x, partial_grad);
61 gradv = variable_to_simulations_.compute_adjoint_term(x) + partial_grad;
62 }
63
64 void AdjointForm::first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
65 {
66 log_and_throw_adjoint_error("first_derivative_unweighted cannot be defined for adjoint forms!");
67 }
68
69 void AdjointForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
70 {
71 gradv = Eigen::VectorXd::Zero(x.size());
72 }
73
74 Eigen::MatrixXd AdjointForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state) const
75 {
76 return Eigen::MatrixXd::Zero(state.ndof(), state.diff_cached.size());
77 }
78
79 void AdjointForm::update_quantities(const double t, const Eigen::VectorXd &x)
80 {
81 }
82 void AdjointForm::init_lagging(const Eigen::VectorXd &x)
83 {
84 }
85 void AdjointForm::update_lagging(const Eigen::VectorXd &x, const int iter_num)
86 {
87 }
88
89 double StaticForm::value_unweighted(const Eigen::VectorXd &x) const
90 {
91 return value_unweighted_step(0, x);
92 }
93
94 void StaticForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
95 {
97 }
98
99 Eigen::VectorXd StaticForm::compute_adjoint_rhs_step_prev(const int time_step, const Eigen::VectorXd &x, const State &state) const
100 {
101 return Eigen::MatrixXd::Zero(state.ndof(), 1);
102 }
103
104 Eigen::MatrixXd StaticForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state) const
105 {
106 assert(!depends_on_step_prev());
107 Eigen::MatrixXd term = Eigen::MatrixXd::Zero(state.ndof(), state.diff_cached.size());
108 term.col(0) = compute_adjoint_rhs_step(0, x, state);
109
110 return term;
111 }
112
113 void StaticForm::solution_changed(const Eigen::VectorXd &new_x)
114 {
116 solution_changed_step(0, new_x);
117 }
118
119 double MaxStressForm::value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const
120 {
121 const double t = state_.problem->is_time_dependent() ? time_step * state_.args["time"]["dt"].get<double>() + state_.args["time"]["t0"].get<double>() : 0;
122 Eigen::VectorXd max_stress;
123 max_stress.setZero(state_.bases.size());
124 utils::maybe_parallel_for(state_.bases.size(), [&](int start, int end, int thread_id) {
125 Eigen::MatrixXd local_vals;
126 assembler::ElementAssemblyValues vals;
127 for (int e = start; e < end; e++)
128 {
129 if (interested_ids_.size() != 0 && interested_ids_.find(state_.mesh->get_body_id(e)) == interested_ids_.end())
130 continue;
131
132 state_.ass_vals_cache.compute(e, state_.mesh->is_volume(), state_.bases[e], state_.geom_bases()[e], vals);
133 // std::vector<assembler::Assembler::NamedMatrix> result;
134 // state_.assembler->compute_tensor_value(e, state_.bases[e], state_.geom_bases()[e], vals.quadrature.points, state_.diff_cached.u(time_step), result);
135 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, state_.diff_cached.u(time_step)), ElasticityTensorType::PK1, local_vals);
136
137 Eigen::VectorXd stress_norms = local_vals.rowwise().norm();
138 max_stress(e) = std::max(max_stress(e), stress_norms.maxCoeff());
139 }
140 });
141
142 return max_stress.maxCoeff();
143 }
144 Eigen::VectorXd MaxStressForm::compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const State &state) const
145 {
146 log_and_throw_adjoint_error("[{}] Not differentiable!", name());
147 return Eigen::VectorXd();
148 }
149 void MaxStressForm::compute_partial_gradient_step(const int time_step, const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
150 {
151 log_and_throw_adjoint_error("[{}] Not differentiable!", name());
152 }
153} // namespace polyfem::solver
double val
Definition Assembler.cpp:86
int x
main class that contains the polyfem solver and all its state
Definition State.hpp:79
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
Definition State.hpp:168
json args
main input arguments containing all defaults
Definition State.hpp:101
solver::DiffCache diff_cached
Definition State.hpp:649
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
Definition State.hpp:171
int ndof() const
Definition State.hpp:653
solver::SolveData solve_data
timedependent stuff cached
Definition State.hpp:324
std::unique_ptr< polysolve::linear::Solver > lin_solver_cached
Definition State.hpp:651
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 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.
virtual Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state) const
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 Eigen::MatrixXd compute_reduced_adjoint_rhs(const Eigen::VectorXd &x, const State &state) 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 override
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
Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const State &state) const final override
virtual Eigen::VectorXd compute_adjoint_rhs_step_prev(const int time_step, const Eigen::VectorXd &x, const State &state) 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
virtual Eigen::VectorXd compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const State &state) const =0
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
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:28
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:77
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:22