63 const Eigen::VectorXi &in_node_to_node,
67 std::vector<basis::ElementBases> &bases,
68 const std::vector<basis::ElementBases> &geom_bases,
72 const double jacobian_threshold,
74 const unsigned conservative_max_iter,
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,
82 const Eigen::MatrixXd &rhs,
83 const Eigen::MatrixXd &sol,
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,
92 const bool ignore_inertia,
94 const std::shared_ptr<assembler::ViscousDamping> damping_assembler,
97 const double lagged_regularization_weight,
98 const int lagged_regularization_iterations,
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,
107 const bool contact_enabled,
108 const ipc::CollisionMesh &collision_mesh,
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,
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,
129 const bool adhesion_enabled,
135 const double tangential_adhesion_coefficient,
137 const int tangential_adhesion_iterations,
143 const bool periodic_contact,
144 const Eigen::VectorXi &tiled_to_single,
147 const double friction_coefficient,
149 const int friction_iterations,
152 const json &rayleigh_damping,
159 const std::vector<mesh::LocalBoundary> *periodic_local_boundary,
160 const json &periodic_conditions,
161 const int fe_space_id)
166 const int ndof = n_bases * dim;
169 const bool is_volume = dim == 3;
171 std::vector<std::shared_ptr<Form>> forms;
175 n_bases, bases, geom_bases, assembler, ass_vals_cache,
176 t, dt, is_volume, jacobian_threshold, check_inversion, conservative_max_iter);
182 ndof, n_pressure_bases, boundary_nodes, local_boundary,
183 local_neumann_boundary, n_boundary_samples, rhs, *
rhs_assembler,
194 local_pressure_boundary,
195 local_pressure_cavity,
205 if (is_time_dependent)
214 if (damping_assembler !=
nullptr)
217 n_bases, bases, geom_bases, *damping_assembler, ass_vals_cache, t, dt, is_volume,
224 if (lagged_regularization_weight > 0)
226 forms.push_back(std::make_shared<LaggedRegForm>(lagged_regularization_iterations));
227 forms.back()->set_weight(lagged_regularization_weight);
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,
247 if (!periodic_conditions.empty())
249 if (periodic_mesh ==
nullptr || periodic_local_boundary ==
nullptr)
252 for (
const json &condition : periodic_conditions)
254 const int condition_fe_space = condition.value(
"fe_space", -1);
257 if (condition_fe_space >= 0 && fe_space_id >= 0 && condition_fe_space != fe_space_id)
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");
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)));
271 bool add_zero_mean =
false;
272 if (zero_mean.is_boolean())
274 add_zero_mean = zero_mean.get<
bool>();
276 else if (zero_mean.is_array())
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();
289 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
294 dim == 3, n_bases, bases, geom_bases,
295 mass_ass_vals_cache, 0, zero_mean_mass,
true);
297 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
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)
304 double weight_sum = 0;
305 for (
int dof = d; dof < ndof; dof += dim)
306 weight_sum += std::abs(
weights(dof));
309 for (
int dof = d; dof < ndof; dof += dim)
316 Eigen::MatrixXd b = Eigen::MatrixXd::Zero(dim, 1);
317 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b));
320 for (
const auto &path : hard_constraint_files)
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"));
329 if (local2global.empty())
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];
337 for (
auto &v : local2global)
338 v = in_node_to_node[v];
341 const Eigen::MatrixXd bin = file.read_matrix(child(
"b"));
343 Eigen::MatrixXd b, b_proj;
345 if (file.exists(child(
"A")))
347 const Eigen::MatrixXd Ain = file.read_matrix(child(
"A"));
349 if (file.exists(child(
"A_proj")))
351 if (!file.exists(child(
"b_proj")))
354 ndof, dim, file.read_matrix(child(
"A_proj")), file.read_matrix(child(
"b_proj")),
355 local2global, A_proj, b_proj);
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);
365 if (file.is_group(child(
"A_proj_triplets")))
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)))
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);
378 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b, A_proj, b_proj));
383 for (
const auto &j : soft_constraint_files)
385 const std::string &path = j[
"data"];
386 double weight = j[
"weight"];
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())
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];
402 for (
auto &v : local2global)
403 v = in_node_to_node[v];
406 const Eigen::MatrixXd bin = file.read_matrix(child(
"b"));
409 if (file.exists(child(
"A")))
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);
417 forms.push_back(std::make_shared<QuadraticPenaltyForm>(A, b, weight));
424 strain_al_lagr_form = std::make_shared<MacroStrainLagrangianForm>(macro_strain_constraint);
432 const bool use_adaptive_barrier_stiffness = !barrier_stiffness.is_number();
434 if (periodic_contact)
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,
441 if (use_adaptive_barrier_stiffness)
448 assert(barrier_stiffness.is_number());
449 assert(barrier_stiffness.get<
double>() > 0);
458 if (use_gcp_formulation)
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,
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(),
473 if (use_adaptive_barrier_stiffness)
475 contact_form->set_barrier_stiffness(initial_barrier_stiffness);
480 assert(barrier_stiffness.is_number());
481 assert(barrier_stiffness.get<
double>() > 0);
489 if (friction_coefficient != 0)
498 if (adhesion_enabled)
501 collision_mesh, dhat_p, dhat_a, Y, is_time_dependent, enable_shape_derivatives,
505 if (tangential_adhesion_coefficient != 0)
508 collision_mesh,
time_integrator, epsa, tangential_adhesion_coefficient,
516 if (is_time_dependent)
519 const std::unordered_map<std::string, std::shared_ptr<Form>> possible_forms_to_damp = {
524 for (
const json ¶ms : rayleigh_damping_jsons)
527 params, possible_forms_to_damp,
531 else if (rayleigh_damping_jsons.size() > 0)
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 ¯o_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.