93 const Eigen::VectorXi &in_node_to_node,
97 std::vector<basis::ElementBases> &bases,
98 const std::vector<basis::ElementBases> &geom_bases,
102 const double jacobian_threshold,
104 const unsigned conservative_max_iter,
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,
112 const Eigen::MatrixXd &rhs,
113 const Eigen::MatrixXd &sol,
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,
122 const bool ignore_inertia,
124 const std::shared_ptr<assembler::ViscousDamping> damping_assembler,
127 const double lagged_regularization_weight,
128 const int lagged_regularization_iterations,
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,
137 const bool contact_enabled,
138 const ipc::CollisionMesh &collision_mesh,
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,
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,
163 const bool use_esp_formulation,
167 const bool adhesion_enabled,
173 const double tangential_adhesion_coefficient,
175 const int tangential_adhesion_iterations,
181 const bool periodic_contact,
182 const Eigen::VectorXi &tiled_to_single,
185 const double friction_coefficient,
187 const int friction_iterations,
190 const json &rayleigh_damping,
197 const std::vector<mesh::LocalBoundary> *periodic_local_boundary,
198 const json &periodic_conditions,
199 const int fe_space_id)
204 const int ndof = n_bases * dim;
207 const bool is_volume = dim == 3;
209 std::vector<std::shared_ptr<Form>> forms;
213 n_bases, bases, geom_bases, assembler, ass_vals_cache,
214 t, dt, is_volume, jacobian_threshold, check_inversion, conservative_max_iter);
220 ndof, n_pressure_bases, boundary_nodes, local_boundary,
221 local_neumann_boundary, n_boundary_samples, rhs, *
rhs_assembler,
232 local_pressure_boundary,
233 local_pressure_cavity,
243 if (is_time_dependent)
252 if (damping_assembler !=
nullptr)
255 n_bases, bases, geom_bases, *damping_assembler, ass_vals_cache, t, dt, is_volume,
262 if (lagged_regularization_weight > 0)
264 forms.push_back(std::make_shared<LaggedRegForm>(lagged_regularization_iterations));
265 forms.back()->set_weight(lagged_regularization_weight);
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,
285 if (!periodic_conditions.empty())
287 if (periodic_mesh ==
nullptr || periodic_local_boundary ==
nullptr)
290 for (
const json &condition : periodic_conditions)
292 const int condition_fe_space = condition.value(
"fe_space", -1);
295 if (condition_fe_space >= 0 && fe_space_id >= 0 && condition_fe_space != fe_space_id)
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");
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)));
309 bool add_zero_mean =
false;
310 if (zero_mean.is_boolean())
312 add_zero_mean = zero_mean.get<
bool>();
314 else if (zero_mean.is_array())
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();
327 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
332 dim == 3, n_bases, bases, geom_bases,
333 mass_ass_vals_cache, 0, zero_mean_mass,
true);
335 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
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)
342 double weight_sum = 0;
343 for (
int dof = d; dof < ndof; dof += dim)
344 weight_sum += std::abs(
weights(dof));
347 for (
int dof = d; dof < ndof; dof += dim)
354 Eigen::MatrixXd b = Eigen::MatrixXd::Zero(dim, 1);
355 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b));
358 for (
const auto &path : hard_constraint_files)
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"));
367 if (local2global.empty())
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];
375 for (
auto &v : local2global)
376 v = in_node_to_node[v];
379 const Eigen::MatrixXd bin = file.read_matrix(child(
"b"));
381 Eigen::MatrixXd b, b_proj;
383 if (file.exists(child(
"A")))
385 const Eigen::MatrixXd Ain = file.read_matrix(child(
"A"));
387 if (file.exists(child(
"A_proj")))
389 if (!file.exists(child(
"b_proj")))
392 ndof, dim, file.read_matrix(child(
"A_proj")), file.read_matrix(child(
"b_proj")),
393 local2global, A_proj, b_proj);
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);
403 if (file.is_group(child(
"A_proj_triplets")))
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)))
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);
416 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b, A_proj, b_proj));
421 for (
const auto &j : soft_constraint_files)
423 const std::string &path = j[
"data"];
424 double weight = j[
"weight"];
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())
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];
440 for (
auto &v : local2global)
441 v = in_node_to_node[v];
444 const Eigen::MatrixXd bin = file.read_matrix(child(
"b"));
447 if (file.exists(child(
"A")))
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);
455 forms.push_back(std::make_shared<QuadraticPenaltyForm>(A, b, weight));
462 strain_al_lagr_form = std::make_shared<MacroStrainLagrangianForm>(macro_strain_constraint);
470 const bool use_adaptive_barrier_stiffness = !barrier_stiffness.is_number();
472 if (periodic_contact)
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);
479 if (use_adaptive_barrier_stiffness)
486 assert(barrier_stiffness.is_number());
487 assert(barrier_stiffness.get<
double>() > 0);
496 if (use_gcp_formulation)
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,
503 else if (use_esp_formulation)
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);
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));
517 if (use_adaptive_barrier_stiffness)
519 contact_form->set_barrier_stiffness(initial_barrier_stiffness);
524 assert(barrier_stiffness.is_number());
525 assert(barrier_stiffness.get<
double>() > 0);
533 if (friction_coefficient != 0)
542 if (adhesion_enabled)
545 collision_mesh, dhat_p, dhat_a, Y, is_time_dependent, enable_shape_derivatives,
549 if (tangential_adhesion_coefficient != 0)
552 collision_mesh,
time_integrator, epsa, tangential_adhesion_coefficient,
560 if (is_time_dependent)
563 const std::unordered_map<std::string, std::shared_ptr<Form>> possible_forms_to_damp = {
568 for (
const json ¶ms : rayleigh_damping_jsons)
571 params, possible_forms_to_damp,
575 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 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 ¯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.