PolyFEM
Loading...
Searching...
No Matches
ElasticVariableToSimulation.cpp
Go to the documentation of this file.
2
9
10#include <Eigen/Core>
11
12#include <string>
13#include <cassert>
14
15namespace polyfem::solver
16{
18 DiffCachePtrs diff_caches,
19 CompositeParametrization parametrizations)
20 : states_(std::move(states)),
21 diff_caches_(std::move(diff_caches)),
22 parametrization_(std::move(parametrizations))
23 {
24 assert(!states_.empty());
25 assert(states_.size() == diff_caches_.size());
26
27 elem_num_ = states_[0]->bases.size();
28 for (auto &s : states_)
29 {
30 if (s->bases.size() != elem_num_)
31 {
32 log_and_throw_adjoint_error("Fail to construct elastic variable to simulation. Reason: Inconsistent element numbers.");
33 }
34 }
35 }
36
38 {
39 return "elastic";
40 }
41
46
48 {
49 for (const auto &s : states_)
50 {
51 if (s.get() == &target)
52 {
53 return true;
54 }
55 }
56 return false;
57 }
58
59 void ElasticVariableToSimulation::update(const Eigen::VectorXd &x)
60 {
61 Eigen::VectorXd y = parametrization_.eval(x);
62 assert(y.size() == para_out_dof());
63
64 for (auto &s : states_)
65 {
66 s->assembler->update_lame_params(y.segment(0, elem_num_), y.segment(elem_num_, elem_num_));
67 }
68 }
69
70 void ElasticVariableToSimulation::update_state_variables(const Eigen::VectorXd &x, Eigen::VectorXd &state_variables) const
71 {
72 assert(state_variables.size() == para_out_dof());
73 state_variables = parametrization_.eval(x);
74 }
75
76 Eigen::VectorXd ElasticVariableToSimulation::compute_adjoint_term(const Eigen::VectorXd &x) const
77 {
78 Eigen::VectorXd term, cur_term;
79 for (int i = 0; i < int(states_.size()); ++i)
80 {
81 auto &state = states_[i];
82 auto &diff_cache = diff_caches_[i];
83
84 if (state->problem->is_time_dependent())
85 {
86 Eigen::MatrixXd adjoint_p = get_adjoint_mat(*state, *diff_cache, 0);
87 Eigen::MatrixXd adjoint_nu = get_adjoint_mat(*state, *diff_cache, 1);
88 AdjointTools::dJ_material_transient_adjoint_term(*state, *diff_cache, adjoint_nu, adjoint_p, cur_term);
89 }
90 else
91 {
92 Eigen::MatrixXd adjoint_p = get_adjoint_mat(*state, *diff_cache, 0);
93 AdjointTools::dJ_material_static_adjoint_term(*state, diff_cache->u(0), adjoint_p, cur_term);
94 }
95
96 if (term.size() != cur_term.size())
97 {
98 term = cur_term;
99 }
100 else
101 {
102 term += cur_term;
103 }
104 }
105
106 assert(term.size() == para_out_dof());
107 return parametrization_.apply_jacobian(term, x);
108 }
109
114
116 {
117 // Sample lame parameters at barycenter of each mesh element.
118 auto &state = *(states_[0]);
119 auto params_map = state.assembler->parameters();
120
121 // params_map returns (key, callback). Callback interpolates param usign FE basis.
122 auto search_lambda = params_map.find("lambda");
123 auto search_mu = params_map.find("mu");
124 if (search_lambda == params_map.end() || search_mu == params_map.end())
125 {
126 log_and_throw_adjoint_error("[{}] Failed to find Lame parameters!", name());
127 }
128
129 int dim = state.mesh->dimension();
130 Eigen::VectorXd lambdas(elem_num_);
131 Eigen::VectorXd mus(elem_num_);
132 for (int e = 0; e < elem_num_; ++e)
133 {
134 RowVectorNd barycenter;
135 if (!state.mesh->is_volume())
136 {
137 auto mesh2d = dynamic_cast<const mesh::Mesh2D *>(state.mesh.get());
138 barycenter = mesh2d->face_barycenter(e);
139 }
140 else
141 {
142 auto mesh3d = dynamic_cast<const mesh::Mesh3D *>(state.mesh.get());
143 barycenter = mesh3d->cell_barycenter(e);
144 }
145 // The callback signature is (uv coordinate, world coordinate, time, elem id)
146 // For lame parameters specifically, uv is not used so we pass a dummy.
147 lambdas(e) = search_lambda->second(RowVectorNd::Zero(dim), barycenter, 0.0f, e);
148 mus(e) = search_mu->second(RowVectorNd::Zero(dim), barycenter, 0.0f, e);
149 }
150
151 Eigen::VectorXd params(para_out_dof());
152 params << lambdas, mus;
153 return parametrization_.inverse_eval(params);
154 }
155
156 Eigen::VectorXd ElasticVariableToSimulation::apply_parametrization_jacobian(const Eigen::VectorXd &term, const Eigen::VectorXd &x) const
157 {
158 assert(term.size() == 2 * elem_num_);
159 return parametrization_.apply_jacobian(term, x);
160 }
161
163 {
164 return 2 * elem_num_;
165 }
166
167} // namespace polyfem::solver
int y
int x
main class that contains the polyfem solver and all its state
Definition State.hpp:114
RowVectorNd face_barycenter(const int index) const override
face barycenter
Definition Mesh2D.cpp:69
virtual RowVectorNd cell_barycenter(const int c) const =0
cell barycenter
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad_full, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
void update_state_variables(const Eigen::VectorXd &x, Eigen::VectorXd &state_variables) const override
Update state variables from optimization variables.
Eigen::VectorXd inverse_eval() const override
Compute optimization variables from forward simulation legacy::State.
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
Compute adjoint contribution of objective gradient.
void update(const Eigen::VectorXd &x) override
Update forward simulation states from optimization variables.
Eigen::VectorXd apply_parametrization_jacobian(const Eigen::VectorXd &term, const Eigen::VectorXd &x) const override
Apply parametrization jacobian to compute the gradient w.r.t.
std::vector< std::shared_ptr< legacy::State > > StatePtrs
int inverse_dof() const override
Compute optimization variables dof.
std::vector< std::shared_ptr< DiffCache > > DiffCachePtrs
ElasticVariableToSimulation(StatePtrs states, DiffCachePtrs diff_caches, CompositeParametrization parametrizations)
Construct ElasticVariableToSimulation.
bool affect_state(const legacy::State &target) const override
Return true if current var2sim maps to target state.
void dJ_material_transient_adjoint_term(const legacy::State &state, const DiffCache &diff_cache, const Eigen::MatrixXd &adjoint_nu, const Eigen::MatrixXd &adjoint_p, Eigen::VectorXd &one_form)
void dJ_material_static_adjoint_term(const legacy::State &state, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &adjoint, Eigen::VectorXd &one_form)
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
Eigen::MatrixXd get_adjoint_mat(const legacy::State &state, const DiffCache &diff_cache, int type)
Get adjoint parameter nu or p.
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:13