207 const std::vector<std::shared_ptr<State>> &states,
208 const std::vector<std::shared_ptr<DiffCache>> &diff_caches,
209 const std::vector<int> &variable_sizes)
214 std::vector<std::shared_ptr<State>> rel_states;
215 std::vector<std::shared_ptr<DiffCache>> rel_diff_caches;
216 if (args[
"state"].is_array())
218 for (
int i : args[
"state"])
220 rel_states.push_back(states[i]);
221 rel_diff_caches.push_back(diff_caches[i]);
226 const int state_id = args[
"state"];
227 rel_states.push_back(states[state_id]);
228 rel_diff_caches.push_back(diff_caches[state_id]);
232 std::vector<std::shared_ptr<Parametrization>> map_list;
233 for (
const auto &arg : args[
"composition"])
240 std::string type = args[
"type"];
241 std::unique_ptr<VariableToSimulation> var2sim;
244 var2sim = std::make_unique<ShapeVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
246 else if (type ==
"elastic")
248 var2sim = std::make_unique<ElasticVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
250 else if (type ==
"friction")
252 var2sim = std::make_unique<FrictionCoeffientVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
254 else if (type ==
"damping")
256 var2sim = std::make_unique<DampingCoeffientVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
258 else if (type ==
"initial")
260 var2sim = std::make_unique<InitialConditionVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
262 else if (type ==
"dirichlet")
264 var2sim = std::make_unique<DirichletVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
266 else if (type ==
"dirichlet-nodes")
268 var2sim = std::make_unique<DirichletNodesVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
270 else if (type ==
"pressure")
272 var2sim = std::make_unique<PressureVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
274 else if (type ==
"periodic-shape")
276 var2sim = std::make_unique<PeriodicShapeVariableToSimulation>(std::move(rel_states), std::move(rel_diff_caches), std::move(compo));
283 var2sim->set_output_indexing(args);
306 const std::vector<std::shared_ptr<State>> &states,
307 const std::vector<std::shared_ptr<DiffCache>> &diff_caches)
311 std::shared_ptr<AdjointForm> obj;
314 std::vector<std::shared_ptr<AdjointForm>> forms;
315 for (
const auto &arg : args)
317 forms.push_back(
build_form(arg, var2sim, states, diff_caches));
320 obj = std::make_shared<SumCompositeForm>(var2sim, forms);
324 const std::string type = args[
"type"];
325 if (type ==
"transient_integral")
327 std::shared_ptr<StaticForm> static_obj =
328 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, states, diff_caches));
333 const auto &state = states[args[
"state"]];
334 obj = std::make_shared<TransientForm>(
335 var2sim, state->args[
"time"][
"time_steps"], state->args[
"time"][
"dt"],
336 args[
"integral_type"], args[
"steps"].get<std::vector<int>>(),
339 else if (type ==
"proxy_transient_integral")
341 std::shared_ptr<StaticForm> static_obj =
342 std::dynamic_pointer_cast<StaticForm>(
build_form(args[
"static_objective"], var2sim, states, diff_caches));
347 if (args[
"steps"].size() == 0)
351 const auto &state = states[args[
"state"]];
352 obj = std::make_shared<ProxyTransientForm>(
353 var2sim, state->args[
"time"][
"time_steps"], state->args[
"time"][
"dt"],
354 args[
"integral_type"], args[
"steps"].get<std::vector<int>>(),
357 else if (type ==
"power")
359 std::shared_ptr<AdjointForm> obj_aux =
360 build_form(args[
"objective"], var2sim, states, diff_caches);
361 obj = std::make_shared<PowerForm>(obj_aux, args[
"power"]);
363 else if (type ==
"divide")
365 std::shared_ptr<AdjointForm> obj1 =
366 build_form(args[
"objective"][0], var2sim, states, diff_caches);
367 std::shared_ptr<AdjointForm> obj2 =
368 build_form(args[
"objective"][1], var2sim, states, diff_caches);
369 std::vector<std::shared_ptr<AdjointForm>> objs({obj1, obj2});
370 obj = std::make_shared<DivideForm>(objs);
372 else if (type ==
"plus-const")
374 obj = std::make_shared<PlusConstCompositeForm>(
375 build_form(args[
"objective"], var2sim, states, diff_caches), args[
"value"]);
377 else if (type ==
"log")
379 obj = std::make_shared<LogCompositeForm>(
380 build_form(args[
"objective"], var2sim, states, diff_caches));
382 else if (type ==
"compliance")
384 obj = std::make_shared<ComplianceForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]],
387 else if (type ==
"acceleration")
389 obj = std::make_shared<AccelerationForm>(var2sim,
390 states[args[
"state"]], diff_caches[args[
"state"]], args);
392 else if (type ==
"kinetic")
394 obj = std::make_shared<AccelerationForm>(var2sim,
395 states[args[
"state"]], diff_caches[args[
"state"]], args);
397 else if (type ==
"target")
399 std::shared_ptr<TargetForm> tmp =
400 std::make_shared<TargetForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
401 auto reference_cached =
402 args[
"reference_cached_body_ids"].get<std::vector<int>>();
404 states[args[
"target_state"]],
405 diff_caches[args[
"target_state"]],
406 std::set(reference_cached.begin(), reference_cached.end()));
409 else if (type ==
"displacement-target")
411 std::shared_ptr<TargetForm> tmp =
412 std::make_shared<TargetForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
414 Eigen::VectorXd target_displacement;
415 target_displacement.setZero(states[args[
"state"]]->mesh->dimension());
416 if (target_displacement.size() != args[
"target_displacement"].size())
418 log_and_throw_error(
"Target displacement shape must match the dimension of the simulation");
420 for (
int i = 0; i < target_displacement.size(); ++i)
422 target_displacement(i) = args[
"target_displacement"][i].get<
double>();
424 if (args[
"active_dimension"].size() > 0)
426 if (target_displacement.size() != args[
"active_dimension"].size())
430 std::vector<bool> active_dimension_mask(args[
"active_dimension"].size());
431 for (
int i = 0; i < args[
"active_dimension"].size(); ++i)
433 active_dimension_mask[i] = args[
"active_dimension"][i].get<
bool>();
435 tmp->set_active_dimension(active_dimension_mask);
437 tmp->set_reference(target_displacement);
440 else if (type ==
"center-target")
442 obj = std::make_shared<BarycenterTargetForm>(
443 var2sim, args, states[args[
"state"]], diff_caches[args[
"state"]], states[args[
"target_state"]], diff_caches[args[
"target_state"]]);
445 else if (type ==
"sdf-target")
447 std::shared_ptr<SDFTargetForm> tmp = std::make_shared<SDFTargetForm>(
448 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
449 double delta = args[
"delta"].get<
double>();
450 if (!states[args[
"state"]]->mesh->is_volume())
453 Eigen::MatrixXd control_points(args[
"control_points"].size(), dim);
454 for (
int i = 0; i < control_points.rows(); ++i)
456 for (
int j = 0; j < control_points.cols(); ++j)
458 control_points(i, j) = args[
"control_points"][i][j].get<
double>();
461 Eigen::VectorXd knots(args[
"knots"].size());
462 for (
int i = 0; i < knots.size(); ++i)
464 knots(i) = args[
"knots"][i].get<
double>();
466 tmp->set_bspline_target(control_points, knots, delta);
471 Eigen::MatrixXd control_points_grid(args[
"control_points_grid"].size(), dim);
472 for (
int i = 0; i < control_points_grid.rows(); ++i)
474 for (
int j = 0; j < control_points_grid.cols(); ++j)
476 control_points_grid(i, j) = args[
"control_points_grid"][i][j].get<
double>();
479 Eigen::VectorXd knots_u(args[
"knots_u"].size());
480 for (
int i = 0; i < knots_u.size(); ++i)
482 knots_u(i) = args[
"knots_u"][i].get<
double>();
484 Eigen::VectorXd knots_v(args[
"knots_v"].size());
485 for (
int i = 0; i < knots_v.size(); ++i)
487 knots_v(i) = args[
"knots_v"][i].get<
double>();
489 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
494 else if (type ==
"mesh-target")
496 std::shared_ptr<MeshTargetForm> tmp = std::make_shared<MeshTargetForm>(
497 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
498 double delta = args[
"delta"].get<
double>();
500 std::string mesh_path =
501 states[args[
"state"]]->resolve_input_path(args[
"mesh_path"].get<std::string>());
503 Eigen::MatrixXi E,
F;
509 tmp->set_surface_mesh_target(
V,
F, delta);
512 else if (type ==
"function-target")
514 std::shared_ptr<TargetForm> tmp =
515 std::make_shared<TargetForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
516 tmp->set_reference(args[
"target_function"], args[
"target_function_gradient"]);
519 else if (type ==
"node-target")
521 obj = std::make_shared<NodeTargetForm>(states[args[
"state"]], diff_caches[args[
"state"]], var2sim, args);
523 else if (type ==
"min-dist-target")
525 obj = std::make_shared<MinTargetDistForm>(
526 var2sim, args[
"steps"], args[
"target"], args, states[args[
"state"]], diff_caches[args[
"state"]]);
528 else if (type ==
"position")
530 obj = std::make_shared<PositionForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
532 else if (type ==
"stress")
534 obj = std::make_shared<StressForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
536 else if (type ==
"stress_norm")
538 obj = std::make_shared<StressNormForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
540 else if (type ==
"dirichlet_energy")
542 obj = std::make_shared<DirichletEnergyForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
544 else if (type ==
"elastic_energy")
546 obj = std::make_shared<ElasticEnergyForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
548 else if (type ==
"quadratic_contact_force_norm")
550 obj = std::make_shared<ProxyContactForceForm>(
551 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
true, args);
553 else if (type ==
"log_contact_force_norm")
555 obj = std::make_shared<ProxyContactForceForm>(
556 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"],
false, args);
558 else if (type ==
"max_stress")
560 obj = std::make_shared<MaxStressForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
562 else if (type ==
"smooth_contact_force_norm")
565 obj = std::make_shared<SmoothContactForceForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
567 else if (type ==
"volume")
569 obj = std::make_shared<VolumeForm>(var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args);
571 else if (type ==
"soft_constraint")
573 std::vector<std::shared_ptr<AdjointForm>> forms({
build_form(args[
"objective"], var2sim, states, diff_caches)});
574 Eigen::VectorXd bounds = args[
"soft_bound"];
575 obj = std::make_shared<InequalityConstraintForm>(forms, bounds, args[
"power"]);
577 else if (type ==
"min_jacobian")
579 obj = std::make_shared<MinJacobianForm>(var2sim, states[args[
"state"]]);
581 else if (type ==
"AMIPS")
583 obj = std::make_shared<AMIPSForm>(var2sim, states[args[
"state"]]);
585 else if (type ==
"boundary_smoothing")
587 if (args[
"surface_selection"].is_array())
589 obj = std::make_shared<BoundarySmoothingForm>(
590 var2sim, states[args[
"state"]], args[
"scale_invariant"],
591 args[
"power"], args[
"surface_selection"].get<std::vector<int>>(),
592 args[
"dimensions"].get<std::vector<int>>());
596 obj = std::make_shared<BoundarySmoothingForm>(
597 var2sim, states[args[
"state"]], args[
"scale_invariant"],
599 std::vector<int>{args[
"surface_selection"].get<
int>()},
600 args[
"dimensions"].get<std::vector<int>>());
603 else if (type ==
"collision_barrier")
605 obj = std::make_shared<CollisionBarrierForm>(
606 var2sim, states[args[
"state"]], args[
"dhat"]);
608 else if (type ==
"layer_thickness")
610 obj = std::make_shared<LayerThicknessForm>(
611 var2sim, states[args[
"state"]],
612 args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"]);
614 else if (type ==
"layer_thickness_log")
616 obj = std::make_shared<LayerThicknessForm>(
617 var2sim, states[args[
"state"]],
618 args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"],
true,
621 else if (type ==
"deformed_collision_barrier")
623 obj = std::make_shared<DeformedCollisionBarrierForm>(
624 var2sim, states[args[
"state"]], diff_caches[args[
"state"]], args[
"dhat"]);
626 else if (type ==
"parametrized_product")
628 std::vector<std::shared_ptr<Parametrization>> map_list;
629 for (
const auto &arg : args[
"parametrization"])
633 obj = std::make_shared<ParametrizedProductForm>(
641 obj->set_weight(args[
"weight"]);
642 if (args[
"print_energy"].get<std::string>() !=
"")
644 obj->enable_energy_print(args[
"print_energy"]);