PolyFEM
Loading...
Searching...
No Matches
PeriodicShapeVariableToSimulation.cpp
Go to the documentation of this file.
2
3#include <polyfem/Common.hpp>
8
9#include <Eigen/Core>
10
11#include <cassert>
12#include <string>
13#include <utility>
14
15namespace polyfem::solver
16{
18 VarFormPtrs varforms,
19 DiffCachePtrs diff_caches,
20 CompositeParametrization parametrizations)
21 : dim_(varforms[0]->get_mesh().dimension()),
22 vertex_num_(varforms[0]->get_mesh().n_vertices()),
23 varforms_(std::move(varforms)),
24 diff_caches_(std::move(diff_caches)),
25 parametrization_(std::move(parametrizations))
26 {
27 assert(!varforms_.empty());
28 assert(varforms_.size() == diff_caches_.size());
29
30 for (const auto &varform : varforms_)
31 {
32 if (varform->get_mesh().dimension() != dim_)
33 {
34 log_and_throw_adjoint_error("Fail to construct periodic shape variable to simulation. Reason: mesh dimension mismatch between varforms.");
35 }
36 if (varform->get_mesh().n_vertices() != vertex_num_)
37 {
38 log_and_throw_adjoint_error("Fail to construct periodic shape variable to simulation. Reason: mesh vertex num mismatch between varforms.");
39 }
40 if (varform->get_problem().is_time_dependent())
41 {
42 log_and_throw_adjoint_error("Fail to construct periodic shape variable to simulation. Reason: transient simulations are not supported.");
43 }
44 if (!varform->has_periodic_boundary())
45 {
46 log_and_throw_adjoint_error("Fail to construct periodic shape variable to simulation. Reason: periodic boundary conditions are not enabled.");
47 }
48 const Eigen::MatrixXd tile_offsets = varform->periodic_tile_offsets();
49 if (tile_offsets.rows() != dim_ || tile_offsets.cols() != dim_
50 || Eigen::FullPivLU<Eigen::MatrixXd>(tile_offsets).rank() != dim_)
51 {
52 log_and_throw_adjoint_error("Fail to construct periodic shape variable to simulation. Reason: partial periodicity is not supported.");
53 }
54 if (!varform->is_homogenization())
55 {
56 log_and_throw_adjoint_error("Fail to construct periodic shape variable to simulation. Reason: only homogenization problems are supported.");
57 }
58 }
59
60 Eigen::MatrixXd V;
61 varforms_[0]->get_vertices(V);
62 periodic_mesh_map_ = std::make_unique<PeriodicMeshToMesh>(V);
63 }
64
66 {
67 return "periodic-shape";
68 }
69
74
76 {
77 for (auto &varform : varforms_)
78 {
79 if (varform.get() == &target)
80 return true;
81 }
82 return false;
83 }
84
85 void PeriodicShapeVariableToSimulation::update(const Eigen::VectorXd &x)
86 {
87 Eigen::VectorXd y = parametrization_.eval(x);
88 assert(y.size() == para_out_dof());
89
90 Eigen::MatrixXd V = utils::unflatten(periodic_mesh_map_->eval(y), dim_);
91
92 for (auto &varform : varforms_)
93 varform->set_vertex_positions(V);
94 }
95
96 void PeriodicShapeVariableToSimulation::update_state_variables(const Eigen::VectorXd &x, Eigen::VectorXd &state_variables) const
97 {
98 assert(state_variables.size() == para_out_dof());
99 state_variables = parametrization_.eval(x);
100 }
101
102 Eigen::VectorXd PeriodicShapeVariableToSimulation::compute_adjoint_term(const Eigen::VectorXd &x) const
103 {
104 Eigen::VectorXd y = parametrization_.eval(x);
105 assert(y.size() == para_out_dof());
106
107 Eigen::VectorXd term, cur_term;
108 for (int i = 0; i < varforms_.size(); ++i)
109 {
110 auto &varform = varforms_[i];
111 auto &diff_cache = diff_caches_[i];
112
113 Eigen::MatrixXd adjoint_p = get_adjoint_mat(*varform, *diff_cache, 0);
114
116 *varform,
117 *diff_cache,
119 y,
120 diff_cache->u(0),
121 adjoint_p,
122 cur_term);
123
124 if (term.size() != cur_term.size())
125 {
126 term = cur_term;
127 }
128 else
129 {
130 term += cur_term;
131 }
132 }
133
134 assert(term.size() == para_out_dof());
135 return parametrization_.apply_jacobian(term, x);
136 }
137
142
144 {
145 Eigen::MatrixXd V;
146 varforms_[0]->get_vertices(V);
147
148 Eigen::VectorXd y = periodic_mesh_map_->inverse_eval(utils::flatten(V));
150 }
151
152 Eigen::VectorXd PeriodicShapeVariableToSimulation::apply_parametrization_jacobian(const Eigen::VectorXd &term, const Eigen::VectorXd &x) const
153 {
154 assert(term.size() == vertex_num_ * dim_);
155
156 const Eigen::VectorXd y = parametrization_.eval(x);
157 assert(y.size() == para_out_dof());
158
159 const Eigen::VectorXd reduced_term = periodic_mesh_map_->apply_jacobian(term, y);
160 assert(reduced_term.size() == para_out_dof());
161
162 return parametrization_.apply_jacobian(reduced_term, x);
163 }
164
166 {
167 return periodic_mesh_map_->input_size();
168 }
169
170} // namespace polyfem::solver
int V
int y
int x
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).
PeriodicShapeVariableToSimulation(VarFormPtrs varforms, DiffCachePtrs diff_caches, CompositeParametrization parametrizations)
Construct PeriodicShapeVariableToSimulation.
void update(const Eigen::VectorXd &x) override
Update forward simulation varforms from optimization variables.
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
Compute adjoint contribution of objective gradient.
void update_state_variables(const Eigen::VectorXd &x, Eigen::VectorXd &state_variables) const override
Update varform variables from optimization variables.
std::vector< std::shared_ptr< varform::DifferentiableVarForm > > VarFormPtrs
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.
int inverse_dof() const override
Compute optimization variables dof.
bool affects_varform(const varform::DifferentiableVarForm &target) const override
Return true if current var2sim maps to target varform.
Eigen::VectorXd inverse_eval() const override
Compute optimization variables from forward simulation varform::DifferentiableVarForm.
Optimization-facing interface implemented by differentiated VarForm adapters.
void dJ_periodic_shape_adjoint_term(const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache, const PeriodicMeshToMesh &periodic_mesh_map, const Eigen::VectorXd &periodic_mesh_representation, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &adjoint, Eigen::VectorXd &one_form)
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
Eigen::MatrixXd get_adjoint_mat(const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache, int type)
Get adjoint parameter nu or p.