PolyFEM
Loading...
Searching...
No Matches
SolveData.cpp
Go to the documentation of this file.
1#include "SolveData.hpp"
2
24
25namespace polyfem::solver
26{
27 using namespace polyfem::time_integrator;
28
29 std::vector<std::shared_ptr<Form>> SolveData::init_forms(
30 // General
31 const Units &units,
32 const int dim,
33 const double t,
34
35 // Elastic form
36 const int n_bases,
37 const std::vector<basis::ElementBases> &bases,
38 const std::vector<basis::ElementBases> &geom_bases,
39 const assembler::Assembler &assembler,
40 const assembler::AssemblyValsCache &ass_vals_cache,
41 const assembler::AssemblyValsCache &mass_ass_vals_cache,
42
43 // Body form
44 const int n_pressure_bases,
45 const std::vector<int> &boundary_nodes,
46 const std::vector<mesh::LocalBoundary> &local_boundary,
47 const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
48 const int n_boundary_samples,
49 const Eigen::MatrixXd &rhs,
50 const Eigen::MatrixXd &sol,
51 const assembler::Density &density,
52
53 // Pressure form
54 const std::vector<mesh::LocalBoundary> &local_pressure_boundary,
55 const std::unordered_map<int, std::vector<mesh::LocalBoundary>> &local_pressure_cavity,
56 const std::shared_ptr<assembler::PressureAssembler> pressure_assembler,
57
58 // Inertia form
59 const bool ignore_inertia,
60 const StiffnessMatrix &mass,
61 const std::shared_ptr<assembler::ViscousDamping> damping_assembler,
62
63 // Lagged regularization form
64 const double lagged_regularization_weight,
65 const int lagged_regularization_iterations,
66
67 // Augemented lagrangian form
68 // const std::vector<int> &boundary_nodes,
69 // const std::vector<mesh::LocalBoundary> &local_boundary,
70 // const std::vector<mesh::LocalBoundary> &local_neumann_boundary,
71 // const int n_boundary_samples,
72 // const StiffnessMatrix &mass,
73 const size_t obstacle_ndof,
74
75 // Contact form
76 const bool contact_enabled,
77 const ipc::CollisionMesh &collision_mesh,
78 const double dhat,
79 const double avg_mass,
80 const bool use_convergent_contact_formulation,
81 const json &barrier_stiffness,
82 const ipc::BroadPhaseMethod broad_phase,
83 const double ccd_tolerance,
84 const long ccd_max_iterations,
85 const bool enable_shape_derivatives,
86
87 // Homogenization
88 const assembler::MacroStrainValue &macro_strain_constraint,
89
90 // Periodic contact
91 const bool periodic_contact,
92 const Eigen::VectorXi &tiled_to_single,
93
94 // Friction form
95 const double friction_coefficient,
96 const double epsv,
97 const int friction_iterations,
98
99 // Rayleigh damping form
100 const json &rayleigh_damping)
101 {
102 const bool is_time_dependent = time_integrator != nullptr;
103 assert(!is_time_dependent || time_integrator != nullptr);
104 const double dt = is_time_dependent ? time_integrator->dt() : 0.0;
105 const int ndof = n_bases * dim;
106 // if (is_formulation_mixed) // mixed not supported
107 // ndof_ += n_pressure_bases; // pressure is a scalar
108 const bool is_volume = dim == 3;
109
110 std::vector<std::shared_ptr<Form>> forms;
111
112 elastic_form = std::make_shared<ElasticForm>(
113 n_bases, bases, geom_bases, assembler, ass_vals_cache,
114 t, dt, is_volume);
115 forms.push_back(elastic_form);
116
117 if (rhs_assembler != nullptr)
118 {
119 body_form = std::make_shared<BodyForm>(
120 ndof, n_pressure_bases, boundary_nodes, local_boundary,
121 local_neumann_boundary, n_boundary_samples, rhs, *rhs_assembler,
122 density, /*apply_DBC=*/true, /*is_formulation_mixed=*/false,
123 is_time_dependent);
124 body_form->update_quantities(t, sol);
125 forms.push_back(body_form);
126 }
127
128 if (pressure_assembler != nullptr)
129 {
130 pressure_form = std::make_shared<PressureForm>(
131 ndof,
132 local_pressure_boundary,
133 local_pressure_cavity,
134 boundary_nodes,
135 n_boundary_samples, *pressure_assembler,
136 is_time_dependent);
137 pressure_form->update_quantities(t, sol);
138 forms.push_back(pressure_form);
139 }
140
141 inertia_form = nullptr;
142 damping_form = nullptr;
143 if (is_time_dependent)
144 {
145 if (!ignore_inertia)
146 {
147 assert(time_integrator != nullptr);
148 inertia_form = std::make_shared<InertiaForm>(mass, *time_integrator);
149 forms.push_back(inertia_form);
150 }
151
152 if (damping_assembler != nullptr)
153 {
154 damping_form = std::make_shared<ElasticForm>(
155 n_bases, bases, geom_bases, *damping_assembler, ass_vals_cache, t, dt, is_volume);
156 forms.push_back(damping_form);
157 }
158 }
159 else
160 {
161 if (lagged_regularization_weight > 0)
162 {
163 forms.push_back(std::make_shared<LaggedRegForm>(lagged_regularization_iterations));
164 forms.back()->set_weight(lagged_regularization_weight);
165 }
166 }
167
168 if (rhs_assembler != nullptr)
169 {
170 // assembler::Mass mass_mat_assembler;
171 // mass_mat_assembler.set_size(dim);
172 StiffnessMatrix mass_tmp = mass;
173 // mass_mat_assembler.assemble(dim == 3, n_bases, bases, geom_bases, mass_ass_vals_cache, mass_tmp, true);
174 // assert(mass_tmp.rows() == mass.rows() && mass_tmp.cols() == mass.cols());
175
176 al_lagr_form = std::make_shared<BCLagrangianForm>(
177 ndof, boundary_nodes, local_boundary, local_neumann_boundary,
178 n_boundary_samples, mass_tmp, *rhs_assembler, obstacle_ndof, is_time_dependent, t);
179 forms.push_back(al_lagr_form);
180
181 al_pen_form = std::make_shared<BCPenaltyForm>(
182 ndof, boundary_nodes, local_boundary, local_neumann_boundary,
183 n_boundary_samples, mass_tmp, *rhs_assembler, obstacle_ndof, is_time_dependent, t);
184 forms.push_back(al_pen_form);
185 }
186
187 if (macro_strain_constraint.is_active())
188 {
189 // don't push these two into forms because they take a different input x
190 strain_al_pen_form = std::make_shared<MacroStrainALForm>(macro_strain_constraint);
191 strain_al_lagr_form = std::make_shared<MacroStrainLagrangianForm>(macro_strain_constraint);
192 }
193
194 contact_form = nullptr;
195 periodic_contact_form = nullptr;
196 friction_form = nullptr;
197 if (contact_enabled)
198 {
199 const bool use_adaptive_barrier_stiffness = !barrier_stiffness.is_number();
200
201 if (periodic_contact)
202 {
203 periodic_contact_form = std::make_shared<PeriodicContactForm>(
204 collision_mesh, tiled_to_single, dhat, avg_mass, use_convergent_contact_formulation,
205 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase, ccd_tolerance,
206 ccd_max_iterations);
207
208 if (use_adaptive_barrier_stiffness)
209 {
210 periodic_contact_form->set_barrier_stiffness(1);
211 // logger().debug("Using adaptive barrier stiffness");
212 }
213 else
214 {
215 assert(barrier_stiffness.is_number());
216 assert(barrier_stiffness.get<double>() > 0);
217 periodic_contact_form->set_barrier_stiffness(barrier_stiffness);
218 // logger().debug("Using fixed barrier stiffness of {}", contact_form->barrier_stiffness());
219 }
220 }
221 else
222 {
223 contact_form = std::make_shared<ContactForm>(
224 collision_mesh, dhat, avg_mass, use_convergent_contact_formulation,
225 use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase, ccd_tolerance * units.characteristic_length(),
226 ccd_max_iterations);
227
228 if (use_adaptive_barrier_stiffness)
229 {
230 contact_form->set_barrier_stiffness(1);
231 // logger().debug("Using adaptive barrier stiffness");
232 }
233 else
234 {
235 assert(barrier_stiffness.is_number());
236 assert(barrier_stiffness.get<double>() > 0);
237 contact_form->set_barrier_stiffness(barrier_stiffness);
238 // logger().debug("Using fixed barrier stiffness of {}", contact_form->barrier_stiffness());
239 }
240
241 if (contact_form)
242 forms.push_back(contact_form);
243
244 // ----------------------------------------------------------------
245 }
246
247 if (friction_coefficient != 0)
248 {
249 friction_form = std::make_shared<FrictionForm>(
250 collision_mesh, time_integrator, epsv, friction_coefficient,
251 broad_phase, *contact_form, friction_iterations);
252 friction_form->init_lagging(sol);
253 forms.push_back(friction_form);
254 }
255 }
256
257 const std::vector<json> rayleigh_damping_jsons = utils::json_as_array(rayleigh_damping);
258 if (is_time_dependent)
259 {
260 // Map from form name to form so RayleighDampingForm::create can get the correct form to damp
261 const std::unordered_map<std::string, std::shared_ptr<Form>> possible_forms_to_damp = {
262 {"elasticity", elastic_form},
263 {"contact", contact_form},
264 };
265
266 for (const json &params : rayleigh_damping_jsons)
267 {
268 forms.push_back(RayleighDampingForm::create(
269 params, possible_forms_to_damp,
271 }
272 }
273 else if (rayleigh_damping_jsons.size() > 0)
274 {
275 log_and_throw_adjoint_error("Rayleigh damping is only supported for time-dependent problems");
276 }
277
278 update_dt();
279
280 return forms;
281 }
282
283 void SolveData::update_barrier_stiffness(const Eigen::VectorXd &x)
284 {
285 if (contact_form == nullptr || !contact_form->use_adaptive_barrier_stiffness())
286 return;
287
288 Eigen::VectorXd grad_energy = Eigen::VectorXd::Zero(x.size());
289 const std::array<std::shared_ptr<Form>, 4> energy_forms{
291 for (const std::shared_ptr<Form> &form : energy_forms)
292 {
293 if (form == nullptr || !form->enabled())
294 continue;
295
296 Eigen::VectorXd grad_form;
297 form->first_derivative(x, grad_form);
298 grad_energy += grad_form;
299 }
300
301 contact_form->update_barrier_stiffness(x, grad_energy);
302 }
303
305 {
306 if (time_integrator == nullptr) // if is not time dependent
307 return;
308
309 const std::array<std::shared_ptr<Form>, 6> energy_forms{
311 for (const std::shared_ptr<Form> &form : energy_forms)
312 {
313 if (form == nullptr)
314 continue;
315 form->set_weight(time_integrator->acceleration_scaling());
316 }
317 }
318
319 std::vector<std::pair<std::string, std::shared_ptr<solver::Form>>> SolveData::named_forms() const
320 {
321 return {
322 {"elastic", elastic_form},
323 {"inertia", inertia_form},
324 {"body", body_form},
325 {"contact", contact_form},
326 {"friction", friction_form},
327 {"damping", damping_form},
328 {"pressure", pressure_form},
329 {"augmented_lagrangian_lagr", al_lagr_form},
330 {"augmented_lagrangian_penalty", al_pen_form},
331 {"strain_augmented_lagrangian_lagr", strain_al_lagr_form},
332 {"strain_augmented_lagrangian_penalty", strain_al_pen_form},
333 {"periodic_contact", periodic_contact_form},
334 };
335 }
336} // namespace polyfem::solver
int x
double characteristic_length() const
Definition Units.hpp:22
Caches basis evaluation and geometric mapping at every element.
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::BCPenaltyForm > al_pen_form
std::shared_ptr< solver::MacroStrainLagrangianForm > strain_al_lagr_form
std::shared_ptr< solver::ContactForm > contact_form
std::shared_ptr< solver::MacroStrainALForm > strain_al_pen_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< Form > > init_forms(const Units &units, const int dim, const double t, const int n_bases, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &geom_bases, const assembler::Assembler &assembler, const assembler::AssemblyValsCache &ass_vals_cache, const assembler::AssemblyValsCache &mass_ass_vals_cache, 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 int 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 bool contact_enabled, const ipc::CollisionMesh &collision_mesh, const double dhat, const double avg_mass, const bool use_convergent_contact_formulation, const json &barrier_stiffness, const ipc::BroadPhaseMethod broad_phase, const double ccd_tolerance, const long ccd_max_iterations, const bool enable_shape_derivatives, 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)
Initialize the forms and return a vector of pointers to them.
Definition SolveData.cpp:29
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::BCLagrangianForm > al_lagr_form
std::shared_ptr< assembler::PressureAssembler > pressure_assembler
std::shared_ptr< assembler::RhsAssembler > rhs_assembler
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
Definition JSONUtils.hpp:38
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:77
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:20