PolyFEM
Loading...
Searching...
No Matches
BuildFromJson.cpp
Go to the documentation of this file.
2
4#include <polyfem/State.hpp>
5#include <polyfem/Common.hpp>
6
8
12
14
26
38
42
43#include <Eigen/Core>
44#include <spdlog/fmt/fmt.h>
45
46#include <string>
47#include <memory>
48#include <cassert>
49#include <cstddef>
50#include <fstream>
51#include <set>
52#include <utility>
53#include <vector>
54
56{
57 namespace
58 {
59 Eigen::VectorXi eigen_vector_xi_from_json(const json &j)
60 {
61 auto tmp = j.get<std::vector<int>>();
62 Eigen::VectorXi out = Eigen::Map<Eigen::VectorXi>(tmp.data(), tmp.size());
63 return out;
64 }
65
66 Eigen::VectorXi eigen_vector_xi_from_file(const std::string &path, const io::ResourceIO &resources)
67 {
68 const Eigen::MatrixXi mat = resources.read_int_matrix(path);
69 return mat.reshaped();
70 }
71
72 Eigen::VectorXi parse_active_geometry_nodes(const json &j, const varform::DifferentiableVarForm &varform, const io::ResourceIO &resources)
73 {
74 if (j.is_array())
75 {
76 return eigen_vector_xi_from_json(j);
77 }
78 if (j.is_string())
79 {
80 return eigen_vector_xi_from_file(j.get<std::string>(), resources);
81 }
82
83 // Advanced selection.
84 std::string type = j["type"].get<std::string>();
85 auto selection = j["selection"].get<std::vector<int>>();
86 if (type == "interior")
87 {
88 return select_interior_nodes(varform, selection);
89 }
90 else if (type == "boundary")
91 {
92 return select_boundary_nodes(varform, selection);
93 }
94 else if (type == "boundary_excluding_surface")
95 {
96 return select_boundary_nodes_excluding_surfaces(varform, selection);
97 }
98 else
99 {
100 log_and_throw_adjoint_error("Unknown advanced active geometry selection type name {}.", type);
101 }
102 }
103
104 } // namespace
105
106 std::shared_ptr<varform::DifferentiableVarForm> build_differentiable_varform(
107 const json &args,
108 const io::ResourceIO &resources,
109 const size_t max_threads)
110 {
111 json in_args = args;
112 in_args["solver"]["max_threads"] = max_threads;
113
114 auto state = std::make_shared<State>();
115 state->init(in_args, resources, true, true);
116 state->load_mesh();
117 auto differentiable_varform =
118 std::dynamic_pointer_cast<varform::DifferentiableVarForm>(state->variational_formulation);
119 if (!differentiable_varform)
120 {
122 "Variational formulation {} does not support differentiable/adjoint optimization.",
123 state->variational_formulation->name());
124 }
125 differentiable_varform->prepare();
126 return std::shared_ptr<varform::DifferentiableVarForm>(
127 std::move(state), differentiable_varform.get());
128 }
129
130 std::shared_ptr<solver::Parametrization> build_parametrization(
131 const json &args,
132 const std::vector<std::shared_ptr<varform::DifferentiableVarForm>> &varforms,
133 const std::vector<int> &variable_sizes)
134 {
135 using namespace polyfem::solver;
136
137 std::shared_ptr<Parametrization> map;
138 const std::string type = args["type"];
139 if (type == "per-body-to-per-elem")
140 {
141 map = std::make_shared<PerBody2PerElem>(varforms[args["state"]]->get_mesh());
142 }
143 else if (type == "per-body-to-per-node")
144 {
145 const auto &varform = varforms[args["state"]];
146 map = std::make_shared<PerBody2PerNode>(varform->get_mesh(),
147 varform->primary_space().basis_list(),
148 varform->primary_space().n_bases);
149 }
150 else if (type == "E-nu-to-lambda-mu")
151 {
152 map = std::make_shared<ENu2LambdaMu>(args["is_volume"]);
153 }
154 else if (type == "slice")
155 {
156 if (args["from"] != -1 || args["to"] != -1)
157 {
158 map = std::make_shared<SliceMap>(args["from"], args["to"], args["last"]);
159 }
160 else if (args["parameter_index"] != -1)
161 {
162 int idx = args["parameter_index"].get<int>();
163 int from, to, last;
164 int cumulative = 0;
165 for (int i = 0; i < variable_sizes.size(); ++i)
166 {
167 if (i == idx)
168 {
169 from = cumulative;
170 to = from + variable_sizes[i];
171 }
172 cumulative += variable_sizes[i];
173 }
174 last = cumulative;
175 map = std::make_shared<SliceMap>(from, to, last);
176 }
177 else
178 {
179 log_and_throw_adjoint_error("Incorrect spec for SliceMap!");
180 }
181 }
182 else if (type == "exp")
183 {
184 map = std::make_shared<ExponentialMap>(args["from"], args["to"]);
185 }
186 else if (type == "scale")
187 {
188 map = std::make_shared<Scaling>(args["value"]);
189 }
190 else if (type == "power")
191 {
192 map = std::make_shared<PowerMap>(args["power"]);
193 }
194 else if (type == "append-values")
195 {
196 Eigen::VectorXd vals = args["values"];
197 map = std::make_shared<InsertConstantMap>(vals, args["start"]);
198 }
199 else if (type == "append-const")
200 {
201 map = std::make_shared<InsertConstantMap>(args["size"], args["value"], args["start"]);
202 }
203 else if (type == "linear-filter")
204 {
205 map = std::make_shared<LinearFilter>(varforms[args["state"]]->get_mesh(), args["radius"]);
206 }
207 else if (type == "bounded-biharmonic-weights")
208 {
209 map = std::make_shared<BoundedBiharmonicWeights2Dto3D>(
210 args["num_control_vertices"], args["num_vertices"],
211 *varforms[args["state"]], args["allow_rotations"]);
212 }
213 else if (type == "scalar-velocity-parametrization")
214 {
215 map = std::make_shared<ScalarVelocityParametrization>(args["start_val"], args["dt"]);
216 }
217 else
218 {
219 log_and_throw_adjoint_error("Unkown parametrization!");
220 }
221
222 return map;
223 }
224
225 std::shared_ptr<solver::VariableToSimulation> build_variable_to_simulation(
226 const json &args,
227 const std::vector<std::shared_ptr<varform::DifferentiableVarForm>> &varforms,
228 const std::vector<std::shared_ptr<DiffCache>> &diff_caches,
229 const std::vector<int> &variable_sizes,
230 const std::vector<std::reference_wrapper<const io::ResourceIO>> &resources)
231 {
232 using namespace polyfem::solver;
233
234 // Collect relevant varforms from the state-index JSON field.
235 std::vector<std::shared_ptr<varform::DifferentiableVarForm>> relevant_varforms;
236 std::vector<std::shared_ptr<DiffCache>> rel_diff_caches;
237 int resource_id;
238 if (args["state"].is_array())
239 {
240 resource_id = args["state"][0].get<int>();
241 for (int i : args["state"])
242 {
243 relevant_varforms.push_back(varforms[i]);
244 rel_diff_caches.push_back(diff_caches[i]);
245 }
246 }
247 else
248 {
249 const int varform_id = args["state"];
250 resource_id = varform_id;
251 relevant_varforms.push_back(varforms[varform_id]);
252 rel_diff_caches.push_back(diff_caches[varform_id]);
253 }
254
255 // Build all parametrizations.
256 std::vector<std::shared_ptr<Parametrization>> map_list;
257 for (const auto &arg : args["composition"])
258 {
259 map_list.push_back(build_parametrization(arg, varforms, variable_sizes));
260 }
261 CompositeParametrization compo{std::move(map_list)};
262
263 // Build VariableToSimulation.
264 std::shared_ptr<VariableToSimulation> var2sim;
265 std::string var2sim_type = args["type"];
266 if (var2sim_type == "shape")
267 {
268 Eigen::VectorXi active_dimensions = eigen_vector_xi_from_json(args["active_dimensions"]);
269 Eigen::VectorXi active_nodes = parse_active_geometry_nodes(args["active_geometry_nodes"], *relevant_varforms[0], resources.at(resource_id).get());
270
271 var2sim = std::make_shared<ShapeVariableToSimulation>(
272 std::move(relevant_varforms),
273 std::move(rel_diff_caches),
274 std::move(compo),
275 std::move(active_dimensions),
276 std::move(active_nodes));
277 }
278 else if (var2sim_type == "elastic")
279 {
280 var2sim = std::make_shared<ElasticVariableToSimulation>(
281 std::move(relevant_varforms),
282 std::move(rel_diff_caches),
283 std::move(compo));
284 }
285 else if (var2sim_type == "friction")
286 {
287 var2sim = std::make_shared<FrictionVariableToSimulation>(
288 std::move(relevant_varforms),
289 std::move(rel_diff_caches),
290 std::move(compo));
291 }
292 else if (var2sim_type == "damping")
293 {
294 var2sim = std::make_shared<DampingVariableToSimulation>(
295 std::move(relevant_varforms),
296 std::move(rel_diff_caches),
297 std::move(compo));
298 }
299 else if (var2sim_type == "initial")
300 {
301 Eigen::VectorXi active_dofs = eigen_vector_xi_from_json(args["active_dofs"]);
302 var2sim = std::make_shared<InitialConditionVariableToSimulation>(
303 std::move(relevant_varforms),
304 std::move(rel_diff_caches),
305 std::move(compo),
306 std::move(active_dofs));
307 }
308 else if (var2sim_type == "dirichlet-boundary")
309 {
310 Eigen::VectorXi active_boundary_ids = eigen_vector_xi_from_json(args["active_boundary_ids"]);
311 Eigen::VectorXi active_time_slices = eigen_vector_xi_from_json(args["active_time_slices"]);
312 var2sim = std::make_shared<DirichletBoundaryVariableToSimulation>(
313 std::move(relevant_varforms),
314 std::move(rel_diff_caches),
315 std::move(compo),
316 std::move(active_boundary_ids),
317 std::move(active_time_slices));
318 }
319 else if (var2sim_type == "dirichlet-nodes")
320 {
321 Eigen::VectorXi active_nodes = parse_active_geometry_nodes(args["active_geometry_nodes"], *relevant_varforms[0], resources.at(resource_id).get());
322 var2sim = std::make_shared<DirichletNodesVariableToSimulation>(
323 std::move(relevant_varforms),
324 std::move(rel_diff_caches),
325 std::move(compo),
326 std::move(active_nodes));
327 }
328 else if (var2sim_type == "pressure")
329 {
330 Eigen::VectorXi active_boundary_ids = eigen_vector_xi_from_json(args["active_boundary_ids"]);
331 Eigen::VectorXi active_time_slices = eigen_vector_xi_from_json(args["active_time_slices"]);
332 var2sim = std::make_shared<PressureBoundaryVariableToSimulation>(
333 std::move(relevant_varforms),
334 std::move(rel_diff_caches),
335 std::move(compo),
336 std::move(active_boundary_ids),
337 std::move(active_time_slices));
338 }
339 else if (var2sim_type == "periodic-shape")
340 {
341 var2sim = std::make_shared<PeriodicShapeVariableToSimulation>(
342 std::move(relevant_varforms),
343 std::move(rel_diff_caches),
344 std::move(compo));
345 }
346 else
347 {
348 log_and_throw_adjoint_error("Unknown variable to simulation name {}.", var2sim_type);
349 }
350
351 return var2sim;
352 }
353
355 const json &args,
356 const std::vector<std::shared_ptr<varform::DifferentiableVarForm>> &varforms,
357 const std::vector<std::shared_ptr<DiffCache>> &diff_caches,
358 const std::vector<int> &variable_sizes,
359 const std::vector<std::reference_wrapper<const io::ResourceIO>> &resources)
360 {
362 for (const auto &arg : args)
363 {
364 v2s_group.data.push_back(
365 build_variable_to_simulation(arg, varforms, diff_caches, variable_sizes, resources));
366 }
367 return v2s_group;
368 }
369
370 std::shared_ptr<solver::AdjointForm> build_form(
371 const json &args,
373 const std::vector<std::shared_ptr<varform::DifferentiableVarForm>> &varforms,
374 const std::vector<std::shared_ptr<DiffCache>> &diff_caches,
375 const std::vector<std::reference_wrapper<const io::ResourceIO>> &resources)
376 {
377 using namespace polyfem::solver;
378
379 std::shared_ptr<AdjointForm> obj;
380 if (args.is_array())
381 {
382 std::vector<std::shared_ptr<AdjointForm>> forms;
383 for (const auto &arg : args)
384 {
385 forms.push_back(build_form(arg, var2sim, varforms, diff_caches, resources));
386 }
387
388 obj = std::make_shared<SumCompositeForm>(var2sim, forms);
389 }
390 else
391 {
392 const std::string type = args["type"];
393 if (type == "transient_integral")
394 {
395 std::shared_ptr<StaticForm> static_obj =
396 std::dynamic_pointer_cast<StaticForm>(build_form(args["static_objective"], var2sim, varforms, diff_caches, resources));
397 if (!static_obj)
398 {
399 log_and_throw_adjoint_error("Transient integral objective must have a static objective!");
400 }
401 const auto &varform = varforms[args["state"]];
402 obj = std::make_shared<TransientForm>(
403 var2sim, varform->get_args()["time"]["time_steps"], varform->get_args()["time"]["dt"],
404 args["integral_type"], args["steps"].get<std::vector<int>>(),
405 static_obj);
406 }
407 else if (type == "proxy_transient_integral")
408 {
409 std::shared_ptr<StaticForm> static_obj =
410 std::dynamic_pointer_cast<StaticForm>(build_form(args["static_objective"], var2sim, varforms, diff_caches, resources));
411 if (!static_obj)
412 {
413 log_and_throw_adjoint_error("Transient integral objective must have a static objective!");
414 }
415 if (args["steps"].size() == 0)
416 {
417 log_and_throw_adjoint_error("ProxyTransientForm requires non-empty \"steps\"!");
418 }
419 const auto &varform = varforms[args["state"]];
420 obj = std::make_shared<ProxyTransientForm>(
421 var2sim, varform->get_args()["time"]["time_steps"], varform->get_args()["time"]["dt"],
422 args["integral_type"], args["steps"].get<std::vector<int>>(),
423 static_obj);
424 }
425 else if (type == "power")
426 {
427 std::shared_ptr<AdjointForm> obj_aux =
428 build_form(args["objective"], var2sim, varforms, diff_caches, resources);
429 obj = std::make_shared<PowerForm>(obj_aux, args["power"]);
430 }
431 else if (type == "divide")
432 {
433 std::shared_ptr<AdjointForm> obj1 =
434 build_form(args["objective"][0], var2sim, varforms, diff_caches, resources);
435 std::shared_ptr<AdjointForm> obj2 =
436 build_form(args["objective"][1], var2sim, varforms, diff_caches, resources);
437 std::vector<std::shared_ptr<AdjointForm>> objs({obj1, obj2});
438 obj = std::make_shared<DivideForm>(objs);
439 }
440 else if (type == "plus-const")
441 {
442 obj = std::make_shared<PlusConstCompositeForm>(
443 build_form(args["objective"], var2sim, varforms, diff_caches, resources), args["value"]);
444 }
445 else if (type == "log")
446 {
447 obj = std::make_shared<LogCompositeForm>(
448 build_form(args["objective"], var2sim, varforms, diff_caches, resources));
449 }
450 else if (type == "compliance")
451 {
452 obj = std::make_shared<ComplianceForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]],
453 args);
454 }
455 else if (type == "acceleration")
456 {
457 obj = std::make_shared<AccelerationForm>(var2sim,
458 varforms[args["state"]], diff_caches[args["state"]], args);
459 }
460 else if (type == "kinetic")
461 {
462 obj = std::make_shared<AccelerationForm>(var2sim,
463 varforms[args["state"]], diff_caches[args["state"]], args);
464 }
465 else if (type == "target")
466 {
467 std::shared_ptr<TargetForm> tmp =
468 std::make_shared<TargetForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args, resources.at(args["state"].get<int>()).get());
469 auto reference_cached =
470 args["reference_cached_body_ids"].get<std::vector<int>>();
471 tmp->set_reference(
472 varforms[args["target_state"]],
473 diff_caches[args["target_state"]],
474 std::set(reference_cached.begin(), reference_cached.end()));
475 obj = tmp;
476 }
477 else if (type == "displacement-target")
478 {
479 std::shared_ptr<TargetForm> tmp =
480 std::make_shared<TargetForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args, resources.at(args["state"].get<int>()).get());
481
482 Eigen::VectorXd target_displacement;
483 target_displacement.setZero(varforms[args["state"]]->get_mesh().dimension());
484 if (target_displacement.size() != args["target_displacement"].size())
485 {
486 log_and_throw_error("Target displacement shape must match the dimension of the simulation");
487 }
488 for (int i = 0; i < target_displacement.size(); ++i)
489 {
490 target_displacement(i) = args["target_displacement"][i].get<double>();
491 }
492 if (args["active_dimension"].size() > 0)
493 {
494 if (target_displacement.size() != args["active_dimension"].size())
495 {
496 log_and_throw_error("Active dimension shape must match the dimension of the simulation");
497 }
498 std::vector<bool> active_dimension_mask(args["active_dimension"].size());
499 for (int i = 0; i < args["active_dimension"].size(); ++i)
500 {
501 active_dimension_mask[i] = args["active_dimension"][i].get<bool>();
502 }
503 tmp->set_active_dimension(active_dimension_mask);
504 }
505 tmp->set_reference(target_displacement);
506 obj = tmp;
507 }
508 else if (type == "center-target")
509 {
510 obj = std::make_shared<BarycenterTargetForm>(
511 var2sim, args, varforms[args["state"]], diff_caches[args["state"]], varforms[args["target_state"]], diff_caches[args["target_state"]]);
512 }
513 else if (type == "sdf-target")
514 {
515 std::shared_ptr<SDFTargetForm> tmp = std::make_shared<SDFTargetForm>(
516 var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
517 double delta = args["delta"].get<double>();
518 if (!varforms[args["state"]]->get_mesh().is_volume())
519 {
520 int dim = 2;
521 Eigen::MatrixXd control_points(args["control_points"].size(), dim);
522 for (int i = 0; i < control_points.rows(); ++i)
523 {
524 for (int j = 0; j < control_points.cols(); ++j)
525 {
526 control_points(i, j) = args["control_points"][i][j].get<double>();
527 }
528 }
529 Eigen::VectorXd knots(args["knots"].size());
530 for (int i = 0; i < knots.size(); ++i)
531 {
532 knots(i) = args["knots"][i].get<double>();
533 }
534 tmp->set_bspline_target(control_points, knots, delta);
535 }
536 else
537 {
538 int dim = 3;
539 Eigen::MatrixXd control_points_grid(args["control_points_grid"].size(), dim);
540 for (int i = 0; i < control_points_grid.rows(); ++i)
541 {
542 for (int j = 0; j < control_points_grid.cols(); ++j)
543 {
544 control_points_grid(i, j) = args["control_points_grid"][i][j].get<double>();
545 }
546 }
547 Eigen::VectorXd knots_u(args["knots_u"].size());
548 for (int i = 0; i < knots_u.size(); ++i)
549 {
550 knots_u(i) = args["knots_u"][i].get<double>();
551 }
552 Eigen::VectorXd knots_v(args["knots_v"].size());
553 for (int i = 0; i < knots_v.size(); ++i)
554 {
555 knots_v(i) = args["knots_v"][i].get<double>();
556 }
557 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
558 }
559
560 obj = tmp;
561 }
562 else if (type == "mesh-target")
563 {
564 std::shared_ptr<MeshTargetForm> tmp = std::make_shared<MeshTargetForm>(
565 var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
566 double delta = args["delta"].get<double>();
567
568 const auto surface = mesh::MeshLoader(resources.at(args["state"].get<int>()).get())
569 .load_surface(args["mesh_path"].get<std::string>());
570 tmp->set_surface_mesh_target(surface.vertices, surface.faces, delta);
571 obj = tmp;
572 }
573 else if (type == "function-target")
574 {
575 std::shared_ptr<TargetForm> tmp =
576 std::make_shared<TargetForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args, resources.at(args["state"].get<int>()).get());
577 tmp->set_reference(args["target_function"], args["target_function_gradient"]);
578 obj = tmp;
579 }
580 else if (type == "node-target")
581 {
582 obj = std::make_shared<NodeTargetForm>(varforms[args["state"]], diff_caches[args["state"]], var2sim, args, resources.at(args["state"].get<int>()).get());
583 }
584 else if (type == "min-dist-target")
585 {
586 obj = std::make_shared<MinTargetDistForm>(
587 var2sim, args["steps"], args["target"], args, varforms[args["state"]], diff_caches[args["state"]]);
588 }
589 else if (type == "position")
590 {
591 obj = std::make_shared<PositionForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
592 }
593 else if (type == "stress")
594 {
595 obj = std::make_shared<StressForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
596 }
597 else if (type == "stress_norm")
598 {
599 obj = std::make_shared<StressNormForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
600 }
601 else if (type == "dirichlet_energy")
602 {
603 obj = std::make_shared<DirichletEnergyForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
604 }
605 else if (type == "elastic_energy")
606 {
607 obj = std::make_shared<ElasticEnergyForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
608 }
609 else if (type == "quadratic_contact_force_norm")
610 {
611 obj = std::make_shared<ProxyContactForceForm>(
612 var2sim, varforms[args["state"]], diff_caches[args["state"]], args["dhat"], true, args);
613 }
614 else if (type == "log_contact_force_norm")
615 {
616 obj = std::make_shared<ProxyContactForceForm>(
617 var2sim, varforms[args["state"]], diff_caches[args["state"]], args["dhat"], false, args);
618 }
619 else if (type == "max_stress")
620 {
621 obj = std::make_shared<MaxStressForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
622 }
623 else if (type == "smooth_contact_force_norm")
624 {
625 // assert(varforms[args["state"]]->args["contact"]["use_gcp_formulation"]);
626 obj = std::make_shared<SmoothContactForceForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
627 }
628 else if (type == "volume")
629 {
630 obj = std::make_shared<VolumeForm>(var2sim, varforms[args["state"]], diff_caches[args["state"]], args);
631 }
632 else if (type == "soft_constraint")
633 {
634 std::vector<std::shared_ptr<AdjointForm>> forms({build_form(args["objective"], var2sim, varforms, diff_caches, resources)});
635 Eigen::VectorXd bounds = args["soft_bound"];
636 obj = std::make_shared<InequalityConstraintForm>(forms, bounds, args["power"]);
637 }
638 else if (type == "min_jacobian")
639 {
640 obj = std::make_shared<MinJacobianForm>(var2sim, varforms[args["state"]]);
641 }
642 else if (type == "AMIPS")
643 {
644 obj = std::make_shared<AMIPSForm>(
645 var2sim, varforms[args["state"]], resources.at(args["state"].get<int>()).get());
646 }
647 else if (type == "boundary_smoothing")
648 {
649 if (args["surface_selection"].is_array())
650 {
651 obj = std::make_shared<BoundarySmoothingForm>(
652 var2sim, varforms[args["state"]], args["scale_invariant"],
653 args["power"], args["surface_selection"].get<std::vector<int>>(),
654 args["dimensions"].get<std::vector<int>>());
655 }
656 else
657 {
658 obj = std::make_shared<BoundarySmoothingForm>(
659 var2sim, varforms[args["state"]], args["scale_invariant"],
660 args["power"],
661 std::vector<int>{args["surface_selection"].get<int>()},
662 args["dimensions"].get<std::vector<int>>());
663 }
664 }
665 else if (type == "elastic_material_smoothing")
666 {
667 obj = std::make_shared<ElasticMaterialSmoothingForm>(
668 var2sim, varforms[args["state"]],
669 args["volume_selection"].get<std::vector<int>>());
670 }
671 else if (type == "collision_barrier")
672 {
673 obj = std::make_shared<CollisionBarrierForm>(
674 var2sim, varforms[args["state"]], resources.at(args["state"].get<int>()).get(), args["dhat"]);
675 }
676 else if (type == "layer_thickness")
677 {
678 obj = std::make_shared<LayerThicknessForm>(
679 var2sim, varforms[args["state"]], resources.at(args["state"].get<int>()).get(),
680 args["boundary_ids"].get<std::vector<int>>(), args["dhat"]);
681 }
682 else if (type == "layer_thickness_log")
683 {
684 obj = std::make_shared<LayerThicknessForm>(
685 var2sim, varforms[args["state"]], resources.at(args["state"].get<int>()).get(),
686 args["boundary_ids"].get<std::vector<int>>(), args["dhat"], true,
687 args["dmin"]);
688 }
689 else if (type == "deformed_collision_barrier")
690 {
691 obj = std::make_shared<DeformedCollisionBarrierForm>(
692 var2sim, varforms[args["state"]], diff_caches[args["state"]], resources.at(args["state"].get<int>()).get(), args["dhat"]);
693 }
694 else if (type == "parametrized_product")
695 {
696 std::vector<std::shared_ptr<Parametrization>> map_list;
697 for (const auto &arg : args["parametrization"])
698 {
699 map_list.push_back(build_parametrization(arg, varforms, {}));
700 }
701 obj = std::make_shared<ParametrizedProductForm>(
702 CompositeParametrization(std::move(map_list)));
703 }
704 else
705 {
706 log_and_throw_adjoint_error("Objective not implemented!");
707 }
708
709 obj->set_weight(args["weight"]);
710 if (args["print_energy"].get<std::string>() != "")
711 {
712 obj->enable_energy_print(args["print_energy"]);
713 }
714 }
715
716 return obj;
717 }
718
719} // namespace polyfem::from_json
ElementAssemblyValues vals
Definition Assembler.cpp:26
Read-only interface to a hierarchical collection of simulation resources.
virtual Eigen::MatrixXi read_int_matrix(const std::string &path) const =0
The only non-legacy decoder from a logical resource path to mesh data.
SurfaceMesh load_surface(const std::string &path) const
std::vector< std::shared_ptr< VariableToSimulation > > data
Optimization-facing interface implemented by differentiated VarForm adapters.
std::shared_ptr< varform::DifferentiableVarForm > build_differentiable_varform(const json &args, const io::ResourceIO &resources, const size_t max_threads)
std::shared_ptr< solver::VariableToSimulation > build_variable_to_simulation(const json &args, const std::vector< std::shared_ptr< varform::DifferentiableVarForm > > &varforms, const std::vector< std::shared_ptr< DiffCache > > &diff_caches, const std::vector< int > &variable_sizes, const std::vector< std::reference_wrapper< const io::ResourceIO > > &resources)
std::shared_ptr< solver::Parametrization > build_parametrization(const json &args, const std::vector< std::shared_ptr< varform::DifferentiableVarForm > > &varforms, const std::vector< int > &variable_sizes)
solver::VariableToSimulationGroup build_variable_to_simulation_group(const json &args, const std::vector< std::shared_ptr< varform::DifferentiableVarForm > > &varforms, const std::vector< std::shared_ptr< DiffCache > > &diff_caches, const std::vector< int > &variable_sizes, const std::vector< std::reference_wrapper< const io::ResourceIO > > &resources)
std::shared_ptr< solver::AdjointForm > build_form(const json &args, const solver::VariableToSimulationGroup &var2sim, const std::vector< std::shared_ptr< varform::DifferentiableVarForm > > &varforms, const std::vector< std::shared_ptr< DiffCache > > &diff_caches, const std::vector< std::reference_wrapper< const io::ResourceIO > > &resources)
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
Eigen::VectorXi select_boundary_nodes_excluding_surfaces(const varform::DifferentiableVarForm &varform, const std::vector< int > &exclude_surface_selections)
Select all boundary nodes (vertex id) except surface.
Eigen::VectorXi select_boundary_nodes(const varform::DifferentiableVarForm &varform, const std::vector< int > &surface_selection)
Select boundary nodes (vertex id).
Eigen::VectorXi select_interior_nodes(const varform::DifferentiableVarForm &varform, const std::vector< int > &volume_selection)
Select interior nodes (vertex id).
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73