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>>());
126 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *state, args[
"scale_invariant"], args[
"power"], std::vector<int>{args[
"surface_selection"].get<
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 ==
"compliance")
184 obj = std::make_shared<ComplianceForm>(var2sim, *(states[args[
"state"]]), args);
186 else if (type ==
"acceleration")
188 obj = std::make_shared<AccelerationForm>(var2sim, *(states[args[
"state"]]), args);
190 else if (type ==
"kinetic")
192 obj = std::make_shared<AccelerationForm>(var2sim, *(states[args[
"state"]]), args);
194 else if (type ==
"target")
196 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
197 auto reference_cached = args[
"reference_cached_body_ids"].get<std::vector<int>>();
198 tmp->set_reference(states[args[
"target_state"]], std::set(reference_cached.begin(), reference_cached.end()));
201 else if (type ==
"displacement-target")
203 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
204 Eigen::VectorXd target_displacement;
205 target_displacement.setZero(states[args[
"state"]]->mesh->dimension());
206 if (target_displacement.size() != args[
"target_displacement"].size())
207 log_and_throw_error(
"Target displacement shape must match the dimension of the simulation");
208 for (
int i = 0; i < target_displacement.size(); ++i)
209 target_displacement(i) = args[
"target_displacement"][i].get<
double>();
210 if (args[
"active_dimension"].size() > 0)
212 if (target_displacement.size() != args[
"active_dimension"].size())
214 std::vector<bool> active_dimension_mask(args[
"active_dimension"].size());
215 for (
int i = 0; i < args[
"active_dimension"].size(); ++i)
216 active_dimension_mask[i] = args[
"active_dimension"][i].get<bool>();
217 tmp->set_active_dimension(active_dimension_mask);
219 tmp->set_reference(target_displacement);
222 else if (type ==
"center-target")
224 obj = std::make_shared<BarycenterTargetForm>(var2sim, args, states[args[
"state"]], states[args[
"target_state"]]);
226 else if (type ==
"sdf-target")
228 std::shared_ptr<SDFTargetForm> tmp = std::make_shared<SDFTargetForm>(var2sim, *(states[args[
"state"]]), args);
229 double delta = args[
"delta"].get<
double>();
230 if (!states[args[
"state"]]->mesh->is_volume())
233 Eigen::MatrixXd control_points(args[
"control_points"].size(), dim);
234 for (
int i = 0; i < control_points.rows(); ++i)
235 for (
int j = 0; j < control_points.cols(); ++j)
236 control_points(i, j) = args[
"control_points"][i][j].get<
double>();
237 Eigen::VectorXd knots(args[
"knots"].size());
238 for (
int i = 0; i < knots.size(); ++i)
239 knots(i) = args[
"knots"][i].get<
double>();
240 tmp->set_bspline_target(control_points, knots, delta);
245 Eigen::MatrixXd control_points_grid(args[
"control_points_grid"].size(), dim);
246 for (
int i = 0; i < control_points_grid.rows(); ++i)
247 for (
int j = 0; j < control_points_grid.cols(); ++j)
248 control_points_grid(i, j) = args[
"control_points_grid"][i][j].get<
double>();
249 Eigen::VectorXd knots_u(args[
"knots_u"].size());
250 for (
int i = 0; i < knots_u.size(); ++i)
251 knots_u(i) = args[
"knots_u"][i].get<
double>();
252 Eigen::VectorXd knots_v(args[
"knots_v"].size());
253 for (
int i = 0; i < knots_v.size(); ++i)
254 knots_v(i) = args[
"knots_v"][i].get<
double>();
255 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
260 else if (type ==
"mesh-target")
262 std::shared_ptr<MeshTargetForm> tmp = std::make_shared<MeshTargetForm>(var2sim, *(states[args[
"state"]]), args);
263 double delta = args[
"delta"].get<
double>();
265 Eigen::MatrixXi E,
F;
269 tmp->set_surface_mesh_target(
V,
F, delta);
272 else if (type ==
"function-target")
274 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
275 tmp->set_reference(args[
"target_function"], args[
"target_function_gradient"]);
278 else if (type ==
"node-target")
280 obj = std::make_shared<NodeTargetForm>(*(states[args[
"state"]]), var2sim, args);
282 else if (type ==
"min-dist-target")
284 obj = std::make_shared<MinTargetDistForm>(var2sim, args[
"steps"], args[
"target"], args, states[args[
"state"]]);
286 else if (type ==
"position")
288 obj = std::make_shared<PositionForm>(var2sim, *(states[args[
"state"]]), args);
290 else if (type ==
"stress")
292 obj = std::make_shared<StressForm>(var2sim, *(states[args[
"state"]]), args);
294 else if (type ==
"stress_norm")
296 obj = std::make_shared<StressNormForm>(var2sim, *(states[args[
"state"]]), args);
298 else if (type ==
"dirichlet_energy")
300 obj = std::make_shared<DirichletEnergyForm>(var2sim, *(states[args[
"state"]]), args);
302 else if (type ==
"elastic_energy")
304 obj = std::make_shared<ElasticEnergyForm>(var2sim, *(states[args[
"state"]]), args);
306 else if (type ==
"quadratic_contact_force_norm")
308 obj = std::make_shared<ProxyContactForceForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"],
true, args);
310 else if (type ==
"log_contact_force_norm")
312 obj = std::make_shared<ProxyContactForceForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"],
false, args);
314 else if (type ==
"max_stress")
316 obj = std::make_shared<MaxStressForm>(var2sim, *(states[args[
"state"]]), args);
318 else if (type ==
"volume")
320 obj = std::make_shared<VolumeForm>(var2sim, *(states[args[
"state"]]), args);
322 else if (type ==
"soft_constraint")
324 std::vector<std::shared_ptr<AdjointForm>> forms({
create_form(args[
"objective"], var2sim, states)});
325 Eigen::VectorXd bounds = args[
"soft_bound"];
326 obj = std::make_shared<InequalityConstraintForm>(forms, bounds, args[
"power"]);
328 else if (type ==
"min_jacobian")
330 obj = std::make_shared<MinJacobianForm>(var2sim, *(states[args[
"state"]]));
332 else if (type ==
"AMIPS")
334 obj = std::make_shared<AMIPSForm>(var2sim, *(states[args[
"state"]]));
336 else if (type ==
"boundary_smoothing")
338 if (args[
"surface_selection"].is_array())
339 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *(states[args[
"state"]]), args[
"scale_invariant"], args[
"power"], args[
"surface_selection"].get<std::vector<int>>());
341 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *(states[args[
"state"]]), args[
"scale_invariant"], args[
"power"], std::vector<int>{args[
"surface_selection"].get<
int>()});
343 else if (type ==
"collision_barrier")
345 obj = std::make_shared<CollisionBarrierForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"]);
347 else if (type ==
"layer_thickness")
349 obj = std::make_shared<LayerThicknessForm>(var2sim, *(states[args[
"state"]]), args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"]);
351 else if (type ==
"layer_thickness_log")
353 obj = std::make_shared<LayerThicknessForm>(var2sim, *(states[args[
"state"]]), args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"],
true, args[
"dmin"]);
355 else if (type ==
"deformed_collision_barrier")
357 obj = std::make_shared<DeformedCollisionBarrierForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"]);
359 else if (type ==
"parametrized_product")
361 std::vector<std::shared_ptr<Parametrization>> map_list;
362 for (
const auto &arg : args[
"parametrization"])
369 obj->set_weight(args[
"weight"]);
370 if (args[
"print_energy"].get<std::string>() !=
"")
371 obj->enable_energy_print(args[
"print_energy"]);
379 std::shared_ptr<Parametrization> map;
380 const std::string type = args[
"type"];
381 if (type ==
"per-body-to-per-elem")
383 map = std::make_shared<PerBody2PerElem>(*(states[args[
"state"]]->mesh));
385 else if (type ==
"per-body-to-per-node")
387 map = std::make_shared<PerBody2PerNode>(*(states[args[
"state"]]->mesh), states[args[
"state"]]->bases, states[args[
"state"]]->n_bases);
389 else if (type ==
"E-nu-to-lambda-mu")
391 map = std::make_shared<ENu2LambdaMu>(args[
"is_volume"]);
393 else if (type ==
"slice")
395 if (args[
"from"] != -1 || args[
"to"] != -1)
396 map = std::make_shared<SliceMap>(args[
"from"], args[
"to"], args[
"last"]);
397 else if (args[
"parameter_index"] != -1)
399 int idx = args[
"parameter_index"].get<
int>();
402 for (
int i = 0; i < variable_sizes.size(); ++i)
407 to = from + variable_sizes[i];
409 cumulative += variable_sizes[i];
412 map = std::make_shared<SliceMap>(from, to, last);
417 else if (type ==
"exp")
419 map = std::make_shared<ExponentialMap>(args[
"from"], args[
"to"]);
421 else if (type ==
"scale")
423 map = std::make_shared<Scaling>(args[
"value"]);
425 else if (type ==
"power")
427 map = std::make_shared<PowerMap>(args[
"power"]);
429 else if (type ==
"append-values")
431 Eigen::VectorXd
vals = args[
"values"];
432 map = std::make_shared<InsertConstantMap>(
vals, args[
"start"]);
434 else if (type ==
"append-const")
436 map = std::make_shared<InsertConstantMap>(args[
"size"], args[
"value"], args[
"start"]);
438 else if (type ==
"linear-filter")
440 map = std::make_shared<LinearFilter>(*(states[args[
"state"]]->mesh), args[
"radius"]);
442 else if (type ==
"bounded-biharmonic-weights")
444 map = std::make_shared<BoundedBiharmonicWeights2Dto3D>(args[
"num_control_vertices"], args[
"num_vertices"], *states[args[
"state"]], args[
"allow_rotations"]);
446 else if (type ==
"scalar-velocity-parametrization")
448 map = std::make_shared<ScalarVelocityParametrization>(args[
"start_val"], args[
"dt"]);