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