17 return std::make_unique<ShapeVariableToSimulation>(states, parametrization);
18 else if (type ==
"elastic")
19 return std::make_unique<ElasticVariableToSimulation>(states, parametrization);
20 else if (type ==
"friction")
21 return std::make_unique<FrictionCoeffientVariableToSimulation>(states, parametrization);
22 else if (type ==
"damping")
23 return std::make_unique<DampingCoeffientVariableToSimulation>(states, parametrization);
24 else if (type ==
"initial")
25 return std::make_unique<InitialConditionVariableToSimulation>(states, parametrization);
26 else if (type ==
"dirichlet")
27 return std::make_unique<DirichletVariableToSimulation>(states, parametrization);
28 else if (type ==
"dirichlet-nodes")
29 return std::make_unique<DirichletNodesVariableToSimulation>(states, parametrization);
30 else if (type ==
"pressure")
31 return std::make_unique<PressureVariableToSimulation>(states, parametrization);
32 else if (type ==
"periodic-shape")
33 return std::make_unique<PeriodicShapeVariableToSimulation>(states, parametrization);
36 return std::unique_ptr<VariableToSimulation>();
41 const std::string composite_map_type = args[
"composite_map_type"];
43 if (composite_map_type ==
"none")
47 else if (composite_map_type ==
"indices")
49 if (args[
"composite_map_indices"].is_string())
55 else if (args[
"composite_map_indices"].is_array())
72 ind.setLinSpaced(out_size, 0, out_size - 1);
77 return Eigen::VectorXi();
88 return Eigen::VectorXd();
98 std::vector<ValueType>().swap(
L);
99 for (
const auto &arg : args)
105 Eigen::VectorXd adjoint_term = Eigen::VectorXd::Zero(
x.size());
106 for (
const auto &v2s :
L)
107 adjoint_term += v2s->compute_adjoint_term(
x);
113 for (
const auto &v2s :
L)
115 if (v2s->get_parameter_type() != type)
118 const Eigen::VectorXd var = v2s->get_parametrization().eval(
x);
119 for (
const auto &state : v2s->get_states())
121 if (state.get() != state_ptr)
124 state_variable(v2s->get_output_indexing(
x)) = var;
131 Eigen::VectorXd gradv = Eigen::VectorXd::Zero(
x.size());
132 for (
const auto &v2s :
L)
134 if (v2s->get_parameter_type() != type)
137 for (
const auto &state : v2s->get_states())
139 if (state.get() != state_ptr)
142 gradv += v2s->apply_parametrization_jacobian(grad(),
x);
152 const int dim = state->mesh->dimension();
159 for (
int i = 0; i < indices.size(); ++i)
161 const int vid = indices(i) / dim;
162 Eigen::VectorXd p = state->mesh->point(vid);
163 p(indices(i) - vid * dim) = state_variable(i);
164 state->mesh->set_point(vid, p);
171 Eigen::VectorXd term, cur_term;
174 if (state->problem->is_time_dependent())
178 if (!state->is_homogenization())
184 if (term.size() != cur_term.size())
193 const int dim =
states_[0]->mesh->dimension();
194 const int npts =
states_[0]->mesh->n_vertices();
199 if (indices.size() == 0)
200 indices.setLinSpaced(npts * dim, 0, npts * dim - 1);
204 if (indices.maxCoeff() >=
V.size())
212 const std::string composite_map_type = args[
"composite_map_type"];
215 if (composite_map_type ==
"interior" || composite_map_type ==
"boundary" || composite_map_type ==
"boundary_excluding_surface")
217 std::vector<int> active_dimensions = args[
"active_dimensions"];
218 if (active_dimensions.size() == 0)
219 for (
int d = 0; d < state.
mesh->dimension(); d++)
220 active_dimensions.push_back(d);
222 if (composite_map_type ==
"interior")
227 else if (composite_map_type ==
"boundary")
232 else if (composite_map_type ==
"boundary_excluding_surface")
234 const std::vector<int> excluded_surfaces = args[
"surface_selection"];
247 const int n_elem = state->bases.size();
248 assert(n_elem * 2 == state_variable.size());
249 state->assembler->update_lame_params(state_variable.segment(0, n_elem), state_variable.segment(n_elem, n_elem));
254 Eigen::VectorXd term, cur_term;
257 if (state->problem->is_time_dependent())
262 if (term.size() != cur_term.size())
272 auto params_map = state.assembler->parameters();
274 auto search_lambda = params_map.find(
"lambda");
275 auto search_mu = params_map.find(
"mu");
276 if (search_lambda == params_map.end() || search_mu == params_map.end())
279 return Eigen::VectorXd();
282 Eigen::VectorXd lambdas(state.mesh->n_elements());
283 Eigen::VectorXd mus(state.mesh->n_elements());
284 for (
int e = 0; e < state.mesh->n_elements(); e++)
287 if (!state.mesh->is_volume())
289 const auto &mesh2d = *
dynamic_cast<mesh::Mesh2D *
>(state.mesh.get());
294 const auto &mesh3d = *
dynamic_cast<mesh::Mesh3D *
>(state.mesh.get());
297 lambdas(e) = search_lambda->second(RowVectorNd::Zero(state.mesh->dimension()), barycenter, 0., e);
298 mus(e) = search_mu->second(RowVectorNd::Zero(state.mesh->dimension()), barycenter, 0., e);
300 state.assembler->update_lame_params(lambdas, mus);
302 Eigen::VectorXd params(lambdas.size() + mus.size());
303 params << lambdas, mus;
310 assert(state_variable.size() == 1);
311 assert(state_variable(0) >= 0);
313 state->args[
"contact"][
"friction_coefficient"] = state_variable(0);
317 Eigen::VectorXd term, cur_term;
320 if (state->problem->is_time_dependent())
325 if (term.size() != cur_term.size())
335 return Eigen::VectorXd();
340 assert(state_variable.size() == 2);
341 json damping_param = {
342 {
"psi", state_variable(0)},
343 {
"phi", state_variable(1)},
347 if (!state->args[
"materials"].is_array())
349 state->args[
"materials"][
"psi"] = damping_param[
"psi"];
350 state->args[
"materials"][
"phi"] = damping_param[
"phi"];
354 for (
auto &arg : state->args[
"materials"])
356 arg[
"psi"] = damping_param[
"psi"];
357 arg[
"phi"] = damping_param[
"phi"];
361 if (state->damping_assembler)
362 state->damping_assembler->add_multimaterial(0, damping_param, state->units);
364 logger().info(
"[{}] Current params: {}, {}",
name(), state_variable(0), state_variable(1));
368 Eigen::VectorXd term, cur_term;
371 if (state->problem->is_time_dependent())
376 if (term.size() != cur_term.size())
386 return Eigen::VectorXd();
393 if (state_variable.size() != state->ndof() * 2)
395 log_and_throw_adjoint_error(
"[{}] Inconsistent number of parameters {} and number of dofs in forward {}!",
name(), state_variable.size(), state->ndof() * 2);
397 state->initial_sol_update = state_variable.head(state->ndof());
398 state->initial_vel_update = state_variable.tail(state->ndof());
403 Eigen::VectorXd term, cur_term;
406 if (state->problem->is_time_dependent())
411 if (term.size() != cur_term.size())
421 Eigen::MatrixXd sol, vel;
422 state.initial_solution(sol);
423 state.initial_velocity(vel);
425 Eigen::VectorXd
x(sol.size() + vel.size());
432 auto tensor_problem = std::dynamic_pointer_cast<polyfem::assembler::GenericTensorProblem>(
states_[0]->problem);
434 int dim =
states_[0]->mesh->dimension();
435 int num_steps = indices.size() / dim;
436 for (
int i = 0; i < num_steps; ++i)
438 tensor_problem->update_dirichlet_boundary(b, indices(i * dim) + 1, state_variable.segment(i * dim, dim));
445 Eigen::VectorXd term, cur_term;
448 if (state->problem->is_time_dependent())
453 if (term.size() != cur_term.size())
469 int dim =
states_[0]->mesh->dimension();
471 for (
const auto &b :
states_[0]->args[
"boundary_conditions"][
"dirichlet_boundary"])
474 auto value = b[
"value"];
475 if (value[0].is_array())
477 if (!
states_[0]->problem->is_time_dependent())
479 Eigen::MatrixXd dirichlet = value;
480 x.setZero(dirichlet.rows() * (dirichlet.cols() - 1));
481 for (
int j = 1; j < dirichlet.cols(); ++j)
482 x.segment((j - 1) * dim, dim) = dirichlet.col(j);
484 else if (value[0].is_number())
486 if (
states_[0]->problem->is_time_dependent())
491 else if (value.is_string())
500 const std::string composite_map_type = args[
"composite_map_type"];
502 if (composite_map_type ==
"time_step_indexing")
504 const int time_steps = state.
args[
"time"][
"time_steps"];
505 const int dim = state.
mesh->dimension();
508 for (
int i = 0; i < time_steps; ++i)
509 for (
int k = 0; k < dim; ++k)
522 assert(state_variable.size() == (state->mesh->dimension() *
dirichlet_nodes_.size()));
523 auto tensor_problem = std::dynamic_pointer_cast<polyfem::assembler::GenericTensorProblem>(state->problem);
524 assert(!state->problem->is_time_dependent());
527 logger().info(
"Updated dirichlet nodes");
533 Eigen::VectorXd term, cur_term;
536 if (state->problem->is_time_dependent())
541 if (term.size() != cur_term.size())
559 const std::string composite_map_type = args_[
"composite_map_type"];
560 if (composite_map_type !=
"indices")
568 std::vector<int> composite_map_indices = {};
570 for (
int k = 0; k < dim; ++k)
572 args_[
"composite_map_indices"] = composite_map_indices;
579 auto tensor_problem = std::dynamic_pointer_cast<polyfem::assembler::GenericTensorProblem>(
states_[0]->problem);
581 for (
int i = 0; i < indices.size(); ++i)
583 tensor_problem->update_pressure_boundary(b, indices(i) + 1, state_variable(i));
590 Eigen::VectorXd term, cur_term;
593 if (state->problem->is_time_dependent())
595 Eigen::MatrixXd adjoint_nu, adjoint_p;
596 adjoint_nu = state->get_adjoint_mat(1);
597 adjoint_p = state->get_adjoint_mat(0);
604 if (term.size() != cur_term.size())
623 for (
const auto &b :
states_[0]->args[
"boundary_conditions"][
"pressure_boundary"])
626 auto value = b[
"value"];
627 if (value.is_array())
629 if (!
states_[0]->problem->is_time_dependent())
631 Eigen::VectorXd pressures = value;
632 x = pressures.segment(1, pressures.size() - 1);
634 else if (value.is_number())
636 if (
states_[0]->problem->is_time_dependent())
641 else if (value.is_string())
651 const std::string composite_map_type = args[
"composite_map_type"];
653 if (composite_map_type ==
"time_step_indexing")
655 const int time_steps = state.
args[
"time"][
"time_steps"];
657 for (
int i = 0; i < time_steps; ++i)
668 Eigen::VectorXd term, cur_term;
671 if (state->problem->is_time_dependent())
679 if (term.size() != cur_term.size())
688 const int dim =
states_[0]->mesh->dimension();
694 const int n_verts = state->mesh->n_vertices();
696 for (
int i = 0; i < n_verts; i++)
697 state->set_mesh_vertex(i,
V.row(i));
702 const auto &state = *(
states_[0]);
705 state.get_vertices(
V);
707 if (!state.periodic_bc->all_direction_periodic())
main class that contains the polyfem solver and all its state
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
json args
main input arguments containing all defaults
std::string resolve_input_path(const std::string &path, const bool only_if_exists=false) const
Resolve input path relative to root_path() if the path is not absolute.
RowVectorNd face_barycenter(const int index) const override
face barycenter
virtual RowVectorNd cell_barycenter(const int c) const =0
cell barycenter
int size(const int x_size) const override
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad_full, const Eigen::VectorXd &x) const override
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) override
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
Eigen::VectorXd inverse_eval() override
void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
std::string name() const override
Eigen::VectorXd inverse_eval() override
void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
std::string name() const override
Eigen::VectorXi dirichlet_nodes_
void set_dirichlet_nodes(const Eigen::VectorXi &dirichlet_nodes)
std::string variable_to_string(const Eigen::VectorXd &variable)
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
void set_output_indexing(const json &args) override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
std::string variable_to_string(const Eigen::VectorXd &variable)
std::vector< int > dirichlet_boundaries_
std::string name() const override
void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
Eigen::VectorXd inverse_eval() override
void set_dirichlet_boundaries(const std::vector< int > &dirichlet_boundaries)
void set_output_indexing(const json &args) override
std::string name() const override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
Eigen::VectorXd inverse_eval() override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
std::string name() const override
Eigen::VectorXd inverse_eval() override
void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
Eigen::VectorXd inverse_eval() override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
std::string name() const override
void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
void update(const Eigen::VectorXd &x) override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
Eigen::VectorXd apply_parametrization_jacobian(const Eigen::VectorXd &term, const Eigen::VectorXd &x) const override
Eigen::VectorXd periodic_mesh_representation
Eigen::VectorXd inverse_eval() override
std::unique_ptr< PeriodicMeshToMesh > periodic_mesh_map
std::vector< int > pressure_boundaries_
void set_pressure_boundaries(const std::vector< int > &pressure_boundaries)
Eigen::VectorXd inverse_eval() override
std::string variable_to_string(const Eigen::VectorXd &variable)
void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
void set_output_indexing(const json &args) override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
virtual void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices) override
void set_output_indexing(const json &args) override
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const override
Eigen::VectorXd inverse_eval() override
const Eigen::VectorXi & get_output_indexing() const
void compute_state_variable(const ParameterType type, const State *state_ptr, const Eigen::VectorXd &x, Eigen::VectorXd &state_variable) const
Evaluate the variable to simulations and overwrite the state_variable based on x.
Eigen::VectorXd compute_adjoint_term(const Eigen::VectorXd &x) const
Computes the sum of adjoint terms for all VariableToSimulation.
virtual Eigen::VectorXd apply_parametrization_jacobian(const ParameterType type, const State *state_ptr, const Eigen::VectorXd &x, const std::function< Eigen::VectorXd()> &grad) const
Maps the partial gradient wrt.
void init(const json &args, const std::vector< std::shared_ptr< State > > &states, const std::vector< int > &variable_sizes)
std::vector< ValueType > L
virtual Eigen::VectorXd apply_parametrization_jacobian(const Eigen::VectorXd &term, const Eigen::VectorXd &x) const
CompositeParametrization parametrization_
virtual Eigen::VectorXd inverse_eval()
const std::vector< std::shared_ptr< State > > states_
virtual void update_state(const Eigen::VectorXd &state_variable, const Eigen::VectorXi &indices)
virtual void set_output_indexing(const json &args)
virtual std::string name() const =0
Eigen::VectorXi get_output_indexing(const Eigen::VectorXd &x) const
static std::unique_ptr< VariableToSimulation > create(const std::string &type, const std::vector< std::shared_ptr< State > > &states, CompositeParametrization &¶metrization)
Eigen::VectorXi output_indexing_
bool read_matrix(const std::string &path, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Reads a matrix from a file. Determines the file format based on the path's extension.
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.
spdlog::logger & logger()
Retrieves the current logger.
void log_and_throw_adjoint_error(const std::string &msg)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
void log_and_throw_error(const std::string &msg)
static std::unique_ptr< VariableToSimulation > create_variable_to_simulation(const json &args, const std::vector< std::shared_ptr< State > > &states, const std::vector< int > &variable_sizes)