PolyFEM
Loading...
Searching...
No Matches
SolveData.cpp
Go to the documentation of this file.
1#include "SolveData.hpp"
2
29
30namespace
31{
32 ipc::NormalCollisions::CollisionSetType collision_set_type_from_string(const std::string &s)
33 {
34 if (s == "OGC")
35 return ipc::NormalCollisions::CollisionSetType::OGC;
36 if (s == "IMPROVED_MAX_APPROX")
37 return ipc::NormalCollisions::CollisionSetType::IMPROVED_MAX_APPROX;
38 return ipc::NormalCollisions::CollisionSetType::IPC;
39 }
40
41 std::shared_ptr<ipc::Barrier> barrier_from_string(const std::string &name)
42 {
43 if (name == "default")
44 return nullptr;
45 if (name == "log")
46 return std::make_shared<ipc::ClampedLogBarrier<>>();
47 if (name == "normalized_log")
48 return std::make_shared<ipc::NormalizedClampedLogBarrier<>>();
49 if (name == "linear_inverse")
50 return std::make_shared<ipc::InversePowerBarrier<>>(1.0);
51 if (name == "quadratic_inverse")
52 return std::make_shared<ipc::InversePowerBarrier<>>(2.0);
53 if (name == "two_stage")
54 return std::make_shared<ipc::TwoStageBarrier<>>();
55 polyfem::log_and_throw_error("Unknown barrier type: '{}'. Valid options: 'default', 'log', 'normalized_log', 'linear_inverse', 'quadratic_inverse', 'two_stage'.", name);
56 }
57} // namespace
58
59namespace polyfem::solver
60{
61 using namespace polyfem::time_integrator;
62
63 namespace
64 {
65 std::string constraint_child(const std::string &group, const std::string &name)
66 {
67 return group.empty() || group == "/" ? "/" + name : group + "/" + name;
68 }
69
70 template <typename Callback>
71 void with_constraint_resource(
72 const io::ResourceIO &resources,
73 const std::string &path,
74 Callback &&callback)
75 {
76 if (resources.is_group(path))
77 {
78 callback(resources, path);
79 return;
80 }
81
82 const io::HDF5IO constraint(resources.materialize(path));
83 callback(constraint, "/");
84 }
85 } // namespace
86
87 std::vector<std::shared_ptr<Form>> SolveData::init_forms(
88 // General
89 const Units &units,
90 const io::ResourceIO &resources,
91 const int dim,
92 const double t,
93 const Eigen::VectorXi &in_node_to_node,
94
95 // Elastic form
96 const int n_bases,
97 std::vector<basis::ElementBases> &bases,
98 const std::vector<basis::ElementBases> &geom_bases,
99 const assembler::Assembler &assembler,
100 assembler::AssemblyValsCache &ass_vals_cache,
101 const assembler::AssemblyValsCache &mass_ass_vals_cache,
102 const double jacobian_threshold,
103 const ElementInversionCheck check_inversion,
104 const unsigned conservative_max_iter,
105
106 // Body form
107 const int n_pressure_bases,
108 const std::vector<int> &boundary_nodes,
109 const std::vector<mesh::LocalBoundary> &local_boundary,
110 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
111 const QuadratureOrders &n_boundary_samples,
112 const Eigen::MatrixXd &rhs,
113 const Eigen::MatrixXd &sol,
114 const assembler::Density &density,
115
116 // Pressure form
117 const std::vector<mesh::LocalBoundary> &local_pressure_boundary,
118 const std::unordered_map<int, std::vector<mesh::LocalBoundary>> &local_pressure_cavity,
119 const std::shared_ptr<assembler::PressureAssembler> pressure_assembler,
120
121 // Inertia form
122 const bool ignore_inertia,
123 const StiffnessMatrix &mass,
124 const std::shared_ptr<assembler::ViscousDamping> damping_assembler,
125
126 // Lagged regularization form
127 const double lagged_regularization_weight,
128 const int lagged_regularization_iterations,
129
130 // Augemented lagrangian form
131 const size_t obstacle_ndof,
132 const std::vector<std::string> &hard_constraint_files,
133 const std::vector<json> &soft_constraint_files,
134 const json &zero_mean,
135
136 // Contact form
137 const bool contact_enabled,
138 const ipc::CollisionMesh &collision_mesh,
139 const double dhat,
140 const double avg_mass,
141 const bool use_area_weighting,
142 const bool use_improved_max_operator,
143 const bool use_physical_barrier,
144 const std::string &collision_set_type,
145 const bool skip_obstacles,
146 const std::string &barrier,
147 const json &barrier_stiffness,
148 const double initial_barrier_stiffness,
149 const double dhat_epsilon_scale,
150 const ipc::BroadPhaseMethod broad_phase,
151 const double ccd_tolerance,
152 const long ccd_max_iterations,
153 const bool enable_shape_derivatives,
154
155 // Smooth Contact Form
156 const bool use_gcp_formulation,
157 const double alpha_t,
158 const double alpha_n,
159 const bool use_adaptive_dhat,
160 const double min_distance_ratio,
161
162 // ESP contact form
163 const bool use_esp_formulation,
164 json esp_params,
165
166 // Normal Adhesion Form
167 const bool adhesion_enabled,
168 const double dhat_p,
169 const double dhat_a,
170 const double Y,
171
172 // Tangential Adhesion Form
173 const double tangential_adhesion_coefficient,
174 const double epsa,
175 const int tangential_adhesion_iterations,
176
177 // Homogenization
178 const assembler::MacroStrainValue &macro_strain_constraint,
179
180 // Periodic contact
181 const bool periodic_contact,
182 const Eigen::VectorXi &tiled_to_single,
183
184 // Friction form
185 const double friction_coefficient,
186 const double epsv,
187 const int friction_iterations,
188
189 // Rayleigh damping form
190 const json &rayleigh_damping,
191
192 // BC augmented-Lagrangian mass-metric lumping
193 const BCLumpingMode al_lumping,
194
195 // Boundary-ID periodic constraints
196 const mesh::Mesh *periodic_mesh,
197 const std::vector<mesh::LocalBoundary> *periodic_local_boundary,
198 const json &periodic_conditions,
199 const int fe_space_id)
200 {
201 const bool is_time_dependent = time_integrator != nullptr;
202 assert(!is_time_dependent || time_integrator != nullptr);
203 const double dt = is_time_dependent ? time_integrator->dt() : 0.0;
204 const int ndof = n_bases * dim;
205 // if (is_formulation_mixed) // mixed not supported
206 // ndof_ += n_pressure_bases; // pressure is a scalar
207 const bool is_volume = dim == 3;
208
209 std::vector<std::shared_ptr<Form>> forms;
210 al_form.clear();
211
212 elastic_form = std::make_shared<ElasticForm>(
213 n_bases, bases, geom_bases, assembler, ass_vals_cache,
214 t, dt, is_volume, jacobian_threshold, check_inversion, conservative_max_iter);
215 forms.push_back(elastic_form);
216
217 if (rhs_assembler != nullptr)
218 {
219 body_form = std::make_shared<BodyForm>(
220 ndof, n_pressure_bases, boundary_nodes, local_boundary,
221 local_neumann_boundary, n_boundary_samples, rhs, *rhs_assembler,
222 density, /*is_formulation_mixed=*/false,
223 is_time_dependent);
224 body_form->update_quantities(t, sol);
225 forms.push_back(body_form);
226 }
227
228 if (pressure_assembler != nullptr)
229 {
230 pressure_form = std::make_shared<PressureForm>(
231 ndof,
232 local_pressure_boundary,
233 local_pressure_cavity,
234 boundary_nodes,
235 n_boundary_samples, *pressure_assembler,
236 is_time_dependent);
237 pressure_form->update_quantities(t, sol);
238 forms.push_back(pressure_form);
239 }
240
241 inertia_form = nullptr;
242 damping_form = nullptr;
243 if (is_time_dependent)
244 {
245 if (!ignore_inertia)
246 {
247 assert(time_integrator != nullptr);
248 inertia_form = std::make_shared<InertiaForm>(mass, *time_integrator);
249 forms.push_back(inertia_form);
250 }
251
252 if (damping_assembler != nullptr)
253 {
254 damping_form = std::make_shared<ElasticForm>(
255 n_bases, bases, geom_bases, *damping_assembler, ass_vals_cache, t, dt, is_volume,
256 0., ElementInversionCheck::Discrete, conservative_max_iter);
257 forms.push_back(damping_form);
258 }
259 }
260 else
261 {
262 if (lagged_regularization_weight > 0)
263 {
264 forms.push_back(std::make_shared<LaggedRegForm>(lagged_regularization_iterations));
265 forms.back()->set_weight(lagged_regularization_weight);
266 }
267 }
268
269 if (rhs_assembler != nullptr)
270 {
271 // assembler::Mass mass_mat_assembler;
272 // mass_mat_assembler.set_size(dim);
273 StiffnessMatrix mass_tmp = mass;
274 // mass_mat_assembler.assemble(dim == 3, n_bases, bases, geom_bases, mass_ass_vals_cache, mass_tmp, true);
275 // assert(mass_tmp.rows() == mass.rows() && mass_tmp.cols() == mass.cols());
276
277 if (!boundary_nodes.empty())
278 al_form.push_back(std::make_shared<BCLagrangianForm>(
279 ndof, boundary_nodes, local_boundary, local_neumann_boundary,
280 n_boundary_samples, mass_tmp, *rhs_assembler, obstacle_ndof, is_time_dependent, t,
281 al_lumping));
282 // forms.push_back(al_form.back());
283 }
284
285 if (!periodic_conditions.empty())
286 {
287 if (periodic_mesh == nullptr || periodic_local_boundary == nullptr)
288 log_and_throw_error("Periodic boundary constraints require mesh boundary data");
289
290 for (const json &condition : periodic_conditions)
291 {
292 const int condition_fe_space = condition.value("fe_space", -1);
293 // -1 means all/unspecified FE spaces. If both IDs are explicit,
294 // instantiate the condition only for the matching space.
295 if (condition_fe_space >= 0 && fe_space_id >= 0 && condition_fe_space != fe_space_id)
296 continue;
297
298 if (!condition.contains("boundary_ids") || !condition["boundary_ids"].is_array() || condition["boundary_ids"].size() != 2)
299 log_and_throw_error("A periodic boundary condition must contain exactly two boundary_ids");
300
301 const std::array<int, 2> boundary_ids = {{condition["boundary_ids"][0].get<int>(),
302 condition["boundary_ids"][1].get<int>()}};
303 al_form.push_back(std::make_shared<PeriodicBoundaryLagrangianForm>(
304 ndof, dim, *periodic_mesh, bases, *periodic_local_boundary,
305 boundary_ids, condition.value("tolerance", 1e-5)));
306 }
307 }
308
309 bool add_zero_mean = false;
310 if (zero_mean.is_boolean())
311 {
312 add_zero_mean = zero_mean.get<bool>();
313 }
314 else if (zero_mean.is_array())
315 {
316 const int current_fe_space = fe_space_id < 0 ? 0 : fe_space_id;
317 add_zero_mean = std::find(zero_mean.begin(), zero_mean.end(), current_fe_space) != zero_mean.end();
318 }
319 else
320 {
321 log_and_throw_error("constraints.zero_mean must be a boolean or a list of FE-space IDs");
322 }
323
324 if (add_zero_mean)
325 {
326 StiffnessMatrix zero_mean_mass = mass;
327 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
328 {
329 assembler::Mass mass_assembler;
330 mass_assembler.set_size(dim);
331 mass_assembler.assemble(
332 dim == 3, n_bases, bases, geom_bases,
333 mass_ass_vals_cache, 0, zero_mean_mass, true);
334 }
335 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
336 log_and_throw_error("Unable to assemble zero-mean constraints for {} DoFs", ndof);
337
338 const Eigen::VectorXd weights = zero_mean_mass * Eigen::VectorXd::Ones(ndof);
339 std::vector<Eigen::Triplet<double>> entries;
340 for (int d = 0; d < dim; ++d)
341 {
342 double weight_sum = 0;
343 for (int dof = d; dof < ndof; dof += dim)
344 weight_sum += std::abs(weights(dof));
345 if (weight_sum <= 0)
346 log_and_throw_error("Unable to assemble a zero-mean constraint for component {}", d);
347 for (int dof = d; dof < ndof; dof += dim)
348 if (weights(dof) != 0)
349 entries.emplace_back(d, dof, weights(dof) / weight_sum);
350 }
351
352 StiffnessMatrix A(dim, ndof);
353 A.setFromTriplets(entries.begin(), entries.end());
354 Eigen::MatrixXd b = Eigen::MatrixXd::Zero(dim, 1);
355 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b));
356 }
357
358 for (const auto &path : hard_constraint_files)
359 {
360 logger().debug("Setting up hard constraints for {}", path);
361 with_constraint_resource(resources, path, [&](const io::ResourceIO &file, const std::string &group) {
362 const auto child = [&](const std::string &name) { return constraint_child(group, name); };
363 std::vector<int> local2global;
364 if (file.exists(child("local2global")))
365 local2global = file.read_int_vector(child("local2global"));
366
367 if (local2global.empty())
368 {
369 local2global.resize(in_node_to_node.size());
370 for (int i = 0; i < local2global.size(); ++i)
371 local2global[i] = in_node_to_node[i];
372 }
373 else
374 {
375 for (auto &v : local2global)
376 v = in_node_to_node[v];
377 }
378
379 const Eigen::MatrixXd bin = file.read_matrix(child("b"));
380 StiffnessMatrix A, A_proj;
381 Eigen::MatrixXd b, b_proj;
382
383 if (file.exists(child("A")))
384 {
385 const Eigen::MatrixXd Ain = file.read_matrix(child("A"));
386 utils::scatter_matrix(ndof, dim, Ain, bin, local2global, A, b);
387 if (file.exists(child("A_proj")))
388 {
389 if (!file.exists(child("b_proj")))
390 log_and_throw_error("Missing b_proj in hard constraint resource");
392 ndof, dim, file.read_matrix(child("A_proj")), file.read_matrix(child("b_proj")),
393 local2global, A_proj, b_proj);
394 }
395 }
396 else
397 {
399 ndof, dim, file.read_long_vector(child("A_triplets/shape")),
400 file.read_int_vector(child("A_triplets/rows")), file.read_int_vector(child("A_triplets/cols")),
401 file.read_double_vector(child("A_triplets/values")), bin, local2global, A, b);
402
403 if (file.is_group(child("A_proj_triplets")))
404 {
405 for (const std::string &required : {"b_proj", "A_proj_triplets/rows", "A_proj_triplets/cols", "A_proj_triplets/values", "A_proj_triplets/shape"})
406 if (!file.exists(child(required)))
407 log_and_throw_error("Missing {} in hard constraint resource", required);
409 ndof, dim, file.read_long_vector(child("A_proj_triplets/shape")),
410 file.read_int_vector(child("A_proj_triplets/rows")), file.read_int_vector(child("A_proj_triplets/cols")),
411 file.read_double_vector(child("A_proj_triplets/values")), file.read_matrix(child("b_proj")),
412 local2global, A_proj, b_proj);
413 }
414 }
415
416 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b, A_proj, b_proj));
417 });
418 // forms.push_back(al_form.back());
419 }
420
421 for (const auto &j : soft_constraint_files)
422 {
423 const std::string &path = j["data"];
424 double weight = j["weight"];
425
426 logger().debug("Setting up soft constraints for {}", path);
427 with_constraint_resource(resources, path, [&](const io::ResourceIO &file, const std::string &group) {
428 const auto child = [&](const std::string &name) { return constraint_child(group, name); };
429 std::vector<int> local2global;
430 if (file.exists(child("local2global")))
431 local2global = file.read_int_vector(child("local2global"));
432 if (local2global.empty())
433 {
434 local2global.resize(in_node_to_node.size());
435 for (int i = 0; i < local2global.size(); ++i)
436 local2global[i] = in_node_to_node[i];
437 }
438 else
439 {
440 for (auto &v : local2global)
441 v = in_node_to_node[v];
442 }
443
444 const Eigen::MatrixXd bin = file.read_matrix(child("b"));
446 Eigen::MatrixXd b;
447 if (file.exists(child("A")))
448 utils::scatter_matrix(ndof, dim, file.read_matrix(child("A")), bin, local2global, A, b);
449 else
451 ndof, dim, file.read_long_vector(child("A_triplets/shape")),
452 file.read_int_vector(child("A_triplets/rows")), file.read_int_vector(child("A_triplets/cols")),
453 file.read_double_vector(child("A_triplets/values")), bin, local2global, A, b);
454
455 forms.push_back(std::make_shared<QuadraticPenaltyForm>(A, b, weight));
456 });
457 }
458
459 if (macro_strain_constraint.is_active())
460 {
461 // don't push these two into forms because they take a different input x
462 strain_al_lagr_form = std::make_shared<MacroStrainLagrangianForm>(macro_strain_constraint);
463 }
464
465 contact_form = nullptr;
466 periodic_contact_form = nullptr;
467 friction_form = nullptr;
468 if (contact_enabled)
469 {
470 const bool use_adaptive_barrier_stiffness = !barrier_stiffness.is_number();
471
472 if (periodic_contact)
473 {
474 periodic_contact_form = std::make_shared<PeriodicContactForm>(
475 collision_mesh, tiled_to_single, dhat, avg_mass, use_area_weighting, use_improved_max_operator, use_physical_barrier,
476 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase, ccd_tolerance,
477 ccd_max_iterations, dhat_epsilon_scale);
478
479 if (use_adaptive_barrier_stiffness)
480 {
481 periodic_contact_form->set_barrier_stiffness(1);
482 // logger().debug("Using adaptive barrier stiffness");
483 }
484 else
485 {
486 assert(barrier_stiffness.is_number());
487 assert(barrier_stiffness.get<double>() > 0);
488 periodic_contact_form->set_barrier_stiffness(barrier_stiffness);
489 // logger().debug("Using fixed barrier stiffness of {}", contact_form->barrier_stiffness());
490 }
491
492 // periodic_contact_form is not pushed into forms since it takes different input vectors.
493 }
494 else
495 {
496 if (use_gcp_formulation)
497 {
498 contact_form = std::make_shared<GCPContactForm>(
499 collision_mesh, dhat, avg_mass, alpha_t, alpha_n, use_adaptive_dhat, min_distance_ratio,
500 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase,
501 ccd_tolerance * units.characteristic_length(), ccd_max_iterations, dhat_epsilon_scale);
502 }
503 else if (use_esp_formulation)
504 {
505 contact_form = std::make_shared<ESPContactForm>(
506 collision_mesh, dhat, avg_mass, esp_params, skip_obstacles, barrier_from_string(barrier), use_adaptive_dhat, use_adaptive_barrier_stiffness, is_time_dependent,
507 enable_shape_derivatives, broad_phase, ccd_tolerance * units.characteristic_length(), ccd_max_iterations, dhat_epsilon_scale);
508 }
509 else
510 {
511 contact_form = std::make_shared<BarrierContactForm>(
512 collision_mesh, dhat, avg_mass, use_area_weighting, use_improved_max_operator, use_physical_barrier,
513 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase, ccd_tolerance * units.characteristic_length(),
514 ccd_max_iterations, dhat_epsilon_scale, collision_set_type_from_string(collision_set_type), skip_obstacles, barrier_from_string(barrier));
515 }
516
517 if (use_adaptive_barrier_stiffness)
518 {
519 contact_form->set_barrier_stiffness(initial_barrier_stiffness);
520 // logger().debug("Using adaptive barrier stiffness");
521 }
522 else
523 {
524 assert(barrier_stiffness.is_number());
525 assert(barrier_stiffness.get<double>() > 0);
526 contact_form->set_barrier_stiffness(barrier_stiffness);
527 // logger().debug("Using fixed barrier stiffness of {}", contact_form->barrier_stiffness());
528 }
529
530 forms.push_back(contact_form);
531 }
532
533 if (friction_coefficient != 0)
534 {
535 friction_form = std::make_shared<FrictionForm>(
536 collision_mesh, time_integrator, epsv, friction_coefficient,
537 broad_phase, *contact_form, friction_iterations);
538 friction_form->init_lagging(sol);
539 forms.push_back(friction_form);
540 }
541
542 if (adhesion_enabled)
543 {
544 normal_adhesion_form = std::make_shared<NormalAdhesionForm>(
545 collision_mesh, dhat_p, dhat_a, Y, is_time_dependent, enable_shape_derivatives,
546 broad_phase, ccd_tolerance * units.characteristic_length(), ccd_max_iterations);
547 forms.push_back(normal_adhesion_form);
548
549 if (tangential_adhesion_coefficient != 0)
550 {
551 tangential_adhesion_form = std::make_shared<TangentialAdhesionForm>(
552 collision_mesh, time_integrator, epsa, tangential_adhesion_coefficient,
553 broad_phase, *normal_adhesion_form, tangential_adhesion_iterations);
554 forms.push_back(tangential_adhesion_form);
555 }
556 }
557 }
558
559 const std::vector<json> rayleigh_damping_jsons = utils::json_as_array(rayleigh_damping);
560 if (is_time_dependent)
561 {
562 // Map from form name to form so RayleighDampingForm::create can get the correct form to damp
563 const std::unordered_map<std::string, std::shared_ptr<Form>> possible_forms_to_damp = {
564 {"elasticity", elastic_form},
565 {"contact", contact_form},
566 };
567
568 for (const json &params : rayleigh_damping_jsons)
569 {
570 forms.push_back(RayleighDampingForm::create(
571 params, possible_forms_to_damp,
573 }
574 }
575 else if (rayleigh_damping_jsons.size() > 0)
576 {
577 log_and_throw_adjoint_error("Rayleigh damping is only supported for time-dependent problems");
578 }
579
580 update_dt();
581
582 return forms;
583 }
584
585 void SolveData::update_barrier_stiffness(const Eigen::VectorXd &x)
586 {
587 if (contact_form == nullptr || !contact_form->use_adaptive_barrier_stiffness())
588 return;
589
590 Eigen::VectorXd grad_energy = Eigen::VectorXd::Zero(x.size());
591 const std::array<std::shared_ptr<Form>, 4> energy_forms{
593 for (const std::shared_ptr<Form> &form : energy_forms)
594 {
595 if (form == nullptr || !form->enabled())
596 continue;
597
598 Eigen::VectorXd grad_form;
599 form->first_derivative(x, grad_form);
600 grad_energy += grad_form;
601 }
602
603 contact_form->update_barrier_stiffness(x, grad_energy);
604 }
605
607 {
608 if (time_integrator == nullptr) // if is not time dependent
609 return;
610
611 const std::array<std::shared_ptr<Form>, 6> energy_forms{
613 for (const std::shared_ptr<Form> &form : energy_forms)
614 {
615 if (form == nullptr)
616 continue;
617 form->set_weight(time_integrator->acceleration_scaling());
618 }
619 }
620
621 std::vector<std::pair<std::string, std::shared_ptr<solver::Form>>> SolveData::named_forms() const
622 {
623 std::vector<std::pair<std::string, std::shared_ptr<solver::Form>>> res{
624 {"elastic", elastic_form},
625 {"inertia", inertia_form},
626 {"body", body_form},
627 {"contact", contact_form},
628 {"friction", friction_form},
629 {"damping", damping_form},
630 {"pressure", pressure_form},
631 {"strain_augmented_lagrangian_lagr", strain_al_lagr_form},
632 {"periodic_contact", periodic_contact_form},
633 };
634
635 for (const auto &form : al_form)
636 res.push_back({"augmented_lagrangian", form});
637
638 return res;
639 }
640} // namespace polyfem::solver
std::vector< Eigen::Triplet< double > > entries
std::vector< std::pair< int, double > > weights
int x
double characteristic_length() const
Definition Units.hpp:22
virtual void set_size(const int size)
Definition Assembler.hpp:67
Caches basis evaluation and geometric mapping at every element.
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 9, 1 > assemble(const LinearAssemblerData &data) const override
computes and returns local stiffness matrix (1x1) for bases i,j (where i,j is passed in through data)...
Definition Mass.cpp:18
HDF5 logical paths always use POSIX separators and roots.
Read-only interface to a hierarchical collection of simulation resources.
virtual std::filesystem::path materialize(const std::string &path) const =0
virtual bool is_group(const std::string &path) const =0
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
static std::shared_ptr< RayleighDampingForm > create(const json &params, const std::unordered_map< std::string, std::shared_ptr< Form > > &forms, const time_integrator::ImplicitTimeIntegrator &time_integrator)
std::shared_ptr< solver::FrictionForm > friction_form
std::shared_ptr< solver::InertiaForm > inertia_form
std::shared_ptr< solver::PeriodicContactForm > periodic_contact_form
void update_dt()
updates the dt inside the different forms
std::shared_ptr< solver::PressureForm > pressure_form
std::shared_ptr< solver::BodyForm > body_form
std::shared_ptr< solver::MacroStrainLagrangianForm > strain_al_lagr_form
std::shared_ptr< solver::NormalAdhesionForm > normal_adhesion_form
std::shared_ptr< solver::ContactForm > contact_form
std::vector< std::pair< std::string, std::shared_ptr< solver::Form > > > named_forms() const
std::shared_ptr< solver::ElasticForm > damping_form
std::shared_ptr< solver::ElasticForm > elastic_form
std::vector< std::shared_ptr< solver::AugmentedLagrangianForm > > al_form
std::shared_ptr< time_integrator::ImplicitTimeIntegrator > time_integrator
void update_barrier_stiffness(const Eigen::VectorXd &x)
update the barrier stiffness for the forms
std::shared_ptr< solver::TangentialAdhesionForm > tangential_adhesion_form
std::vector< std::shared_ptr< Form > > init_forms(const Units &units, const io::ResourceIO &resources, const int dim, const double t, const Eigen::VectorXi &in_node_to_node, const int n_bases, std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &geom_bases, const assembler::Assembler &assembler, assembler::AssemblyValsCache &ass_vals_cache, const assembler::AssemblyValsCache &mass_ass_vals_cache, const double jacobian_threshold, const solver::ElementInversionCheck check_inversion, const unsigned conservative_max_iter, const int n_pressure_bases, const std::vector< int > &boundary_nodes, const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, const QuadratureOrders &n_boundary_samples, const Eigen::MatrixXd &rhs, const Eigen::MatrixXd &sol, const assembler::Density &density, const std::vector< mesh::LocalBoundary > &local_pressure_boundary, const std::unordered_map< int, std::vector< mesh::LocalBoundary > > &local_pressure_cavity, const std::shared_ptr< assembler::PressureAssembler > pressure_assembler, const bool ignore_inertia, const StiffnessMatrix &mass, const std::shared_ptr< assembler::ViscousDamping > damping_assembler, const double lagged_regularization_weight, const int lagged_regularization_iterations, const size_t obstacle_ndof, const std::vector< std::string > &hard_constraint_files, const std::vector< json > &soft_constraint_files, const json &zero_mean, const bool contact_enabled, const ipc::CollisionMesh &collision_mesh, const double dhat, const double avg_mass, const bool use_area_weighting, const bool use_improved_max_operator, const bool use_physical_barrier, const std::string &collision_set_type, const bool skip_obstacles, const std::string &barrier, const json &barrier_stiffness, const double initial_barrier_stiffness, const double dhat_epsilon_scale, const ipc::BroadPhaseMethod broad_phase, const double ccd_tolerance, const long ccd_max_iterations, const bool enable_shape_derivatives, const bool use_gcp_formulation, const double alpha_t, const double alpha_n, const bool use_adaptive_dhat, const double min_distance_ratio, const bool use_esp_formulation, json esp_params, const bool adhesion_enabled, const double dhat_p, const double dhat_a, const double Y, const double tangential_adhesion_coefficient, const double epsa, const int tangential_adhesion_iterations, const assembler::MacroStrainValue &macro_strain_constraint, const bool periodic_contact, const Eigen::VectorXi &tiled_to_single, const double friction_coefficient, const double epsv, const int friction_iterations, const json &rayleigh_damping, const BCLumpingMode al_lumping=BCLumpingMode::ROW_SUM, const mesh::Mesh *periodic_mesh=nullptr, const std::vector< mesh::LocalBoundary > *periodic_local_boundary=nullptr, const json &periodic_conditions=json::array(), const int fe_space_id=-1)
Initialize the forms and return a vector of pointers to them.
Definition SolveData.cpp:87
std::shared_ptr< assembler::PressureAssembler > pressure_assembler
std::shared_ptr< assembler::RhsAssembler > rhs_assembler
BCLumpingMode
Lumping mode for the mass metric of the BC penalty.
void scatter_matrix(const int n_dofs, const int dim, const Eigen::MatrixXd &A, const Eigen::MatrixXd &b, const std::vector< int > &local_to_global, StiffnessMatrix &Aout, Eigen::MatrixXd &bout)
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
Definition JSONUtils.hpp:49
void scatter_matrix_col(const int n_dofs, const int dim, const Eigen::MatrixXd &A, const Eigen::MatrixXd &b, const std::vector< int > &local_to_global, StiffnessMatrix &Aout, Eigen::MatrixXd &bout)
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44
std::array< int, 2 > QuadratureOrders
Definition Types.hpp:19
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24