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