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)
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())
279 for (
int i : args[
"state"])
281 rel_states.push_back(states[i]);
282 rel_diff_caches.push_back(diff_caches[i]);
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]);
293 std::vector<std::shared_ptr<Parametrization>> map_list;
294 for (
const auto &arg : args[
"composition"])
301 std::shared_ptr<VariableToSimulation> var2sim;
302 std::string var2sim_type = args[
"type"];
303 if (var2sim_type ==
"shape")
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]);
308 var2sim = std::make_shared<ShapeVariableToSimulation>(
309 std::move(rel_states),
310 std::move(rel_diff_caches),
312 std::move(active_dimensions),
313 std::move(active_nodes));
315 else if (var2sim_type ==
"elastic")
317 var2sim = std::make_shared<ElasticVariableToSimulation>(
318 std::move(rel_states),
319 std::move(rel_diff_caches),
322 else if (var2sim_type ==
"friction")
324 var2sim = std::make_shared<FrictionVariableToSimulation>(
325 std::move(rel_states),
326 std::move(rel_diff_caches),
329 else if (var2sim_type ==
"damping")
331 var2sim = std::make_shared<DampingVariableToSimulation>(
332 std::move(rel_states),
333 std::move(rel_diff_caches),
336 else if (var2sim_type ==
"initial")
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),
343 std::move(active_dofs));
345 else if (var2sim_type ==
"dirichlet-boundary")
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),
353 std::move(active_boundary_ids),
354 std::move(active_time_slices));
356 else if (var2sim_type ==
"dirichlet-nodes")
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),
363 std::move(active_nodes));
365 else if (var2sim_type ==
"pressure")
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),
373 std::move(active_boundary_ids),
374 std::move(active_time_slices));
376 else if (var2sim_type ==
"periodic-shape")
378 var2sim = std::make_shared<PeriodicShapeVariableToSimulation>(
379 std::move(rel_states),
380 std::move(rel_diff_caches),
409 const std::vector<std::shared_ptr<legacy::State>> &states,
410 const std::vector<std::shared_ptr<DiffCache>> &diff_caches)
414 std::shared_ptr<AdjointForm> obj;
417 std::vector<std::shared_ptr<AdjointForm>> forms;
418 for (
const auto &arg : args)
420 forms.push_back(
build_form(arg, var2sim, states, diff_caches));
423 obj = std::make_shared<SumCompositeForm>(var2sim, forms);
427 const std::string type = args[
"type"];
428 if (type ==
"transient_integral")
430 std::shared_ptr<StaticForm> static_obj =
431 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, states, diff_caches));
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>>(),
442 else if (type ==
"proxy_transient_integral")
444 std::shared_ptr<StaticForm> static_obj =
445 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, states, diff_caches));
450 if (args[
"steps"].size() == 0)
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>>(),
460 else if (type ==
"power")
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"]);
466 else if (type ==
"divide")
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);
475 else if (type ==
"plus-const")
477 obj = std::make_shared<PlusConstCompositeForm>(
478 build_form(args[
"objective"], var2sim, states, diff_caches), args[
"value"]);
480 else if (type ==
"log")
482 obj = std::make_shared<LogCompositeForm>(
483 build_form(args[
"objective"], var2sim, states, diff_caches));
485 else if (type ==
"compliance")
487 obj = std::make_shared<ComplianceForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]],
490 else if (type ==
"acceleration")
492 obj = std::make_shared<AccelerationForm>(var2sim,
493 states[args[
"state"]], diff_caches[args[
"state"]], args);
495 else if (type ==
"kinetic")
497 obj = std::make_shared<AccelerationForm>(var2sim,
498 states[args[
"state"]], diff_caches[args[
"state"]], args);
500 else if (type ==
"target")
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>>();
507 states[args[
"target_state"]],
508 diff_caches[args[
"target_state"]],
509 std::set(reference_cached.begin(), reference_cached.end()));
512 else if (type ==
"displacement-target")
514 std::shared_ptr<TargetForm> tmp =
515 std::make_shared<TargetForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
517 Eigen::VectorXd target_displacement;
518 target_displacement.setZero(states[args[
"state"]]->mesh->dimension());
519 if (target_displacement.size() != args[
"target_displacement"].size())
521 log_and_throw_error(
"Target displacement shape must match the dimension of the simulation");
523 for (
int i = 0; i < target_displacement.size(); ++i)
525 target_displacement(i) = args[
"target_displacement"][i].get<
double>();
527 if (args[
"active_dimension"].size() > 0)
529 if (target_displacement.size() != args[
"active_dimension"].size())
533 std::vector<bool> active_dimension_mask(args[
"active_dimension"].size());
534 for (
int i = 0; i < args[
"active_dimension"].size(); ++i)
536 active_dimension_mask[i] = args[
"active_dimension"][i].get<
bool>();
538 tmp->set_active_dimension(active_dimension_mask);
540 tmp->set_reference(target_displacement);
543 else if (type ==
"center-target")
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"]]);
548 else if (type ==
"sdf-target")
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())
556 Eigen::MatrixXd control_points(args[
"control_points"].size(), dim);
557 for (
int i = 0; i < control_points.rows(); ++i)
559 for (
int j = 0; j < control_points.cols(); ++j)
561 control_points(i, j) = args[
"control_points"][i][j].get<
double>();
564 Eigen::VectorXd knots(args[
"knots"].size());
565 for (
int i = 0; i < knots.size(); ++i)
567 knots(i) = args[
"knots"][i].get<
double>();
569 tmp->set_bspline_target(control_points, knots, delta);
574 Eigen::MatrixXd control_points_grid(args[
"control_points_grid"].size(), dim);
575 for (
int i = 0; i < control_points_grid.rows(); ++i)
577 for (
int j = 0; j < control_points_grid.cols(); ++j)
579 control_points_grid(i, j) = args[
"control_points_grid"][i][j].get<
double>();
582 Eigen::VectorXd knots_u(args[
"knots_u"].size());
583 for (
int i = 0; i < knots_u.size(); ++i)
585 knots_u(i) = args[
"knots_u"][i].get<
double>();
587 Eigen::VectorXd knots_v(args[
"knots_v"].size());
588 for (
int i = 0; i < knots_v.size(); ++i)
590 knots_v(i) = args[
"knots_v"][i].get<
double>();
592 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
597 else if (type ==
"mesh-target")
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>();
603 std::string mesh_path =
604 states[args[
"state"]]->resolve_input_path(args[
"mesh_path"].get<std::string>());
606 Eigen::MatrixXi E,
F;
612 tmp->set_surface_mesh_target(
V,
F, delta);
615 else if (type ==
"function-target")
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"]);
622 else if (type ==
"node-target")
624 obj = std::make_shared<NodeTargetForm>(states[args[
"state"]], diff_caches[args[
"state"]], var2sim, args);
626 else if (type ==
"min-dist-target")
628 obj = std::make_shared<MinTargetDistForm>(
629 var2sim, args[
"steps"], args[
"target"], args, states[args[
"state"]], diff_caches[args[
"state"]]);
631 else if (type ==
"position")
633 obj = std::make_shared<PositionForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
635 else if (type ==
"stress")
637 obj = std::make_shared<StressForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
639 else if (type ==
"stress_norm")
641 obj = std::make_shared<StressNormForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
643 else if (type ==
"dirichlet_energy")
645 obj = std::make_shared<DirichletEnergyForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
647 else if (type ==
"elastic_energy")
649 obj = std::make_shared<ElasticEnergyForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
651 else if (type ==
"quadratic_contact_force_norm")
653 obj = std::make_shared<ProxyContactForceForm>(
654 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
true, args);
656 else if (type ==
"log_contact_force_norm")
658 obj = std::make_shared<ProxyContactForceForm>(
659 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
false, args);
661 else if (type ==
"max_stress")
663 obj = std::make_shared<MaxStressForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
665 else if (type ==
"smooth_contact_force_norm")
668 obj = std::make_shared<SmoothContactForceForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
670 else if (type ==
"volume")
672 obj = std::make_shared<VolumeForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
674 else if (type ==
"soft_constraint")
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"]);
680 else if (type ==
"min_jacobian")
682 obj = std::make_shared<MinJacobianForm>(var2sim, states[args[
"state"]]);
684 else if (type ==
"AMIPS")
686 obj = std::make_shared<AMIPSForm>(var2sim, states[args[
"state"]]);
688 else if (type ==
"boundary_smoothing")
690 if (args[
"surface_selection"].is_array())
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>>());
699 obj = std::make_shared<BoundarySmoothingForm>(
700 var2sim, states[args[
"state"]], args[
"scale_invariant"],
702 std::vector<int>{args[
"surface_selection"].get<
int>()},
703 args[
"dimensions"].get<std::vector<int>>());
706 else if (type ==
"collision_barrier")
708 obj = std::make_shared<CollisionBarrierForm>(
709 var2sim, states[args[
"state"]], args[
"dhat"]);
711 else if (type ==
"layer_thickness")
713 obj = std::make_shared<LayerThicknessForm>(
714 var2sim, states[args[
"state"]],
715 args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"]);
717 else if (type ==
"layer_thickness_log")
719 obj = std::make_shared<LayerThicknessForm>(
720 var2sim, states[args[
"state"]],
721 args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"],
true,
724 else if (type ==
"deformed_collision_barrier")
726 obj = std::make_shared<DeformedCollisionBarrierForm>(
727 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"]);
729 else if (type ==
"parametrized_product")
731 std::vector<std::shared_ptr<Parametrization>> map_list;
732 for (
const auto &arg : args[
"parametrization"])
736 obj = std::make_shared<ParametrizedProductForm>(
744 obj->set_weight(args[
"weight"]);
745 if (args[
"print_energy"].get<std::string>() !=
"")
747 obj->enable_energy_print(args[
"print_energy"]);