40 const Eigen::VectorXi &in_node_to_node,
44 std::vector<basis::ElementBases> &bases,
45 const std::vector<basis::ElementBases> &geom_bases,
49 const double jacobian_threshold,
51 const unsigned conservative_max_iter,
54 const int n_pressure_bases,
55 const std::vector<int> &boundary_nodes,
56 const std::vector<mesh::LocalBoundary> &local_boundary,
57 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
59 const Eigen::MatrixXd &rhs,
60 const Eigen::MatrixXd &sol,
64 const std::vector<mesh::LocalBoundary> &local_pressure_boundary,
65 const std::unordered_map<
int, std::vector<mesh::LocalBoundary>> &local_pressure_cavity,
66 const std::shared_ptr<assembler::PressureAssembler> pressure_assembler,
69 const bool ignore_inertia,
71 const std::shared_ptr<assembler::ViscousDamping> damping_assembler,
74 const double lagged_regularization_weight,
75 const int lagged_regularization_iterations,
78 const size_t obstacle_ndof,
79 const std::vector<std::string> &hard_constraint_files,
80 const std::vector<json> &soft_constraint_files,
81 const json &zero_mean,
84 const bool contact_enabled,
85 const ipc::CollisionMesh &collision_mesh,
87 const double avg_mass,
88 const bool use_area_weighting,
89 const bool use_improved_max_operator,
90 const bool use_physical_barrier,
91 const json &barrier_stiffness,
92 const double initial_barrier_stiffness,
93 const ipc::BroadPhaseMethod broad_phase,
94 const double ccd_tolerance,
95 const long ccd_max_iterations,
96 const bool enable_shape_derivatives,
99 const bool use_gcp_formulation,
100 const double alpha_t,
101 const double alpha_n,
102 const bool use_adaptive_dhat,
103 const double min_distance_ratio,
106 const bool adhesion_enabled,
112 const double tangential_adhesion_coefficient,
114 const int tangential_adhesion_iterations,
120 const bool periodic_contact,
121 const Eigen::VectorXi &tiled_to_single,
124 const double friction_coefficient,
126 const int friction_iterations,
129 const json &rayleigh_damping,
136 const std::vector<mesh::LocalBoundary> *periodic_local_boundary,
137 const json &periodic_conditions,
138 const int fe_space_id)
143 const int ndof = n_bases * dim;
146 const bool is_volume = dim == 3;
148 std::vector<std::shared_ptr<Form>> forms;
152 n_bases, bases, geom_bases, assembler, ass_vals_cache,
153 t, dt, is_volume, jacobian_threshold, check_inversion, conservative_max_iter);
159 ndof, n_pressure_bases, boundary_nodes, local_boundary,
160 local_neumann_boundary, n_boundary_samples, rhs, *
rhs_assembler,
171 local_pressure_boundary,
172 local_pressure_cavity,
182 if (is_time_dependent)
191 if (damping_assembler !=
nullptr)
194 n_bases, bases, geom_bases, *damping_assembler, ass_vals_cache, t, dt, is_volume,
201 if (lagged_regularization_weight > 0)
203 forms.push_back(std::make_shared<LaggedRegForm>(lagged_regularization_iterations));
204 forms.back()->set_weight(lagged_regularization_weight);
216 if (!boundary_nodes.empty())
217 al_form.push_back(std::make_shared<BCLagrangianForm>(
218 ndof, boundary_nodes, local_boundary, local_neumann_boundary,
219 n_boundary_samples, mass_tmp, *
rhs_assembler, obstacle_ndof, is_time_dependent, t,
224 if (!periodic_conditions.empty())
226 if (periodic_mesh ==
nullptr || periodic_local_boundary ==
nullptr)
229 for (
const json &condition : periodic_conditions)
231 const int condition_fe_space = condition.value(
"fe_space", -1);
234 if (condition_fe_space >= 0 && fe_space_id >= 0 && condition_fe_space != fe_space_id)
237 if (!condition.contains(
"boundary_ids") || !condition[
"boundary_ids"].is_array() || condition[
"boundary_ids"].size() != 2)
238 log_and_throw_error(
"A periodic boundary condition must contain exactly two boundary_ids");
240 const std::array<int, 2> boundary_ids = {{condition[
"boundary_ids"][0].get<
int>(),
241 condition[
"boundary_ids"][1].get<int>()}};
242 al_form.push_back(std::make_shared<PeriodicBoundaryLagrangianForm>(
243 ndof, dim, *periodic_mesh, bases, *periodic_local_boundary,
244 boundary_ids, condition.value(
"tolerance", 1e-5)));
248 bool add_zero_mean =
false;
249 if (zero_mean.is_boolean())
251 add_zero_mean = zero_mean.get<
bool>();
253 else if (zero_mean.is_array())
255 const int current_fe_space = fe_space_id < 0 ? 0 : fe_space_id;
256 add_zero_mean = std::find(zero_mean.begin(), zero_mean.end(), current_fe_space) != zero_mean.end();
266 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
271 dim == 3, n_bases, bases, geom_bases,
272 mass_ass_vals_cache, 0, zero_mean_mass,
true);
274 if (zero_mean_mass.rows() != ndof || zero_mean_mass.cols() != ndof)
277 const Eigen::VectorXd
weights = zero_mean_mass * Eigen::VectorXd::Ones(ndof);
278 std::vector<Eigen::Triplet<double>>
entries;
279 for (
int d = 0; d < dim; ++d)
281 double weight_sum = 0;
282 for (
int dof = d; dof < ndof; dof += dim)
283 weight_sum += std::abs(
weights(dof));
286 for (
int dof = d; dof < ndof; dof += dim)
293 Eigen::MatrixXd b = Eigen::MatrixXd::Zero(dim, 1);
294 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b));
297 for (
const auto &path : hard_constraint_files)
299 logger().debug(
"Setting up hard constraints for {}", path);
300 h5pp::File file(path, h5pp::FileAccess::READONLY);
301 std::vector<int> local2global;
302 if (!file.findDatasets(
"local2global").empty())
303 local2global = file.readDataset<std::vector<int>>(
"local2global");
305 if (local2global.empty())
307 local2global.resize(in_node_to_node.size());
309 for (
int i = 0; i < local2global.size(); ++i)
310 local2global[i] = in_node_to_node[i];
314 for (
auto &v : local2global)
315 v = in_node_to_node[v];
318 Eigen::MatrixXd bin = file.readDataset<Eigen::MatrixXd>(
"b");
321 Eigen::MatrixXd b, b_proj;
323 if (!file.findDatasets(
"A").empty())
325 Eigen::MatrixXd Ain = file.readDataset<Eigen::MatrixXd>(
"A");
328 if (!file.findDatasets(
"A_proj").empty())
330 Eigen::MatrixXd A_proj_in = file.readDataset<Eigen::MatrixXd>(
"A_proj");
331 if (file.findDatasets(
"b_proj").empty())
334 Eigen::MatrixXd b_proj_in = file.readDataset<Eigen::MatrixXd>(
"b_proj");
340 std::vector<double> values = file.readDataset<std::vector<double>>(
"A_triplets/values");
341 std::vector<int> rows = file.readDataset<std::vector<int>>(
"A_triplets/rows");
342 std::vector<int> cols = file.readDataset<std::vector<int>>(
"A_triplets/cols");
343 std::vector<long> shape = file.readDataset<std::vector<long>>(
"A_triplets/shape");
346 if (!file.findGroups(
"A_proj_triplets").empty())
348 if (file.findDatasets(
"b_proj").empty())
350 if (file.findDatasets(
"rows",
"/A_proj_triplets").empty())
352 if (file.findDatasets(
"cols",
"/A_proj_triplets").empty())
354 if (file.findDatasets(
"values",
"/A_proj_triplets").empty())
357 std::vector<double> values_proj = file.readDataset<std::vector<double>>(
"A_proj_triplets/values");
358 std::vector<int> rows_proj = file.readDataset<std::vector<int>>(
"A_proj_triplets/rows");
359 std::vector<int> cols_proj = file.readDataset<std::vector<int>>(
"A_proj_triplets/cols");
360 Eigen::MatrixXd b_projin = file.readDataset<Eigen::MatrixXd>(
"b_proj");
361 std::vector<long> shape_proj = file.readDataset<std::vector<long>>(
"A_proj_triplets/shape");
363 utils::scatter_matrix_col(ndof, dim, shape_proj, rows_proj, cols_proj, values_proj, b_projin, local2global, A_proj, b_proj);
367 al_form.push_back(std::make_shared<MatrixLagrangianForm>(A, b, A_proj, b_proj));
371 for (
const auto &j : soft_constraint_files)
373 const std::string &path = j[
"data"];
374 double weight = j[
"weight"];
376 logger().debug(
"Setting up soft constraints for {}", path);
377 h5pp::File file(path, h5pp::FileAccess::READONLY);
378 std::vector<int> local2global;
379 if (!file.findDatasets(
"local2global").empty())
380 local2global = file.readDataset<std::vector<int>>(
"local2global");
382 if (local2global.empty())
384 local2global.resize(in_node_to_node.size());
386 for (
int i = 0; i < local2global.size(); ++i)
387 local2global[i] = in_node_to_node[i];
391 for (
auto &v : local2global)
392 v = in_node_to_node[v];
395 Eigen::MatrixXd bin = file.readDataset<Eigen::MatrixXd>(
"b");
400 if (!file.findDatasets(
"A").empty())
402 Eigen::MatrixXd Ain = file.readDataset<Eigen::MatrixXd>(
"A");
407 std::vector<double> values = file.readDataset<std::vector<double>>(
"A_triplets/values");
408 std::vector<int> rows = file.readDataset<std::vector<int>>(
"A_triplets/rows");
409 std::vector<int> cols = file.readDataset<std::vector<int>>(
"A_triplets/cols");
410 std::vector<long> shape = file.readDataset<std::vector<long>>(
"A_triplets/shape");
415 forms.push_back(std::make_shared<QuadraticPenaltyForm>(A, b, weight));
421 strain_al_lagr_form = std::make_shared<MacroStrainLagrangianForm>(macro_strain_constraint);
429 const bool use_adaptive_barrier_stiffness = !barrier_stiffness.is_number();
431 if (periodic_contact)
434 collision_mesh, tiled_to_single, dhat, avg_mass, use_area_weighting, use_improved_max_operator, use_physical_barrier,
435 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase, ccd_tolerance,
438 if (use_adaptive_barrier_stiffness)
445 assert(barrier_stiffness.is_number());
446 assert(barrier_stiffness.get<
double>() > 0);
455 if (use_gcp_formulation)
458 collision_mesh, dhat, avg_mass, alpha_t, alpha_n, use_adaptive_dhat, min_distance_ratio,
459 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase,
465 collision_mesh, dhat, avg_mass, use_area_weighting, use_improved_max_operator, use_physical_barrier,
466 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase, ccd_tolerance * units.
characteristic_length(),
470 if (use_adaptive_barrier_stiffness)
472 contact_form->set_barrier_stiffness(initial_barrier_stiffness);
477 assert(barrier_stiffness.is_number());
478 assert(barrier_stiffness.get<
double>() > 0);
486 if (friction_coefficient != 0)
495 if (adhesion_enabled)
498 collision_mesh, dhat_p, dhat_a, Y, is_time_dependent, enable_shape_derivatives,
502 if (tangential_adhesion_coefficient != 0)
505 collision_mesh,
time_integrator, epsa, tangential_adhesion_coefficient,
513 if (is_time_dependent)
516 const std::unordered_map<std::string, std::shared_ptr<Form>> possible_forms_to_damp = {
521 for (
const json ¶ms : rayleigh_damping_jsons)
524 params, possible_forms_to_damp,
528 else if (rayleigh_damping_jsons.size() > 0)
std::vector< std::shared_ptr< Form > > init_forms(const Units &units, 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.