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 ==
"elastic_energy")
100 obj = std::make_shared<ElasticEnergyForm>(var2sim, *state, args);
101 else if (obj_type ==
"max_stress")
102 obj = std::make_shared<MaxStressForm>(var2sim, *state, args);
103 else if (obj_type ==
"volume")
104 obj = std::make_shared<VolumeForm>(var2sim, *state, args);
105 else if (obj_type ==
"min_jacobian")
106 obj = std::make_shared<MinJacobianForm>(var2sim, *state);
107 else if (obj_type ==
"AMIPS")
108 obj = std::make_shared<AMIPSForm>(var2sim, *state);
109 else if (obj_type ==
"function-target")
111 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *state, args);
112 tmp->set_reference(args[
"target_function"], args[
"target_function_gradient"]);
115 else if (obj_type ==
"boundary_smoothing")
117 if (args[
"surface_selection"].is_array())
118 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *state, args[
"scale_invariant"], args[
"power"], args[
"surface_selection"].get<std::vector<int>>());
120 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *state, args[
"scale_invariant"], args[
"power"], std::vector<int>{args[
"surface_selection"].get<
int>()});
130 std::shared_ptr<AdjointForm> obj;
133 std::vector<std::shared_ptr<AdjointForm>> forms;
134 for (
const auto &arg : args)
135 forms.push_back(
create_form(arg, var2sim, states));
137 obj = std::make_shared<SumCompositeForm>(var2sim, forms);
141 const std::string type = args[
"type"];
142 if (type ==
"transient_integral")
144 std::shared_ptr<StaticForm> static_obj = std::dynamic_pointer_cast<StaticForm>(
create_form(args[
"static_objective"], var2sim, states));
147 const auto &state = states[args[
"state"]];
148 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);
150 else if (type ==
"proxy_transient_integral")
152 std::shared_ptr<StaticForm> static_obj = std::dynamic_pointer_cast<StaticForm>(
create_form(args[
"static_objective"], var2sim, states));
155 if (args[
"steps"].size() == 0)
157 const auto &state = states[args[
"state"]];
158 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);
160 else if (type ==
"power")
162 std::shared_ptr<AdjointForm> obj_aux =
create_form(args[
"objective"], var2sim, states);
163 obj = std::make_shared<PowerForm>(obj_aux, args[
"power"]);
165 else if (type ==
"divide")
167 std::shared_ptr<AdjointForm> obj1 =
create_form(args[
"objective"][0], var2sim, states);
168 std::shared_ptr<AdjointForm> obj2 =
create_form(args[
"objective"][1], var2sim, states);
169 std::vector<std::shared_ptr<AdjointForm>> objs({obj1, obj2});
170 obj = std::make_shared<DivideForm>(objs);
172 else if (type ==
"plus-const")
174 obj = std::make_shared<PlusConstCompositeForm>(
create_form(args[
"objective"], var2sim, states), args[
"value"]);
176 else if (type ==
"compliance")
178 obj = std::make_shared<ComplianceForm>(var2sim, *(states[args[
"state"]]), args);
180 else if (type ==
"acceleration")
182 obj = std::make_shared<AccelerationForm>(var2sim, *(states[args[
"state"]]), args);
184 else if (type ==
"kinetic")
186 obj = std::make_shared<AccelerationForm>(var2sim, *(states[args[
"state"]]), args);
188 else if (type ==
"target")
190 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
191 auto reference_cached = args[
"reference_cached_body_ids"].get<std::vector<int>>();
192 tmp->set_reference(states[args[
"target_state"]], std::set(reference_cached.begin(), reference_cached.end()));
195 else if (type ==
"displacement-target")
197 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
198 Eigen::VectorXd target_displacement;
199 target_displacement.setZero(states[args[
"state"]]->mesh->dimension());
200 if (target_displacement.size() != args[
"target_displacement"].size())
201 log_and_throw_error(
"Target displacement shape must match the dimension of the simulation");
202 for (
int i = 0; i < target_displacement.size(); ++i)
203 target_displacement(i) = args[
"target_displacement"][i].get<
double>();
204 if (args[
"active_dimension"].size() > 0)
206 if (target_displacement.size() != args[
"active_dimension"].size())
208 std::vector<bool> active_dimension_mask(args[
"active_dimension"].size());
209 for (
int i = 0; i < args[
"active_dimension"].size(); ++i)
210 active_dimension_mask[i] = args[
"active_dimension"][i].get<bool>();
211 tmp->set_active_dimension(active_dimension_mask);
213 tmp->set_reference(target_displacement);
216 else if (type ==
"center-target")
218 obj = std::make_shared<BarycenterTargetForm>(var2sim, args, states[args[
"state"]], states[args[
"target_state"]]);
220 else if (type ==
"sdf-target")
222 std::shared_ptr<SDFTargetForm> tmp = std::make_shared<SDFTargetForm>(var2sim, *(states[args[
"state"]]), args);
223 double delta = args[
"delta"].get<
double>();
224 if (!states[args[
"state"]]->mesh->is_volume())
227 Eigen::MatrixXd control_points(args[
"control_points"].size(), dim);
228 for (
int i = 0; i < control_points.rows(); ++i)
229 for (
int j = 0; j < control_points.cols(); ++j)
230 control_points(i, j) = args[
"control_points"][i][j].get<
double>();
231 Eigen::VectorXd knots(args[
"knots"].size());
232 for (
int i = 0; i < knots.size(); ++i)
233 knots(i) = args[
"knots"][i].get<
double>();
234 tmp->set_bspline_target(control_points, knots, delta);
239 Eigen::MatrixXd control_points_grid(args[
"control_points_grid"].size(), dim);
240 for (
int i = 0; i < control_points_grid.rows(); ++i)
241 for (
int j = 0; j < control_points_grid.cols(); ++j)
242 control_points_grid(i, j) = args[
"control_points_grid"][i][j].get<
double>();
243 Eigen::VectorXd knots_u(args[
"knots_u"].size());
244 for (
int i = 0; i < knots_u.size(); ++i)
245 knots_u(i) = args[
"knots_u"][i].get<
double>();
246 Eigen::VectorXd knots_v(args[
"knots_v"].size());
247 for (
int i = 0; i < knots_v.size(); ++i)
248 knots_v(i) = args[
"knots_v"][i].get<
double>();
249 tmp->set_bspline_target(control_points_grid, knots_u, knots_v, delta);
254 else if (type ==
"mesh-target")
256 std::shared_ptr<MeshTargetForm> tmp = std::make_shared<MeshTargetForm>(var2sim, *(states[args[
"state"]]), args);
257 double delta = args[
"delta"].get<
double>();
259 Eigen::MatrixXi E,
F;
263 tmp->set_surface_mesh_target(
V,
F, delta);
266 else if (type ==
"function-target")
268 std::shared_ptr<TargetForm> tmp = std::make_shared<TargetForm>(var2sim, *(states[args[
"state"]]), args);
269 tmp->set_reference(args[
"target_function"], args[
"target_function_gradient"]);
272 else if (type ==
"node-target")
274 obj = std::make_shared<NodeTargetForm>(*(states[args[
"state"]]), var2sim, args);
276 else if (type ==
"min-dist-target")
278 obj = std::make_shared<MinTargetDistForm>(var2sim, args[
"steps"], args[
"target"], args, states[args[
"state"]]);
280 else if (type ==
"position")
282 obj = std::make_shared<PositionForm>(var2sim, *(states[args[
"state"]]), args);
284 else if (type ==
"stress")
286 obj = std::make_shared<StressForm>(var2sim, *(states[args[
"state"]]), args);
288 else if (type ==
"stress_norm")
290 obj = std::make_shared<StressNormForm>(var2sim, *(states[args[
"state"]]), args);
292 else if (type ==
"elastic_energy")
294 obj = std::make_shared<ElasticEnergyForm>(var2sim, *(states[args[
"state"]]), args);
296 else if (type ==
"quadratic_contact_force_norm")
298 obj = std::make_shared<ProxyContactForceForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"],
true, args);
300 else if (type ==
"log_contact_force_norm")
302 obj = std::make_shared<ProxyContactForceForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"],
false, args);
304 else if (type ==
"max_stress")
306 obj = std::make_shared<MaxStressForm>(var2sim, *(states[args[
"state"]]), args);
308 else if (type ==
"volume")
310 obj = std::make_shared<VolumeForm>(var2sim, *(states[args[
"state"]]), args);
312 else if (type ==
"soft_constraint")
314 std::vector<std::shared_ptr<AdjointForm>> forms({
create_form(args[
"objective"], var2sim, states)});
315 Eigen::VectorXd bounds = args[
"soft_bound"];
316 obj = std::make_shared<InequalityConstraintForm>(forms, bounds, args[
"power"]);
318 else if (type ==
"min_jacobian")
320 obj = std::make_shared<MinJacobianForm>(var2sim, *(states[args[
"state"]]));
322 else if (type ==
"AMIPS")
324 obj = std::make_shared<AMIPSForm>(var2sim, *(states[args[
"state"]]));
326 else if (type ==
"boundary_smoothing")
328 if (args[
"surface_selection"].is_array())
329 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *(states[args[
"state"]]), args[
"scale_invariant"], args[
"power"], args[
"surface_selection"].get<std::vector<int>>());
331 obj = std::make_shared<BoundarySmoothingForm>(var2sim, *(states[args[
"state"]]), args[
"scale_invariant"], args[
"power"], std::vector<int>{args[
"surface_selection"].get<
int>()});
333 else if (type ==
"collision_barrier")
335 obj = std::make_shared<CollisionBarrierForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"]);
337 else if (type ==
"layer_thickness")
339 obj = std::make_shared<LayerThicknessForm>(var2sim, *(states[args[
"state"]]), args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"]);
341 else if (type ==
"layer_thickness_log")
343 obj = std::make_shared<LayerThicknessForm>(var2sim, *(states[args[
"state"]]), args[
"boundary_ids"].get<std::vector<int>>(), args[
"dhat"],
true, args[
"dmin"]);
345 else if (type ==
"deformed_collision_barrier")
347 obj = std::make_shared<DeformedCollisionBarrierForm>(var2sim, *(states[args[
"state"]]), args[
"dhat"]);
349 else if (type ==
"parametrized_product")
351 std::vector<std::shared_ptr<Parametrization>> map_list;
352 for (
const auto &arg : args[
"parametrization"])
359 obj->set_weight(args[
"weight"]);
360 if (args[
"print_energy"].get<std::string>() !=
"")
361 obj->enable_energy_print(args[
"print_energy"]);
369 std::shared_ptr<Parametrization> map;
370 const std::string type = args[
"type"];
371 if (type ==
"per-body-to-per-elem")
373 map = std::make_shared<PerBody2PerElem>(*(states[args[
"state"]]->mesh));
375 else if (type ==
"per-body-to-per-node")
377 map = std::make_shared<PerBody2PerNode>(*(states[args[
"state"]]->mesh), states[args[
"state"]]->bases, states[args[
"state"]]->n_bases);
379 else if (type ==
"E-nu-to-lambda-mu")
381 map = std::make_shared<ENu2LambdaMu>(args[
"is_volume"]);
383 else if (type ==
"slice")
385 if (args[
"from"] != -1 || args[
"to"] != -1)
386 map = std::make_shared<SliceMap>(args[
"from"], args[
"to"], args[
"last"]);
387 else if (args[
"parameter_index"] != -1)
389 int idx = args[
"parameter_index"].get<
int>();
392 for (
int i = 0; i < variable_sizes.size(); ++i)
397 to = from + variable_sizes[i];
399 cumulative += variable_sizes[i];
402 map = std::make_shared<SliceMap>(from, to, last);
407 else if (type ==
"exp")
409 map = std::make_shared<ExponentialMap>(args[
"from"], args[
"to"]);
411 else if (type ==
"scale")
413 map = std::make_shared<Scaling>(args[
"value"]);
415 else if (type ==
"power")
417 map = std::make_shared<PowerMap>(args[
"power"]);
419 else if (type ==
"append-values")
421 Eigen::VectorXd
vals = args[
"values"];
422 map = std::make_shared<InsertConstantMap>(
vals, args[
"start"]);
424 else if (type ==
"append-const")
426 map = std::make_shared<InsertConstantMap>(args[
"size"], args[
"value"], args[
"start"]);
428 else if (type ==
"linear-filter")
430 map = std::make_shared<LinearFilter>(*(states[args[
"state"]]->mesh), args[
"radius"]);
432 else if (type ==
"bounded-biharmonic-weights")
434 map = std::make_shared<BoundedBiharmonicWeights2Dto3D>(args[
"num_control_vertices"], args[
"num_vertices"], *states[args[
"state"]], args[
"allow_rotations"]);
436 else if (type ==
"scalar-velocity-parametrization")
438 map = std::make_shared<ScalarVelocityParametrization>(args[
"start_val"], args[
"dt"]);