PolyFEM
Loading...
Searching...
No Matches
InitialConditionVariableToSimulation.cpp
Go to the documentation of this file.
2
7
8#include <Eigen/Core>
9
10#include <cassert>
11#include <string>
12
13namespace polyfem::solver
14{
15
17 DiffCachePtrs diff_caches,
18 CompositeParametrization parametrizations,
19 Eigen::VectorXi active_dofs)
20 : dof_num_(states[0]->ndof()),
21 states_(std::move(states)),
22 diff_caches_(std::move(diff_caches)),
23 parametrization_(std::move(parametrizations)),
24 active_dofs_(std::move(active_dofs))
25 {
26 assert(!states_.empty());
27 assert(states_.size() == diff_caches_.size());
28
29 for (auto &s : states_)
30 {
31 if (!s->problem->is_time_dependent())
32 {
33 log_and_throw_adjoint_error("Fail to construct initial condition variable to simulation. Reason: Static problem not supported.");
34 }
35 }
36
37 // Validate active selection.
38 std::string reason;
40 {
41 log_and_throw_adjoint_error("Fail to construct initial condition variable to simulation. Reason: {}", reason);
42 }
43
44 // Expand implicit all active selection.
45 if (active_dofs_.size() == 0)
46 {
47 active_dofs_ = Eigen::VectorXi::LinSpaced(dof_num_, 0, dof_num_ - 1);
48 }
49
50 // Populate baseline initial-condition override for each state.
51 for (int i = 0; i < states_.size(); ++i)
52 {
53 Eigen::MatrixXd sol, vel;
54 states_[i]->initial_solution(sol);
55 states_[i]->initial_velocity(vel);
56
57 // initial condition might return history of position and velocity.
58 // Since we can't handle that, drop all condition from prev time steps.
59 if (sol.cols() > 1)
60 {
61 sol.conservativeResize(Eigen::NoChange, 1);
62 }
63 if (vel.cols() > 1)
64 {
65 vel.conservativeResize(Eigen::NoChange, 1);
66 }
67
68 if (sol.rows() != dof_num_ || sol.cols() != 1)
69 {
70 log_and_throw_adjoint_error("Fail to construct initial condition variable to simulation. Reason: Invalid initial solution shape ({}, {}). Expect ({}, 1).",
71 sol.rows(), sol.cols(), dof_num_);
72 }
73 if (vel.rows() != dof_num_ || vel.cols() != 1)
74 {
75 log_and_throw_adjoint_error("Fail to construct initial condition variable to simulation. Reason: Invalid initial velocity shape ({}, {}). Expect ({}, 1).",
76 vel.rows(), vel.cols(), dof_num_);
77 }
78
79 diff_caches_[i]->initial_condition_override.solution = sol;
80 diff_caches_[i]->initial_condition_override.velocity = vel;
81 diff_caches_[i]->initial_condition_override.acceleration = {};
82 }
83 }
84
86 {
87 return "initial";
88 }
89
94
96 {
97 for (const auto &s : states_)
98 {
99 if (s.get() == &target)
100 {
101 return true;
102 }
103 }
104 return false;
105 }
106
108 {
109 Eigen::VectorXd y = parametrization_.eval(x);
110 assert(y.size() == para_out_dof());
111
112 int active_num = active_dofs_.size();
113 for (auto &dc : diff_caches_)
114 {
115 auto &sol = dc->initial_condition_override.solution;
116 auto &vel = dc->initial_condition_override.velocity;
117 // Override should already be populated in the constructor.
118 assert(sol.rows() == dof_num_ && sol.cols() >= 1);
119 assert(vel.rows() == dof_num_ && vel.cols() >= 1);
120
121 for (int i = 0; i < active_num; ++i)
122 {
123 sol(active_dofs_(i), 0) = y(i);
124 vel(active_dofs_(i), 0) = y(active_num + i);
125 }
126
127 dc->initial_condition_override.acceleration = {};
128 }
129 }
130
131 void InitialConditionVariableToSimulation::update_state_variables(const Eigen::VectorXd &x, Eigen::VectorXd &state_variables) const
132 {
133 assert(state_variables.size() == 2 * dof_num_);
134
135 Eigen::VectorXd y = parametrization_.eval(x);
136 assert(y.size() == para_out_dof());
137
138 int active_num = active_dofs_.size();
139 for (int i = 0; i < active_num; ++i)
140 {
141 state_variables(active_dofs_(i)) = y(i);
142 state_variables(dof_num_ + active_dofs_(i)) = y(active_num + i);
143 }
144 }
145
146 Eigen::VectorXd InitialConditionVariableToSimulation::compute_adjoint_term(const Eigen::VectorXd &x) const
147 {
148 Eigen::VectorXd term, cur_term;
149 for (int i = 0; i < states_.size(); ++i)
150 {
151 auto &state = states_[i];
152 auto &diff_cache = diff_caches_[i];
153
154 Eigen::MatrixXd adjoint_p = get_adjoint_mat(*state, *diff_cache, 0);
155 Eigen::MatrixXd adjoint_nu = get_adjoint_mat(*state, *diff_cache, 1);
156 AdjointTools::dJ_initial_condition_adjoint_term(*state, adjoint_nu, adjoint_p, cur_term);
157
158 if (term.size() != cur_term.size())
159 {
160 term = cur_term;
161 }
162 else
163 {
164 term += cur_term;
165 }
166 }
167
168 assert(term.size() == 2 * dof_num_);
169
170 int active_num = active_dofs_.size();
171 Eigen::VectorXd active_term(para_out_dof());
172 for (int j = 0; j < active_num; ++j)
173 {
174 active_term(j) = term(active_dofs_(j));
175 active_term(active_num + j) = term(dof_num_ + active_dofs_(j));
176 }
177
178 assert(active_term.size() == para_out_dof());
179 return parametrization_.apply_jacobian(active_term, x);
180 }
181
186
188 {
189 const Eigen::MatrixXd &sol = diff_caches_[0]->initial_condition_override.solution;
190 const Eigen::MatrixXd &vel = diff_caches_[0]->initial_condition_override.velocity;
191 assert(sol.rows() == dof_num_ && sol.cols() >= 1);
192 assert(vel.rows() == dof_num_ && vel.cols() >= 1);
193
194 int active_num = active_dofs_.size();
195 Eigen::VectorXd y(para_out_dof());
196 for (int j = 0; j < active_num; ++j)
197 {
198 y(j) = sol(active_dofs_(j), 0);
199 y(active_num + j) = vel(active_dofs_(j), 0);
200 }
202 }
203
204 Eigen::VectorXd InitialConditionVariableToSimulation::apply_parametrization_jacobian(const Eigen::VectorXd &, const Eigen::VectorXd &) const
205 {
206 // Not implemented because there's no user
207 log_and_throw_adjoint_error("apply_parametrization_jacobian is not implemented in {} variable to simulation.", name());
208 }
209
211 {
212 return 2 * active_dofs_.size();
213 }
214
215} // namespace polyfem::solver
int y
int x
main class that contains the polyfem solver and all its state
Definition State.hpp:114
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).
int inverse_dof() const override
Compute optimization variables dof.
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
Compute adjoint contribution of objective gradient.
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.
Eigen::VectorXd inverse_eval() const override
Compute optimization variables from forward simulation legacy::State.
InitialConditionVariableToSimulation(StatePtrs states, DiffCachePtrs diff_caches, CompositeParametrization parametrizations, Eigen::VectorXi active_dofs)
Construct InitialConditionVariableToSimulation.
void update(const Eigen::VectorXd &x) override
Update forward simulation states from optimization variables.
bool affect_state(const legacy::State &target) const override
Return true if current var2sim maps to target state.
void update_state_variables(const Eigen::VectorXd &x, Eigen::VectorXd &state_variables) const override
Update state variables from optimization variables.
void dJ_initial_condition_adjoint_term(const legacy::State &state, const Eigen::MatrixXd &adjoint_nu, const Eigen::MatrixXd &adjoint_p, Eigen::VectorXd &one_form)
bool is_active_dofs_valid(const Eigen::VectorXi &active_dofs, const std::vector< std::shared_ptr< legacy::State > > &states, std::string &reason)
Validate active solution space dofs selection given states.
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.