84 std::shared_ptr<AdjointForm> obj;
87 if (obj_type ==
"compliance")
88 obj = std::make_shared<ComplianceForm>(var2sim, *state, args);
89 else if (obj_type ==
"acceleration")
90 obj = std::make_shared<AccelerationForm>(var2sim, *state, args);
91 else if (obj_type ==
"kinetic")
92 obj = std::make_shared<AccelerationForm>(var2sim, *state, args);
93 else if (obj_type ==
"position")
94 obj = std::make_shared<PositionForm>(var2sim, *state, args);
95 else if (obj_type ==
"stress")
96 obj = std::make_shared<StressForm>(var2sim, *state, args);
97 else if (obj_type ==
"stress_norm")
98 obj = std::make_shared<StressNormForm>(var2sim, *state, args);
99 else if (obj_type ==
"dirichlet_energy")
100 obj = std::make_shared<DirichletEnergyForm>(var2sim, *state, args);
101 else if (obj_type ==
"elastic_energy")
102 obj = std::make_shared<ElasticEnergyForm>(var2sim, *state, args);
103 else if (obj_type ==
"max_stress")
104 obj = std::make_shared<MaxStressForm>(var2sim, *state, args);
105 else if (obj_type ==
"volume")
106 obj = std::make_shared<VolumeForm>(var2sim, *state, args);
107 else if (obj_type ==
"min_jacobian")
108 obj = std::make_shared<MinJacobianForm>(var2sim, *state);
109 else if (obj_type ==
"AMIPS")
110 obj = std::make_shared<AMIPSForm>(var2sim, *state);
111 else if (obj_type ==
"layer_thickness")
112 obj = std::make_shared<LayerThicknessForm>(var2sim, *state, args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"]);
113 else if (obj_type ==
"layer_thickness_log")
114 obj = std::make_shared<LayerThicknessForm>(var2sim, *state, args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"],
true, args[
"dmin"]);
115 else if (obj_type ==
"function-target")
117 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *state, args);
118 tmp->set_reference(args[
"target_function"], args[
"target_function_gradient"]);
121 else if (obj_type ==
"boundary_smoothing")
123 if (args[
"surface_selection"].is_array())
124 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *state, args[
"scale_invariant"], args[
"power"], args[
"surface_selection"].get<std::vector<int>>(), args[
"dimensions"].get<std::vector<int>>());
126 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *state, args[
"scale_invariant"], args[
"power"], std::vector<int>{args[
"surface_selection"].get<
int>()}, args[
"dimensions"].get<std::vector<int>>());
136 std::shared_ptr<AdjointForm> obj;
139 std::vector<std::shared_ptr<AdjointForm>> forms;
140 for (
const auto &arg : args)
141 forms.push_back(
create_form(arg, var2sim, states));
143 obj = std::make_shared<SumCompositeForm>(var2sim, forms);
147 const std::string type = args[
"type"];
148 if (type ==
"transient_integral")
150 std::shared_ptr<StaticForm> static_obj = std::dynamic_pointer_cast<StaticForm>(
create_form(args[
"static_objective"], var2sim, states));
153 const auto &state = states[args[
"state"]];
154 obj = std::make_shared<TransientForm>(var2sim, state->args[
"time"][
"time_steps"], state->args[
"time"][
"dt"], args[
"integral_type"], args[
"steps"].get<std::vector<int>>(), static_obj);
156 else if (type ==
"proxy_transient_integral")
158 std::shared_ptr<StaticForm> static_obj = std::dynamic_pointer_cast<StaticForm>(
create_form(args[
"static_objective"], var2sim, states));
161 if (args[
"steps"].size() == 0)
163 const auto &state = states[args[
"state"]];
164 obj = std::make_shared<ProxyTransientForm>(var2sim, state->args[
"time"][
"time_steps"], state->args[
"time"][
"dt"], args[
"integral_type"], args[
"steps"].get<std::vector<int>>(), static_obj);
166 else if (type ==
"power")
168 std::shared_ptr<AdjointForm> obj_aux =
create_form(args[
"objective"], var2sim, states);
169 obj = std::make_shared<PowerForm>(obj_aux, args[
"power"]);
171 else if (type ==
"divide")
173 std::shared_ptr<AdjointForm> obj1 =
create_form(args[
"objective"][0], var2sim, states);
174 std::shared_ptr<AdjointForm> obj2 =
create_form(args[
"objective"][1], var2sim, states);
175 std::vector<std::shared_ptr<AdjointForm>> objs({obj1, obj2});
176 obj = std::make_shared<DivideForm>(objs);
178 else if (type ==
"plus-const")
180 obj = std::make_shared<PlusConstCompositeForm>(
create_form(args[
"objective"], var2sim, states), args[
"value"]);
182 else if (type ==
"log")
184 obj = std::make_shared<LogCompositeForm>(
create_form(args[
"objective"], var2sim, states));
186 else if (type ==
"compliance")
188 obj = std::make_shared<ComplianceForm>(var2sim, *(states[args[
"state"]]), args);
190 else if (type ==
"acceleration")
192 obj = std::make_shared<AccelerationForm>(var2sim, *(states[args[
"state"]]), args);
194 else if (type ==
"kinetic")
196 obj = std::make_shared<AccelerationForm>(var2sim, *(states[args[
"state"]]), args);
198 else if (type ==
"target")
200 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
201 auto reference_cached = args[
"reference_cached_body_ids"].get<std::vector<int>>();
202 tmp->set_reference(states[args[
"target_state"]], std::set(reference_cached.begin(), reference_cached.end()));
205 else if (type ==
"displacement-target")
207 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
208 Eigen::VectorXd target_displacement;
209 target_displacement.setZero(states[args[
"state"]]->mesh->dimension());
210 if (target_displacement.size() != args[
"target_displacement"].size())
211 log_and_throw_error(
"Target displacement shape must match the dimension of the simulation");
212 for (
int i = 0; i < target_displacement.size(); ++i)
213 target_displacement(i) = args[
"target_displacement"][i].get<
double>();
214 if (args[
"active_dimension"].size() > 0)
216 if (target_displacement.size() != args[
"active_dimension"].size())
218 std::vector<bool> active_dimension_mask(args[
"active_dimension"].size());
219 for (
int i = 0; i < args[
"active_dimension"].size(); ++i)
220 active_dimension_mask[i] = args[
"active_dimension"][i].get<bool>();
221 tmp->set_active_dimension(active_dimension_mask);
223 tmp->set_reference(target_displacement);
226 else if (type ==
"center-target")
228 obj = std::make_shared<BarycenterTargetForm>(var2sim, args, states[args[
"state"]], states[args[
"target_state"]]);
230 else if (type ==
"sdf-target")
232 std::shared_ptr<SDFTargetForm> tmp = std::make_shared<SDFTargetForm>(var2sim, *(states[args[
"state"]]), args);
233 double delta = args[
"delta"].get<
double>();
234 if (!states[args[
"state"]]->mesh->is_volume())
237 Eigen::MatrixXd control_points(args[
"control_points"].size(), dim);
238 for (
int i = 0; i < control_points.rows(); ++i)
239 for (
int j = 0; j < control_points.cols(); ++j)
240 control_points(i, j) = args[
"control_points"][i][j].get<
double>();
241 Eigen::VectorXd knots(args[
"knots"].size());
242 for (
int i = 0; i < knots.size(); ++i)
243 knots(i) = args[
"knots"][i].get<
double>();
244 tmp->set_bspline_target(control_points, knots, delta);
249 Eigen::MatrixXd control_points_grid(args[
"control_points_grid"].size(), dim);
250 for (
int i = 0; i < control_points_grid.rows(); ++i)
251 for (
int j = 0; j < control_points_grid.cols(); ++j)
252 control_points_grid(i, j) = args[
"control_points_grid"][i][j].get<
double>();
253 Eigen::VectorXd knots_u(args[
"knots_u"].size());
254 for (
int i = 0; i < knots_u.size(); ++i)
255 knots_u(i) = args[
"knots_u"][i].get<
double>();
256 Eigen::VectorXd knots_v(args[
"knots_v"].size());
257 for (
int i = 0; i < knots_v.size(); ++i)
258 knots_v(i) = args[
"knots_v"][i].get<
double>();
259 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
264 else if (type ==
"mesh-target")
266 std::shared_ptr<MeshTargetForm> tmp = std::make_shared<MeshTargetForm>(var2sim, *(states[args[
"state"]]), args);
267 double delta = args[
"delta"].get<
double>();
269 Eigen::MatrixXi E,
F;
273 tmp->set_surface_mesh_target(
V,
F, delta);
276 else if (type ==
"function-target")
278 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
279 tmp->set_reference(args[
"target_function"], args[
"target_function_gradient"]);
282 else if (type ==
"node-target")
284 obj = std::make_shared<NodeTargetForm>(*(states[args[
"state"]]), var2sim, args);
286 else if (type ==
"min-dist-target")
288 obj = std::make_shared<MinTargetDistForm>(var2sim, args[
"steps"], args[
"target"], args, states[args[
"state"]]);
290 else if (type ==
"position")
292 obj = std::make_shared<PositionForm>(var2sim, *(states[args[
"state"]]), args);
294 else if (type ==
"stress")
296 obj = std::make_shared<StressForm>(var2sim, *(states[args[
"state"]]), args);
298 else if (type ==
"stress_norm")
300 obj = std::make_shared<StressNormForm>(var2sim, *(states[args[
"state"]]), args);
302 else if (type ==
"dirichlet_energy")
304 obj = std::make_shared<DirichletEnergyForm>(var2sim, *(states[args[
"state"]]), args);
306 else if (type ==
"elastic_energy")
308 obj = std::make_shared<ElasticEnergyForm>(var2sim, *(states[args[
"state"]]), args);
310 else if (type ==
"quadratic_contact_force_norm")
312 obj = std::make_shared<ProxyContactForceForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"],
true, args);
314 else if (type ==
"log_contact_force_norm")
316 obj = std::make_shared<ProxyContactForceForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"],
false, args);
318 else if (type ==
"max_stress")
320 obj = std::make_shared<MaxStressForm>(var2sim, *(states[args[
"state"]]), args);
322 else if (type ==
"smooth_contact_force_norm")
325 obj = std::make_shared<SmoothContactForceForm>(var2sim, *(states[args[
"state"]]), args);
327 else if (type ==
"volume")
329 obj = std::make_shared<VolumeForm>(var2sim, *(states[args[
"state"]]), args);
331 else if (type ==
"soft_constraint")
333 std::vector<std::shared_ptr<AdjointForm>> forms({
create_form(args[
"objective"], var2sim, states)});
334 Eigen::VectorXd bounds = args[
"soft_bound"];
335 obj = std::make_shared<InequalityConstraintForm>(forms, bounds, args[
"power"]);
337 else if (type ==
"min_jacobian")
339 obj = std::make_shared<MinJacobianForm>(var2sim, *(states[args[
"state"]]));
341 else if (type ==
"AMIPS")
343 obj = std::make_shared<AMIPSForm>(var2sim, *(states[args[
"state"]]));
345 else if (type ==
"boundary_smoothing")
347 if (args[
"surface_selection"].is_array())
348 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *(states[args[
"state"]]), args[
"scale_invariant"], args[
"power"], args[
"surface_selection"].get<std::vector<int>>(), args[
"dimensions"].get<std::vector<int>>());
350 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *(states[args[
"state"]]), args[
"scale_invariant"], args[
"power"], std::vector<int>{args[
"surface_selection"].get<
int>()}, args[
"dimensions"].get<std::vector<int>>());
352 else if (type ==
"collision_barrier")
354 obj = std::make_shared<CollisionBarrierForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"]);
356 else if (type ==
"layer_thickness")
358 obj = std::make_shared<LayerThicknessForm>(var2sim, *(states[args[
"state"]]), args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"]);
360 else if (type ==
"layer_thickness_log")
362 obj = std::make_shared<LayerThicknessForm>(var2sim, *(states[args[
"state"]]), args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"],
true, args[
"dmin"]);
364 else if (type ==
"deformed_collision_barrier")
366 obj = std::make_shared<DeformedCollisionBarrierForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"]);
368 else if (type ==
"parametrized_product")
370 std::vector<std::shared_ptr<Parametrization>> map_list;
371 for (
const auto &arg : args[
"parametrization"])
378 obj->set_weight(args[
"weight"]);
379 if (args[
"print_energy"].get<std::string>() !=
"")
380 obj->enable_energy_print(args[
"print_energy"]);
388 std::shared_ptr<Parametrization> map;
389 const std::string type = args[
"type"];
390 if (type ==
"per-body-to-per-elem")
392 map = std::make_shared<PerBody2PerElem>(*(states[args[
"state"]]->mesh));
394 else if (type ==
"per-body-to-per-node")
396 map = std::make_shared<PerBody2PerNode>(*(states[args[
"state"]]->mesh), states[args[
"state"]]->bases, states[args[
"state"]]->n_bases);
398 else if (type ==
"E-nu-to-lambda-mu")
400 map = std::make_shared<ENu2LambdaMu>(args[
"is_volume"]);
402 else if (type ==
"slice")
404 if (args[
"from"] != -1 || args[
"to"] != -1)
405 map = std::make_shared<SliceMap>(args[
"from"], args[
"to"], args[
"last"]);
406 else if (args[
"parameter_index"] != -1)
408 int idx = args[
"parameter_index"].get<
int>();
411 for (
int i = 0; i < variable_sizes.size(); ++i)
416 to = from + variable_sizes[i];
418 cumulative += variable_sizes[i];
421 map = std::make_shared<SliceMap>(from, to, last);
426 else if (type ==
"exp")
428 map = std::make_shared<ExponentialMap>(args[
"from"], args[
"to"]);
430 else if (type ==
"scale")
432 map = std::make_shared<Scaling>(args[
"value"]);
434 else if (type ==
"power")
436 map = std::make_shared<PowerMap>(args[
"power"]);
438 else if (type ==
"append-values")
440 Eigen::VectorXd
vals = args[
"values"];
441 map = std::make_shared<InsertConstantMap>(
vals, args[
"start"]);
443 else if (type ==
"append-const")
445 map = std::make_shared<InsertConstantMap>(args[
"size"], args[
"value"], args[
"start"]);
447 else if (type ==
"linear-filter")
449 map = std::make_shared<LinearFilter>(*(states[args[
"state"]]->mesh), args[
"radius"]);
451 else if (type ==
"bounded-biharmonic-weights")
453 map = std::make_shared<BoundedBiharmonicWeights2Dto3D>(args[
"num_control_vertices"], args[
"num_vertices"], *states[args[
"state"]], args[
"allow_rotations"]);
455 else if (type ==
"scalar-velocity-parametrization")
457 map = std::make_shared<ScalarVelocityParametrization>(args[
"start_val"], args[
"dt"]);