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)
235 std::vector<std::shared_ptr<varform::DifferentiableVarForm>> relevant_varforms;
236 std::vector<std::shared_ptr<DiffCache>> rel_diff_caches;
238 if (args[
"state"].is_array())
240 resource_id = args[
"state"][0].get<
int>();
241 for (
int i : args[
"state"])
243 relevant_varforms.push_back(varforms[i]);
244 rel_diff_caches.push_back(diff_caches[i]);
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]);
256 std::vector<std::shared_ptr<Parametrization>> map_list;
257 for (
const auto &arg : args[
"composition"])
264 std::shared_ptr<VariableToSimulation> var2sim;
265 std::string var2sim_type = args[
"type"];
266 if (var2sim_type ==
"shape")
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());
271 var2sim = std::make_shared<ShapeVariableToSimulation>(
272 std::move(relevant_varforms),
273 std::move(rel_diff_caches),
275 std::move(active_dimensions),
276 std::move(active_nodes));
278 else if (var2sim_type ==
"elastic")
280 var2sim = std::make_shared<ElasticVariableToSimulation>(
281 std::move(relevant_varforms),
282 std::move(rel_diff_caches),
285 else if (var2sim_type ==
"friction")
287 var2sim = std::make_shared<FrictionVariableToSimulation>(
288 std::move(relevant_varforms),
289 std::move(rel_diff_caches),
292 else if (var2sim_type ==
"damping")
294 var2sim = std::make_shared<DampingVariableToSimulation>(
295 std::move(relevant_varforms),
296 std::move(rel_diff_caches),
299 else if (var2sim_type ==
"initial")
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),
306 std::move(active_dofs));
308 else if (var2sim_type ==
"dirichlet-boundary")
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),
316 std::move(active_boundary_ids),
317 std::move(active_time_slices));
319 else if (var2sim_type ==
"dirichlet-nodes")
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),
326 std::move(active_nodes));
328 else if (var2sim_type ==
"pressure")
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),
336 std::move(active_boundary_ids),
337 std::move(active_time_slices));
339 else if (var2sim_type ==
"periodic-shape")
341 var2sim = std::make_shared<PeriodicShapeVariableToSimulation>(
342 std::move(relevant_varforms),
343 std::move(rel_diff_caches),
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)
379 std::shared_ptr<AdjointForm> obj;
382 std::vector<std::shared_ptr<AdjointForm>> forms;
383 for (
const auto &arg : args)
385 forms.push_back(
build_form(arg, var2sim, varforms, diff_caches, resources));
388 obj = std::make_shared<SumCompositeForm>(var2sim, forms);
392 const std::string type = args[
"type"];
393 if (type ==
"transient_integral")
395 std::shared_ptr<StaticForm> static_obj =
396 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, varforms, diff_caches, resources));
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>>(),
407 else if (type ==
"proxy_transient_integral")
409 std::shared_ptr<StaticForm> static_obj =
410 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, varforms, diff_caches, resources));
415 if (args[
"steps"].size() == 0)
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>>(),
425 else if (type ==
"power")
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"]);
431 else if (type ==
"divide")
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);
440 else if (type ==
"plus-const")
442 obj = std::make_shared<PlusConstCompositeForm>(
443 build_form(args[
"objective"], var2sim, varforms, diff_caches, resources), args[
"value"]);
445 else if (type ==
"log")
447 obj = std::make_shared<LogCompositeForm>(
448 build_form(args[
"objective"], var2sim, varforms, diff_caches, resources));
450 else if (type ==
"compliance")
452 obj = std::make_shared<ComplianceForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]],
455 else if (type ==
"acceleration")
457 obj = std::make_shared<AccelerationForm>(var2sim,
458 varforms[args[
"state"]], diff_caches[args[
"state"]], args);
460 else if (type ==
"kinetic")
462 obj = std::make_shared<AccelerationForm>(var2sim,
463 varforms[args[
"state"]], diff_caches[args[
"state"]], args);
465 else if (type ==
"target")
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>>();
472 varforms[args[
"target_state"]],
473 diff_caches[args[
"target_state"]],
474 std::set(reference_cached.begin(), reference_cached.end()));
477 else if (type ==
"displacement-target")
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());
482 Eigen::VectorXd target_displacement;
483 target_displacement.setZero(varforms[args[
"state"]]->get_mesh().dimension());
484 if (target_displacement.size() != args[
"target_displacement"].size())
486 log_and_throw_error(
"Target displacement shape must match the dimension of the simulation");
488 for (
int i = 0; i < target_displacement.size(); ++i)
490 target_displacement(i) = args[
"target_displacement"][i].get<
double>();
492 if (args[
"active_dimension"].size() > 0)
494 if (target_displacement.size() != args[
"active_dimension"].size())
498 std::vector<bool> active_dimension_mask(args[
"active_dimension"].size());
499 for (
int i = 0; i < args[
"active_dimension"].size(); ++i)
501 active_dimension_mask[i] = args[
"active_dimension"][i].get<
bool>();
503 tmp->set_active_dimension(active_dimension_mask);
505 tmp->set_reference(target_displacement);
508 else if (type ==
"center-target")
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"]]);
513 else if (type ==
"sdf-target")
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())
521 Eigen::MatrixXd control_points(args[
"control_points"].size(), dim);
522 for (
int i = 0; i < control_points.rows(); ++i)
524 for (
int j = 0; j < control_points.cols(); ++j)
526 control_points(i, j) = args[
"control_points"][i][j].get<
double>();
529 Eigen::VectorXd knots(args[
"knots"].size());
530 for (
int i = 0; i < knots.size(); ++i)
532 knots(i) = args[
"knots"][i].get<
double>();
534 tmp->set_bspline_target(control_points, knots, delta);
539 Eigen::MatrixXd control_points_grid(args[
"control_points_grid"].size(), dim);
540 for (
int i = 0; i < control_points_grid.rows(); ++i)
542 for (
int j = 0; j < control_points_grid.cols(); ++j)
544 control_points_grid(i, j) = args[
"control_points_grid"][i][j].get<
double>();
547 Eigen::VectorXd knots_u(args[
"knots_u"].size());
548 for (
int i = 0; i < knots_u.size(); ++i)
550 knots_u(i) = args[
"knots_u"][i].get<
double>();
552 Eigen::VectorXd knots_v(args[
"knots_v"].size());
553 for (
int i = 0; i < knots_v.size(); ++i)
555 knots_v(i) = args[
"knots_v"][i].get<
double>();
557 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
562 else if (type ==
"mesh-target")
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>();
568 const auto surface =
mesh::MeshLoader(resources.at(args[
"state"].get<
int>()).get())
570 tmp->set_surface_mesh_target(surface.vertices, surface.faces, delta);
573 else if (type ==
"function-target")
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"]);
580 else if (type ==
"node-target")
582 obj = std::make_shared<NodeTargetForm>(varforms[args[
"state"]], diff_caches[args[
"state"]], var2sim, args, resources.at(args[
"state"].get<
int>()).get());
584 else if (type ==
"min-dist-target")
586 obj = std::make_shared<MinTargetDistForm>(
587 var2sim, args[
"steps"], args[
"target"], args, varforms[args[
"state"]], diff_caches[args[
"state"]]);
589 else if (type ==
"position")
591 obj = std::make_shared<PositionForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
593 else if (type ==
"stress")
595 obj = std::make_shared<StressForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
597 else if (type ==
"stress_norm")
599 obj = std::make_shared<StressNormForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
601 else if (type ==
"dirichlet_energy")
603 obj = std::make_shared<DirichletEnergyForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
605 else if (type ==
"elastic_energy")
607 obj = std::make_shared<ElasticEnergyForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
609 else if (type ==
"quadratic_contact_force_norm")
611 obj = std::make_shared<ProxyContactForceForm>(
612 var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
true, args);
614 else if (type ==
"log_contact_force_norm")
616 obj = std::make_shared<ProxyContactForceForm>(
617 var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
false, args);
619 else if (type ==
"max_stress")
621 obj = std::make_shared<MaxStressForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
623 else if (type ==
"smooth_contact_force_norm")
626 obj = std::make_shared<SmoothContactForceForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
628 else if (type ==
"volume")
630 obj = std::make_shared<VolumeForm>(var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], args);
632 else if (type ==
"soft_constraint")
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"]);
638 else if (type ==
"min_jacobian")
640 obj = std::make_shared<MinJacobianForm>(var2sim, varforms[args[
"state"]]);
642 else if (type ==
"AMIPS")
644 obj = std::make_shared<AMIPSForm>(
645 var2sim, varforms[args[
"state"]], resources.at(args[
"state"].get<
int>()).get());
647 else if (type ==
"boundary_smoothing")
649 if (args[
"surface_selection"].is_array())
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>>());
658 obj = std::make_shared<BoundarySmoothingForm>(
659 var2sim, varforms[args[
"state"]], args[
"scale_invariant"],
661 std::vector<int>{args[
"surface_selection"].get<
int>()},
662 args[
"dimensions"].get<std::vector<int>>());
665 else if (type ==
"elastic_material_smoothing")
667 obj = std::make_shared<ElasticMaterialSmoothingForm>(
668 var2sim, varforms[args[
"state"]],
669 args[
"volume_selection"].get<std::vector<int>>());
671 else if (type ==
"collision_barrier")
673 obj = std::make_shared<CollisionBarrierForm>(
674 var2sim, varforms[args[
"state"]], resources.at(args[
"state"].get<
int>()).get(), args[
"dhat"]);
676 else if (type ==
"layer_thickness")
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"]);
682 else if (type ==
"layer_thickness_log")
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,
689 else if (type ==
"deformed_collision_barrier")
691 obj = std::make_shared<DeformedCollisionBarrierForm>(
692 var2sim, varforms[args[
"state"]], diff_caches[args[
"state"]], resources.at(args[
"state"].get<
int>()).get(), args[
"dhat"]);
694 else if (type ==
"parametrized_product")
696 std::vector<std::shared_ptr<Parametrization>> map_list;
697 for (
const auto &arg : args[
"parametrization"])
701 obj = std::make_shared<ParametrizedProductForm>(
709 obj->set_weight(args[
"weight"]);
710 if (args[
"print_energy"].get<std::string>() !=
"")
712 obj->enable_energy_print(args[
"print_energy"]);