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