176 const std::vector<std::shared_ptr<varform::DifferentiableVarForm>> &varforms,
177 const std::vector<int> &variable_sizes)
181 std::shared_ptr<Parametrization> map;
182 const std::string type = args[
"type"];
183 if (type ==
"per-body-to-per-elem")
185 map = std::make_shared<PerBody2PerElem>(varforms[args[
"state"]]->get_mesh());
187 else if (type ==
"per-body-to-per-node")
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);
194 else if (type ==
"E-nu-to-lambda-mu")
196 map = std::make_shared<ENu2LambdaMu>(args[
"is_volume"]);
198 else if (type ==
"slice")
200 if (args[
"from"] != -1 || args[
"to"] != -1)
202 map = std::make_shared<SliceMap>(args[
"from"], args[
"to"], args[
"last"]);
204 else if (args[
"parameter_index"] != -1)
206 int idx = args[
"parameter_index"].get<
int>();
209 for (
int i = 0; i < variable_sizes.size(); ++i)
214 to = from + variable_sizes[i];
216 cumulative += variable_sizes[i];
219 map = std::make_shared<SliceMap>(from, to, last);
226 else if (type ==
"exp")
228 map = std::make_shared<ExponentialMap>(args[
"from"], args[
"to"]);
230 else if (type ==
"scale")
232 map = std::make_shared<Scaling>(args[
"value"]);
234 else if (type ==
"power")
236 map = std::make_shared<PowerMap>(args[
"power"]);
238 else if (type ==
"append-values")
240 Eigen::VectorXd
vals = args[
"values"];
241 map = std::make_shared<InsertConstantMap>(
vals, args[
"start"]);
243 else if (type ==
"append-const")
245 map = std::make_shared<InsertConstantMap>(args[
"size"], args[
"value"], args[
"start"]);
247 else if (type ==
"linear-filter")
249 map = std::make_shared<LinearFilter>(varforms[args[
"state"]]->get_mesh(), args[
"radius"]);
251 else if (type ==
"bounded-biharmonic-weights")
253 map = std::make_shared<BoundedBiharmonicWeights2Dto3D>(
254 args[
"num_control_vertices"], args[
"num_vertices"],
255 *varforms[args[
"state"]], args[
"allow_rotations"]);
257 else if (type ==
"scalar-velocity-parametrization")
259 map = std::make_shared<ScalarVelocityParametrization>(args[
"start_val"], args[
"dt"]);
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)
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())
282 for (
int i : args[
"state"])
284 relevant_varforms.push_back(varforms[i]);
285 rel_diff_caches.push_back(diff_caches[i]);
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]);
296 std::vector<std::shared_ptr<Parametrization>> map_list;
297 for (
const auto &arg : args[
"composition"])
304 std::shared_ptr<VariableToSimulation> var2sim;
305 std::string var2sim_type = args[
"type"];
306 if (var2sim_type ==
"shape")
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]);
311 var2sim = std::make_shared<ShapeVariableToSimulation>(
312 std::move(relevant_varforms),
313 std::move(rel_diff_caches),
315 std::move(active_dimensions),
316 std::move(active_nodes));
318 else if (var2sim_type ==
"elastic")
320 var2sim = std::make_shared<ElasticVariableToSimulation>(
321 std::move(relevant_varforms),
322 std::move(rel_diff_caches),
325 else if (var2sim_type ==
"friction")
327 var2sim = std::make_shared<FrictionVariableToSimulation>(
328 std::move(relevant_varforms),
329 std::move(rel_diff_caches),
332 else if (var2sim_type ==
"damping")
334 var2sim = std::make_shared<DampingVariableToSimulation>(
335 std::move(relevant_varforms),
336 std::move(rel_diff_caches),
339 else if (var2sim_type ==
"initial")
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),
346 std::move(active_dofs));
348 else if (var2sim_type ==
"dirichlet-boundary")
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),
356 std::move(active_boundary_ids),
357 std::move(active_time_slices));
359 else if (var2sim_type ==
"dirichlet-nodes")
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),
366 std::move(active_nodes));
368 else if (var2sim_type ==
"pressure")
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),
376 std::move(active_boundary_ids),
377 std::move(active_time_slices));
379 else if (var2sim_type ==
"periodic-shape")
381 var2sim = std::make_shared<PeriodicShapeVariableToSimulation>(
382 std::move(relevant_varforms),
383 std::move(rel_diff_caches),
412 const std::vector<std::shared_ptr<varform::DifferentiableVarForm>> &varforms,
413 const std::vector<std::shared_ptr<DiffCache>> &diff_caches)
417 std::shared_ptr<AdjointForm> obj;
420 std::vector<std::shared_ptr<AdjointForm>> forms;
421 for (
const auto &arg : args)
423 forms.push_back(
build_form(arg, var2sim, varforms, diff_caches));
426 obj = std::make_shared<SumCompositeForm>(var2sim, forms);
430 const std::string type = args[
"type"];
431 if (type ==
"transient_integral")
433 std::shared_ptr<StaticForm> static_obj =
434 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, varforms, diff_caches));
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>>(),
445 else if (type ==
"proxy_transient_integral")
447 std::shared_ptr<StaticForm> static_obj =
448 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, varforms, diff_caches));
453 if (args[
"steps"].size() == 0)
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>>(),
463 else if (type ==
"power")
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"]);
469 else if (type ==
"divide")
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);
478 else if (type ==
"plus-const")
480 obj = std::make_shared<PlusConstCompositeForm>(
481 build_form(args[
"objective"], var2sim, varforms, diff_caches), args[
"value"]);
483 else if (type ==
"log")
485 obj = std::make_shared<LogCompositeForm>(
486 build_form(args[
"objective"], var2sim, varforms, diff_caches));
488 else if (type ==
"compliance")
490 obj = std::make_shared<ComplianceForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]],
493 else if (type ==
"acceleration")
495 obj = std::make_shared<AccelerationForm>(var2sim,
496 varforms[args[
"state"]], diff_caches[args[
"state"]], args);
498 else if (type ==
"kinetic")
500 obj = std::make_shared<AccelerationForm>(var2sim,
501 varforms[args[
"state"]], diff_caches[args[
"state"]], args);
503 else if (type ==
"target")
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>>();
510 varforms[args[
"target_state"]],
511 diff_caches[args[
"target_state"]],
512 std::set(reference_cached.begin(), reference_cached.end()));
515 else if (type ==
"displacement-target")
517 std::shared_ptr<TargetForm> tmp =
518 std::make_shared<TargetForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
520 Eigen::VectorXd target_displacement;
521 target_displacement.setZero(varforms[args[
"state"]]->get_mesh().dimension());
522 if (target_displacement.size() != args[
"target_displacement"].size())
524 log_and_throw_error(
"Target displacement shape must match the dimension of the simulation");
526 for (
int i = 0; i < target_displacement.size(); ++i)
528 target_displacement(i) = args[
"target_displacement"][i].get<
double>();
530 if (args[
"active_dimension"].size() > 0)
532 if (target_displacement.size() != args[
"active_dimension"].size())
536 std::vector<bool> active_dimension_mask(args[
"active_dimension"].size());
537 for (
int i = 0; i < args[
"active_dimension"].size(); ++i)
539 active_dimension_mask[i] = args[
"active_dimension"][i].get<
bool>();
541 tmp->set_active_dimension(active_dimension_mask);
543 tmp->set_reference(target_displacement);
546 else if (type ==
"center-target")
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"]]);
551 else if (type ==
"sdf-target")
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())
559 Eigen::MatrixXd control_points(args[
"control_points"].size(), dim);
560 for (
int i = 0; i < control_points.rows(); ++i)
562 for (
int j = 0; j < control_points.cols(); ++j)
564 control_points(i, j) = args[
"control_points"][i][j].get<
double>();
567 Eigen::VectorXd knots(args[
"knots"].size());
568 for (
int i = 0; i < knots.size(); ++i)
570 knots(i) = args[
"knots"][i].get<
double>();
572 tmp->set_bspline_target(control_points, knots, delta);
577 Eigen::MatrixXd control_points_grid(args[
"control_points_grid"].size(), dim);
578 for (
int i = 0; i < control_points_grid.rows(); ++i)
580 for (
int j = 0; j < control_points_grid.cols(); ++j)
582 control_points_grid(i, j) = args[
"control_points_grid"][i][j].get<
double>();
585 Eigen::VectorXd knots_u(args[
"knots_u"].size());
586 for (
int i = 0; i < knots_u.size(); ++i)
588 knots_u(i) = args[
"knots_u"][i].get<
double>();
590 Eigen::VectorXd knots_v(args[
"knots_v"].size());
591 for (
int i = 0; i < knots_v.size(); ++i)
593 knots_v(i) = args[
"knots_v"][i].get<
double>();
595 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
600 else if (type ==
"mesh-target")
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>();
606 std::string mesh_path =
607 varforms[args[
"state"]]->input_path(args[
"mesh_path"].get<std::string>());
609 Eigen::MatrixXi E,
F;
615 tmp->set_surface_mesh_target(
V,
F, delta);
618 else if (type ==
"function-target")
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"]);
625 else if (type ==
"node-target")
627 obj = std::make_shared<NodeTargetForm>(varforms[args[
"state"]], diff_caches[args[
"state"]], var2sim, args);
629 else if (type ==
"min-dist-target")
631 obj = std::make_shared<MinTargetDistForm>(
632 var2sim, args[
"steps"], args[
"target"], args, varforms[args[
"state"]], diff_caches[args[
"state"]]);
634 else if (type ==
"position")
636 obj = std::make_shared<PositionForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
638 else if (type ==
"stress")
640 obj = std::make_shared<StressForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
642 else if (type ==
"stress_norm")
644 obj = std::make_shared<StressNormForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
646 else if (type ==
"dirichlet_energy")
648 obj = std::make_shared<DirichletEnergyForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
650 else if (type ==
"elastic_energy")
652 obj = std::make_shared<ElasticEnergyForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
654 else if (type ==
"quadratic_contact_force_norm")
656 obj = std::make_shared<ProxyContactForceForm>(
657 var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
true, args);
659 else if (type ==
"log_contact_force_norm")
661 obj = std::make_shared<ProxyContactForceForm>(
662 var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
false, args);
664 else if (type ==
"max_stress")
666 obj = std::make_shared<MaxStressForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
668 else if (type ==
"smooth_contact_force_norm")
671 obj = std::make_shared<SmoothContactForceForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
673 else if (type ==
"volume")
675 obj = std::make_shared<VolumeForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
677 else if (type ==
"soft_constraint")
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"]);
683 else if (type ==
"min_jacobian")
685 obj = std::make_shared<MinJacobianForm>(var2sim, varforms[args[
"state"]]);
687 else if (type ==
"AMIPS")
689 obj = std::make_shared<AMIPSForm>(var2sim, varforms[args[
"state"]]);
691 else if (type ==
"boundary_smoothing")
693 if (args[
"surface_selection"].is_array())
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>>());
702 obj = std::make_shared<BoundarySmoothingForm>(
703 var2sim, varforms[args[
"state"]], args[
"scale_invariant"],
705 std::vector<int>{args[
"surface_selection"].get<
int>()},
706 args[
"dimensions"].get<std::vector<int>>());
709 else if (type ==
"collision_barrier")
711 obj = std::make_shared<CollisionBarrierForm>(
712 var2sim, varforms[args[
"state"]], args[
"dhat"]);
714 else if (type ==
"layer_thickness")
716 obj = std::make_shared<LayerThicknessForm>(
717 var2sim, varforms[args[
"state"]],
718 args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"]);
720 else if (type ==
"layer_thickness_log")
722 obj = std::make_shared<LayerThicknessForm>(
723 var2sim, varforms[args[
"state"]],
724 args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"],
true,
727 else if (type ==
"deformed_collision_barrier")
729 obj = std::make_shared<DeformedCollisionBarrierForm>(
730 var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"]);
732 else if (type ==
"parametrized_product")
734 std::vector<std::shared_ptr<Parametrization>> map_list;
735 for (
const auto &arg : args[
"parametrization"])
739 obj = std::make_shared<ParametrizedProductForm>(
747 obj->set_weight(args[
"weight"]);
748 if (args[
"print_energy"].get<std::string>() !=
"")
750 obj->enable_energy_print(args[
"print_energy"]);