16#include <unordered_map>
28 Eigen::VectorXi active_boundary_ids,
29 Eigen::VectorXi active_time_slices)
30 : dim_(states[0]->mesh->dimension()),
32 states_(std::move(states)),
33 diff_caches_(std::move(diff_caches)),
34 parametrization_(std::move(parametrizations)),
35 active_boundary_ids_(std::move(active_boundary_ids)),
36 active_time_slices_(std::move(active_time_slices))
44 if (!s->problem->is_time_dependent())
46 log_and_throw_adjoint_error(
"Fail to construct dirichlet boundary variable to simulation. Reason: only transient simulations supported.");
59 auto boundary_dims =
states_[0]->boundary_conditions_ids(
"dirichlet_boundary");
62 for (
auto [
id, _] : boundary_dims)
91 return "dirichlet-boundary";
103 if (s.get() == &target)
119 auto tensor_problem = std::dynamic_pointer_cast<polyfem::assembler::GenericTensorProblem>(s->problem);
129 for (
int bi = 0; bi < boundary_num; ++bi)
132 int offset = (ti * boundary_num + bi) *
dim_;
133 tensor_problem->update_dirichlet_boundary(boundary_id, t,
y.segment(offset,
dim_));
147 Eigen::VectorXd term = Eigen::VectorXd::Zero(
para_out_dof());
149 for (
int si = 0; si <
states_.size(); ++si)
157 Eigen::VectorXd node_term;
160 int boundary_node_num = state->boundary_nodes.size();
161 assert(node_term.size() ==
time_steps_ * boundary_node_num);
168 auto seg = node_term.segment(
active_time_slices_(ti) * boundary_node_num, boundary_node_num);
171 for (
int d = 0; d <
dim_; ++d)
174 for (
int offset : map[bi][d])
179 term(boundary_count *
dim_ + d) += sum;
197 std::vector<json> boundary_jsons =
203 auto pred = [boundary_id](
const json &bc) {
return bc[
"id"].get<
int>() == boundary_id; };
204 auto iter = std::find_if(boundary_jsons.begin(), boundary_jsons.end(), pred);
205 if (iter == boundary_jsons.end())
212 const json &value = (*iter)[
"value"];
213 Eigen::MatrixXd dirichlet_mat;
216 dirichlet_mat = value;
218 catch (std::exception &err)
223 if (dirichlet_mat.rows() !=
dim_ || dirichlet_mat.cols() != required_cols)
225 logger().warn(
"Unsupported value type for dirichlet boundary id {}; inverse_eval falling back to zero.", boundary_id);
232 for (
int c = 0; c <
dim_; ++c)
235 y(boundary_count *
dim_ + c) = dirichlet_mat(c, slice + 1);
257 std::unordered_map<int, int> active_boundary_id_offset;
266 for (
int si = 0; si <
states_.size(); ++si)
271 std::unordered_map<int, int> boundary_node_offset;
292 int e = lb.element_id();
295 for (
int i = 0; i < lb.size(); ++i)
297 int primitive_global_id = lb.global_primitive_id(i);
298 int boundary_id = state.
mesh->get_boundary_id(primitive_global_id);
301 auto iter = active_boundary_id_offset.find(boundary_id);
302 if (iter == active_boundary_id_offset.end())
306 int boundary_offset = iter->second;
310 for (
int geom_node : geom_nodes)
313 auto &local_to_globals = bs.
bases[geom_node].global();
314 for (
auto &lg : local_to_globals)
316 for (
int c = 0; c <
dim_; ++c)
318 int fe_dof = lg.index *
dim_ + c;
321 auto iter = boundary_node_offset.find(fe_dof);
322 assert(iter != boundary_node_offset.end() &&
"Expect boundary dof to exist in boundary_nodes");
323 map[boundary_offset][c].push_back(iter->second);
Stores the basis functions for a given element in a mesh (facet in 2d, cell in 3d).
Eigen::VectorXi local_nodes_for_primitive(const int local_index, const mesh::Mesh &mesh) const
std::vector< Basis > bases
one basis function per node in the element
main class that contains the polyfem solver and all its state
std::vector< mesh::LocalBoundary > local_boundary
mapping from elements to nodes for dirichlet boundary conditions
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
std::vector< int > boundary_nodes
list of boundary nodes
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).
std::vector< BoundaryNodeMap > boundary_node_maps_
boundary node map per state.
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::string name() const override
DiffCachePtrs diff_caches_
ParameterType parameter_type() const override
Eigen::VectorXi active_time_slices_
int inverse_dof() const override
Compute optimization variables dof.
bool affect_state(const legacy::State &target) const override
Return true if current var2sim maps to target state.
std::vector< std::shared_ptr< legacy::State > > StatePtrs
CompositeParametrization parametrization_
Eigen::VectorXi active_boundary_ids_
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 build_boundary_node_maps()
std::vector< std::vector< std::vector< int > > > BoundaryNodeMap
boundary order in this var2sim -> component (dim) -> offset in state.boundary_nodes
DirichletBoundaryVariableToSimulation(StatePtrs states, DiffCachePtrs diff_caches, CompositeParametrization parametrizations, Eigen::VectorXi active_boundary_ids, Eigen::VectorXi active_time_slices)
Construct DirichletBoundaryVariableToSimulation.
void update_state_variables(const Eigen::VectorXd &x, Eigen::VectorXd &state_variables) const override
Update state variables from optimization variables.
std::vector< std::shared_ptr< DiffCache > > DiffCachePtrs
bool is_active_time_slices_valid(const Eigen::VectorXi &active_time_slices, const std::vector< std::shared_ptr< legacy::State > > &states, std::string &reason)
Validate active time slices selection given states.
bool is_active_dirichlet_boundary_ids_valid(const Eigen::VectorXi &active_boundary_ids, const std::vector< std::shared_ptr< legacy::State > > &states, std::string &reason)
Validate active Dirichlet boundary ids selection given states.
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
spdlog::logger & logger()
Retrieves the current logger.
void log_and_throw_adjoint_error(const std::string &msg)
Eigen::MatrixXd get_adjoint_mat(const legacy::State &state, const DiffCache &diff_cache, int type)
Get adjoint parameter nu or p.