PolyFEM
Loading...
Searching...
No Matches
DifferentiableNonlinearElasticVarForm.cpp
Go to the documentation of this file.
2
15
16#include <igl/Timer.h>
17
18#include <polysolve/linear/Solver.hpp>
19#include <polysolve/nonlinear/Solver.hpp>
20
21namespace polyfem::varform
22{
24 Eigen::MatrixXd &solution,
25 const InitialConditionOverride *initial_condition_override,
26 const ForwardStepCallback &post_step,
27 const bool differentiable)
28 {
29 differentiable_mode_ = differentiable;
30 NonlinearElasticVarForm::solve(solution, initial_condition_override, post_step);
31 }
32
37
39 const std::string &path,
40 const Eigen::MatrixXd &solution,
41 const double time,
42 const double dt) const
43 {
46 const auto opts = NonlinearElasticVarForm::export_options(space);
48 path, space, NonlinearElasticVarForm::output_field_function(solution, opts), time, dt, opts);
49 }
50
53
55 {
56 assert(mesh_ && "The mesh must be loaded before it is accessed");
57 return *mesh_;
58 }
59
61 {
62 assert(problem && "The problem must be initialized before it is accessed");
63 return *problem;
64 }
65
67 {
68 assert(problem && "The problem must be initialized before it is accessed");
69 return *problem;
70 }
71
72 std::string DifferentiableNonlinearElasticVarForm::output_file_path(const std::string &path) const
73 {
75 }
76
79
82
84 {
85 assert(primary_assembler_ && "The primary assembler must be initialized before it is accessed");
86 return *primary_assembler_;
87 }
88
90 {
91 assert(mass_assembler_ && "The mass assembler must be initialized before it is accessed");
92 return *mass_assembler_;
93 }
94
100 const ipc::CollisionMesh &DifferentiableNonlinearElasticVarForm::collision_mesh() const { return collision_mesh_; }
102
107
112
114 Eigen::MatrixXd &solution,
115 const InitialConditionOverride *override) const
116 {
118 }
119
121 Eigen::MatrixXd &velocity,
122 const InitialConditionOverride *override) const
123 {
125 }
126
128 Eigen::MatrixXd &acceleration,
129 const InitialConditionOverride *override) const
130 {
131 NonlinearElasticVarForm::initial_acceleration(acceleration, override);
132 }
133
140
142 {
143 assert(mesh_ && "Vertex positions can only be updated after loading a mesh");
144 return *mesh_;
145 }
146
160
173
175 const int discr_order,
176 const int discr_orderq,
177 const int geometry_discr_order) const
178 {
179 return NonlinearElasticVarForm::n_boundary_samples(discr_order, discr_orderq, geometry_discr_order);
180 }
181
182 // The differentiable path matches NonlinearElasticVarForm::init_forms except
183 // that it enables IPC shape derivatives when constructing the contact forms.
185 const json &args,
186 const int dim,
187 Eigen::MatrixXd &solution,
188 const double time)
189 {
191 {
192 NonlinearElasticVarForm::init_forms(args, dim, solution, time);
193 return;
194 }
195
196 damping_assembler_ = std::make_shared<assembler::ViscousDamping>();
197 set_materials(*damping_assembler_, mesh_->dimension());
198
200
201 damping_prev_assembler_ = std::make_shared<assembler::ViscousDampingPrev>();
203
204 const solver::ElementInversionCheck check_inversion = args["solver"]["advanced"]["check_inversion"];
205
207 units,
209 dim, time, space_.space_in_node_to_node,
210 space_.n_bases, *space_.bases, space_.geometry_basis_list(), *primary_assembler_, ass_vals_cache_, mass_ass_vals_cache_, args["solver"]["advanced"]["jacobian_threshold"], check_inversion,
211 args["solver"]["advanced"]["conservative_max_iter"],
214 elastic_boundary_samples(), rhs_, solution, mass_assembler_->density(),
216 args.value("/time/quasistatic"_json_pointer, true), mass_,
217 damping_assembler_->is_valid() ? damping_assembler_ : nullptr,
218 args["solver"]["advanced"]["lagged_regularization_weight"],
219 args["solver"]["advanced"]["lagged_regularization_iterations"],
220 obstacle.ndof(), args["constraints"]["hard"], args["constraints"]["soft"], args["constraints"]["zero_mean"],
221 args["contact"]["enabled"],
222 args["contact"]["periodic"] ? periodic_collision_mesh_ : collision_mesh_,
223 args["contact"]["dhat"],
224 avg_mass_, args["contact"]["use_convergent_formulation"] ? bool(args["contact"]["use_area_weighting"]) : false,
225 args["contact"]["use_convergent_formulation"] ? bool(args["contact"]["use_improved_max_operator"]) : false,
226 args["contact"]["use_convergent_formulation"] ? bool(args["contact"]["use_physical_barrier"]) : false,
227 args["solver"]["contact"]["barrier_stiffness"],
228 args["solver"]["contact"]["initial_barrier_stiffness"],
229 args["solver"]["contact"]["CCD"]["broad_phase"],
230 args["solver"]["contact"]["CCD"]["tolerance"],
231 args["solver"]["contact"]["CCD"]["max_iterations"],
232 true,
233 args["contact"]["use_gcp_formulation"],
234 args["contact"]["alpha_t"],
235 args["contact"]["alpha_n"],
236 args["contact"]["use_adaptive_dhat"],
237 args["contact"]["min_distance_ratio"],
238 args["contact"]["adhesion"]["adhesion_enabled"],
239 args["contact"]["adhesion"]["dhat_p"],
240 args["contact"]["adhesion"]["dhat_a"],
241 args["contact"]["adhesion"]["adhesion_strength"],
242 args["contact"]["adhesion"]["tangential_adhesion_coefficient"],
243 args["contact"]["adhesion"]["epsa"],
244 args["solver"]["contact"]["tangential_adhesion_iterations"],
246 args["contact"]["periodic"], periodic_collision_mesh_to_basis_,
247 args["contact"]["friction_coefficient"],
248 args["contact"]["epsv"],
249 args["solver"]["contact"]["friction_iterations"],
250 args["solver"]["rayleigh_damping"],
251 args["solver"]["augmented_lagrangian"]["lumping"],
253 args["boundary_conditions"]["periodic"], /*fe_space_id=*/-1);
254
255 for (const auto &form : forms)
256 form->set_output_dir(output_path);
257
258 if (solve_data_.contact_form != nullptr)
259 solve_data_.contact_form->save_ccd_debug_meshes = args["output"]["advanced"]["save_ccd_debug_meshes"];
260 }
261
262 // The differentiable path performs the initial nonlinear solve but skips the
263 // subsequent lagging iterations. The adjoint uses the forms frozen at that
264 // solution instead of differentiating through the lagging update loop.
266 const int step,
267 Eigen::MatrixXd &solution,
268 const bool init_lagging)
269 {
271 {
272 NonlinearElasticVarForm::solve_tensor_nonlinear(step, solution, init_lagging);
273 return;
274 }
275
276 assert(solve_data_.nl_problem != nullptr && "Nonlinear forms must initialize the nonlinear problem before solving");
278 assert(solution.size() == rhs_.size());
279
280 if (nl_problem.uses_lagging())
281 {
282 if (init_lagging)
283 {
284 POLYFEM_SCOPED_TIMER("Initializing lagging");
285 nl_problem.init_lagging(solution);
286 }
287 logger().info("Lagging iteration 1:");
288 }
289
290 save_subsolve(0, step, solution);
291
292 std::shared_ptr<polysolve::nonlinear::Solver> nl_solver =
293 polysolve::nonlinear::Solver::create(
294 args["solver"]["augmented_lagrangian"]["nonlinear"],
295 args["solver"]["linear"], units.characteristic_length(), logger());
296
297 solver::ALSolver al_solver(
299 args["solver"]["augmented_lagrangian"]["initial_weight"],
300 args["solver"]["augmented_lagrangian"]["scaling"],
301 args["solver"]["augmented_lagrangian"]["max_weight"],
302 args["solver"]["augmented_lagrangian"]["eta"],
303 [&](const Eigen::VectorXd &) {
304 solve_data_.update_barrier_stiffness(solution);
305 });
306
307 al_solver.post_subsolve = [&](const double al_weight) {
308 stats.solver_info.push_back(
309 {{"type", al_weight > 0 ? "al" : "rc"},
310 {"t", step},
311 {"info", nl_solver->info()}});
312 if (al_weight > 0)
313 stats.solver_info.back()["weight"] = al_weight;
314 save_subsolve(stats.solver_info.size(), step, solution);
315 };
316
317 al_solver.solve_al(
318 nl_problem, solution,
319 args["solver"]["augmented_lagrangian"]["nonlinear"],
320 args["solver"]["linear"], units.characteristic_length());
321
322 al_solver.solve_reduced(
323 nl_problem, solution,
324 args["solver"]["nonlinear"],
325 args["solver"]["linear"], units.characteristic_length());
326
327 if (args["space"]["advanced"]["count_flipped_els_continuous"])
328 {
329 const auto invalid = utils::count_invalid(
330 mesh_->dimension(), space_.basis_list(), space_.geometry_basis_list(), solution);
331 logger().debug("Flipped elements (cnt {}) : {}", invalid.size(), invalid);
332 }
333 }
334
336 Eigen::MatrixXd &solution,
337 const double time,
338 const InitialConditionOverride *initial_condition_override)
339 {
340 assert(is_homogenization());
343 mesh_->dimension(), args["constraints"]["macro_displacement_gradient"], resources_);
344 init_solve_data(solution, time, "", initial_condition_override);
345
346 for (const auto &[name, form] : solve_data_.named_forms())
347 {
348 if (name == "augmented_lagrangian")
349 {
350 form->set_weight(0);
351 form->disable();
352 }
353 }
354
355 bool solve_symmetric_macro_strain = false;
356 const Eigen::VectorXi &fixed_entries = macro_strain_constraint_.get_fixed_entry();
357 const int dim = mesh_->dimension();
358 for (int i = 0; i < dim && !solve_symmetric_macro_strain; ++i)
359 {
360 for (int j = 0; j < i; ++j)
361 {
362 const bool ij_fixed = std::find(
363 fixed_entries.data(), fixed_entries.data() + fixed_entries.size(), i + j * dim)
364 != fixed_entries.data() + fixed_entries.size();
365 const bool ji_fixed = std::find(
366 fixed_entries.data(), fixed_entries.data() + fixed_entries.size(), j + i * dim)
367 != fixed_entries.data() + fixed_entries.size();
368 if (!ij_fixed && !ji_fixed)
369 solve_symmetric_macro_strain = true;
370 }
371 }
372
373 double characteristic_length = args["solver"]["advanced"]["characteristic_length"];
374 if (characteristic_length <= 0)
375 {
376 RowVectorNd min, max;
377 mesh_->bounding_box(min, max);
378 characteristic_length = (max - min).norm();
379 }
380 double characteristic_force_density = args["solver"]["advanced"]["characteristic_force_density"];
381 if (characteristic_force_density <= 0)
382 characteristic_force_density = 10000;
383
384 const int ndof = space_.n_bases * dim;
385 auto homo_problem = std::make_shared<solver::NLHomoProblem>(
387 time, forms, solve_data_.al_form, solve_symmetric_macro_strain,
388 polysolve::linear::Solver::create(args["solver"]["linear"], logger()),
389 characteristic_length, characteristic_force_density, pure_mass_, dim);
391 homo_problem->add_form(solve_data_.periodic_contact_form);
393 homo_problem->add_form(solve_data_.strain_al_lagr_form);
394
395 solve_data_.nl_problem = homo_problem;
396 const Eigen::VectorXd initial_reduced = Eigen::VectorXd::Zero(
397 homo_problem->reduced_size() + homo_problem->macro_reduced_size());
398 homo_problem->init(initial_reduced);
399 homo_problem->update_quantities(time, initial_reduced);
400 stats.solver_info = json::array();
401 }
402
404 Eigen::MatrixXd &solution,
405 const ForwardStepCallback &post_step)
406 {
407 auto homo_problem = std::dynamic_pointer_cast<solver::NLHomoProblem>(solve_data_.nl_problem);
408 assert(homo_problem && solve_data_.strain_al_lagr_form);
409
410 const int dim = mesh_->dimension();
411 Eigen::VectorXd extended_solution = Eigen::VectorXd::Zero(homo_problem->full_size() + dim * dim);
412 const Eigen::VectorXi &fixed_entries = macro_strain_constraint_.get_fixed_entry();
413 homo_problem->set_fixed_entry({});
414
415 auto lagrangian_form = solve_data_.strain_al_lagr_form;
416 lagrangian_form->enable();
417 Eigen::VectorXd reduced_solution = homo_problem->extended_to_reduced(extended_solution);
418 const Eigen::VectorXd initial_solution = reduced_solution;
419 const Eigen::VectorXi fixed_indices = fixed_entries.array() + homo_problem->full_size();
420 const Eigen::VectorXd fixed_values =
421 utils::flatten(macro_strain_constraint_.eval(/*time=*/0))(fixed_entries);
422 const double initial_error = lagrangian_form->compute_error(extended_solution);
423 extended_solution(fixed_indices) = fixed_values;
424 Eigen::VectorXd constrained_solution = homo_problem->extended_to_reduced(extended_solution);
425 homo_problem->line_search_begin(reduced_solution, constrained_solution);
426
427 double al_weight = args["solver"]["augmented_lagrangian"]["initial_weight"];
428 const double max_weight = args["solver"]["augmented_lagrangian"]["max_weight"];
429 const double eta_tolerance = args["solver"]["augmented_lagrangian"]["eta"];
430 const double scaling = args["solver"]["augmented_lagrangian"]["scaling"];
431 lagrangian_form->set_initial_weight(al_weight);
432 bool force_al_solve = true;
433
434 while (force_al_solve
435 || !std::isfinite(homo_problem->value(constrained_solution))
436 || !homo_problem->is_step_valid(reduced_solution, constrained_solution)
437 || !homo_problem->is_step_collision_free(reduced_solution, constrained_solution))
438 {
439 force_al_solve = false;
440 homo_problem->line_search_end();
441 homo_problem->init(reduced_solution);
442 auto nonlinear_solver = polysolve::nonlinear::Solver::create(
443 args["solver"]["augmented_lagrangian"]["nonlinear"],
444 args["solver"]["linear"], units.characteristic_length(), logger());
445 homo_problem->normalize_forms();
446 nonlinear_solver->minimize(*homo_problem, reduced_solution);
447
448 extended_solution = homo_problem->reduced_to_extended(reduced_solution);
449 const double current_error = lagrangian_form->compute_error(extended_solution);
450 const double eta = initial_error > 0 ? 1 - std::sqrt(current_error / initial_error) : 1;
451 if (eta < eta_tolerance && al_weight < max_weight)
452 al_weight *= scaling;
453 else
454 lagrangian_form->update_lagrangian(extended_solution, al_weight);
455 if (eta <= 0)
456 reduced_solution = initial_solution;
457
458 extended_solution(fixed_indices) = fixed_values;
459 constrained_solution = homo_problem->extended_to_reduced(extended_solution);
460 homo_problem->line_search_begin(reduced_solution, constrained_solution);
461 }
462 homo_problem->line_search_end();
463 lagrangian_form->disable();
464
465 homo_problem->set_fixed_entry(fixed_entries);
466 reduced_solution = homo_problem->extended_to_reduced(extended_solution);
467 homo_problem->init(reduced_solution);
468 auto nonlinear_solver = polysolve::nonlinear::Solver::create(
469 args["solver"]["nonlinear"], args["solver"]["linear"],
471 homo_problem->normalize_forms();
472 nonlinear_solver->minimize(*homo_problem, reduced_solution);
473
474 displacement_gradient_ = homo_problem->reduced_to_disp_grad(reduced_solution);
475 solution = homo_problem->reduced_to_full(reduced_solution);
476 if (post_step)
477 post_step(0, solution);
478 }
479
480 // Same as NonlinearElasticStaticVarForm
482 Eigen::MatrixXd &solution,
483 const InitialConditionOverride *initial_condition_override,
484 const ForwardStepCallback &post_step)
485 {
486 assert(
487 (!initial_condition_override
488 || (initial_condition_override->velocity.size() == 0
489 && initial_condition_override->acceleration.size() == 0))
490 && "Static elasticity does not accept initial velocity or acceleration overrides");
491
492 stats.spectrum.setZero();
493
494 igl::Timer timer;
495 timer.start();
496 logger().info("Solving {}", primary_assembler_->name());
497
498 {
499 POLYFEM_SCOPED_TIMER("Setup RHS");
500
501 if (initial_condition_override && initial_condition_override->solution.size() != 0)
502 initial_solution(solution, initial_condition_override);
503 else if (solution.size() <= 0)
504 initial_solution(solution, initial_condition_override);
505
506 if (initial_condition_override && initial_condition_override->solution.size() != 0)
507 assert(solution.cols() == 1 && "Static initial solution override must have exactly one column");
508 else if (solution.cols() != 1)
509 log_and_throw_error("Static elasticity requires exactly one initial solution column.");
510 }
511
512 if (is_homogenization())
513 {
514 init_homogenization_solve(solution, /*time=*/0, initial_condition_override);
515 solve_homogenization_step(solution, post_step);
516 timer.stop();
517 timings.solving_time = timer.getElapsedTime();
518 logger().info(" took {}s", timings.solving_time);
519 return;
520 }
521
522 init_solve(solution, 1.0, initial_condition_override);
523 solve_tensor_nonlinear(0, solution, true);
524 if (post_step)
525 post_step(0, solution);
526
527 timer.stop();
528 timings.solving_time = timer.getElapsedTime();
529 logger().info(" took {}s", timings.solving_time);
530 }
531
532 // Same as NonlinearElasticTransientVarForm.
534 Eigen::MatrixXd &solution,
535 const InitialConditionOverride *initial_condition_override,
536 const ForwardStepCallback &post_step)
537 {
538 const bool save_stats = args["output"]["stats"];
539 stats.spectrum.setZero();
540
541 igl::Timer timer;
542 timer.start();
543 logger().info("Solving {}", primary_assembler_->name());
544
545 {
546 POLYFEM_SCOPED_TIMER("Setup RHS");
547
548 if (initial_condition_override && initial_condition_override->solution.size() != 0)
549 initial_solution(solution, initial_condition_override);
550 else if (solution.size() <= 0)
551 initial_solution(solution, initial_condition_override);
552
553 if (solution.cols() > 1)
554 solution.conservativeResize(Eigen::NoChange, 1);
555 }
556
557 init_solve(solution, t0 + dt, initial_condition_override);
558 if (post_step)
559 post_step(0, solution);
560
561 int save_i = 0;
562 std::unique_ptr<io::EnergyCSVWriter> energy_csv;
563 std::unique_ptr<io::RuntimeStatsCSVWriter> stats_csv;
564
565 if (save_stats)
566 {
567 logger().debug(
568 "Saving nl stats to {} and {}",
569 resolve_output_path("energy.csv"), resolve_output_path("stats.csv"));
570 energy_csv = std::make_unique<io::EnergyCSVWriter>(resolve_output_path("energy.csv"), solve_data_);
571 const io::OutputSpace space = output_space();
572 stats_csv = std::make_unique<io::RuntimeStatsCSVWriter>(
573 resolve_output_path("stats.csv"),
575 space.mesh ? space.mesh->n_elements() : 0,
576 t0, dt);
577 }
578
579 if (energy_csv)
580 energy_csv->write(save_i, solution);
581 save_timestep(t0, 0, t0, dt, solution);
582 ++save_i;
583
584 for (int t = 1; t <= time_steps; ++t)
585 {
586 double forward_solve_time = 0;
587 const double remeshing_time = 0;
588 const double global_relaxation_time = 0;
589
590 {
591 POLYFEM_SCOPED_TIMER(forward_solve_time);
592 solve_tensor_nonlinear(t, solution, true);
593 }
594 if (post_step)
595 post_step(t, solution);
596
597 if (energy_csv)
598 energy_csv->write(save_i, solution);
599 save_timestep(t0 + dt * t, t, t0, dt, solution);
600 ++save_i;
601
602 {
603 POLYFEM_SCOPED_TIMER("Update quantities");
605 solve_data_.time_integrator->update_quantities(solution);
606 solve_data_.nl_problem->update_quantities(t0 + (t + 1) * dt, solution);
609 }
610
611 logger().info("{}/{} t={}", t, time_steps, t0 + dt * t);
614 if (stats_csv)
615 stats_csv->write(t, forward_solve_time, remeshing_time, global_relaxation_time);
616 }
617
618 timer.stop();
619 timings.solving_time = timer.getElapsedTime();
620 logger().info(" took {}s", timings.solving_time);
621 }
622} // namespace polyfem::varform
#define POLYFEM_SCOPED_TIMER(...)
Definition Timer.hpp:10
double characteristic_length() const
Definition Units.hpp:22
Caches basis evaluation and geometric mapping at every element.
void init(const int dim, const json &param, const io::ResourceIO &resources)
Eigen::MatrixXd eval(const double t) const
const Eigen::VectorXi & get_fixed_entry() const
void save_vtu(const std::string &path, const OutputSpace &space, const OutputFieldFunction &output_fields, const double t, const double dt, const ExportOptions &opts) const
saves the vtu file for time t
Definition OutData.cpp:2162
double solving_time
time to solve
json solver_info
information of the solver, eg num iteration, time, errors, etc the informations varies depending on t...
Eigen::Vector4d spectrum
spectrum of the stiffness matrix, enable only if POLYSOLVE_WITH_SPECTRA is ON (off by default)
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
Definition Mesh.hpp:148
void solve_reduced(NLProblem &nl_problem, Eigen::MatrixXd &sol, std::shared_ptr< polysolve::nonlinear::Solver > nl_solver)
Definition ALSolver.hpp:41
std::function< void(const double)> post_subsolve
Definition ALSolver.hpp:53
void solve_al(NLProblem &nl_problem, Eigen::MatrixXd &sol, std::shared_ptr< polysolve::nonlinear::Solver > nl_solver)
Definition ALSolver.hpp:29
void init_lagging(const TVector &x) override
class to store time stepping data
Definition SolveData.hpp:56
std::shared_ptr< solver::PeriodicContactForm > periodic_contact_form
void update_dt()
updates the dt inside the different forms
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::NLProblem > nl_problem
std::shared_ptr< solver::MacroStrainLagrangianForm > strain_al_lagr_form
std::shared_ptr< solver::ContactForm > contact_form
std::vector< std::pair< std::string, std::shared_ptr< solver::Form > > > named_forms() const
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
void solve_problem(Eigen::MatrixXd &solution, const InitialConditionOverride *initial_condition_override, const ForwardStepCallback &post_step) override
void solve_problem(Eigen::MatrixXd &solution, const InitialConditionOverride *initial_condition_override, const ForwardStepCallback &post_step) override
void init_homogenization_solve(Eigen::MatrixXd &solution, double time, const InitialConditionOverride *initial_condition_override)
void init_forms(const json &args, int dim, Eigen::MatrixXd &solution, double time) override
const assembler::ViscousDampingPrev * damping_prev_assembler() const override
QuadratureOrders boundary_samples(int discr_order, int discr_orderq, int geometry_discr_order) const override
void initial_solution(Eigen::MatrixXd &solution, const InitialConditionOverride *override=nullptr) const override
void initial_velocity(Eigen::MatrixXd &velocity, const InitialConditionOverride *override=nullptr) const override
void solve_tensor_nonlinear(int step, Eigen::MatrixXd &solution, bool init_lagging=true) override
void solve(Eigen::MatrixXd &solution, const InitialConditionOverride *initial_condition_override, const ForwardStepCallback &post_step, bool differentiable) override
const assembler::AssemblyValsCache & assembly_cache() const override
void solve_homogenization_step(Eigen::MatrixXd &solution, const ForwardStepCallback &post_step)
void initial_acceleration(Eigen::MatrixXd &acceleration, const InitialConditionOverride *override=nullptr) const override
bool is_contact_enabled() const override
Check if contact is enabled for the variational formulation, for output purposes.
const assembler::AssemblyValsCache & mass_assembly_cache() const override
void save_vtu(const std::string &path, const Eigen::MatrixXd &solution, double time, double dt) const override
std::string output_file_path(const std::string &path) const override
virtual Eigen::MatrixXd displacement_gradient() const
virtual std::string name() const =0
std::shared_ptr< assembler::Assembler > primary_assembler_
QuadratureOrders elastic_boundary_samples() const
assembler::AssemblyValsCache ass_vals_cache_
std::shared_ptr< assembler::Mass > mass_assembler_
void save_elastic_step_state(const double t0, const double dt, const int t, const Eigen::MatrixXd &solution, const time_integrator::ImplicitTimeIntegrator *time_integrator) const
std::shared_ptr< assembler::RhsAssembler > rhs_assembler_
assembler::AssemblyValsCache mass_ass_vals_cache_
void initial_velocity(Eigen::MatrixXd &velocity, const InitialConditionOverride *override=nullptr, const std::string &state_prefix="") const
void initial_acceleration(Eigen::MatrixXd &acceleration, const InitialConditionOverride *override=nullptr, const std::string &state_prefix="") const
void initial_solution(Eigen::MatrixXd &solution, const InitialConditionOverride *override=nullptr, const std::string &state_prefix="") const
A finite-element space for one scalar- or vector-valued field.
Definition FESpace.hpp:59
const std::vector< basis::ElementBases > & geometry_basis_list() const
Definition FESpace.hpp:115
std::shared_ptr< std::vector< basis::ElementBases > > bases
Per-element basis data.
Definition FESpace.hpp:68
int n_bases
Number of globally indexed scalar basis functions in the space.
Definition FESpace.hpp:65
Eigen::VectorXi space_in_node_to_node
Definition FESpace.hpp:91
const std::vector< basis::ElementBases > & basis_list() const
Definition FESpace.hpp:109
std::shared_ptr< mesh::MeshNodes > mesh_nodes
Optional primitive-to-node mapping for this FE space.
Definition FESpace.hpp:86
virtual void init_forms(const json &args, int dim, Eigen::MatrixXd &sol, double t)
std::shared_ptr< assembler::PressureAssembler > elasticity_pressure_assembler
std::shared_ptr< assembler::ViscousDampingPrev > damping_prev_assembler_
virtual void solve_tensor_nonlinear(int step, Eigen::MatrixXd &sol, bool init_lagging=true)
void init_solve(Eigen::MatrixXd &sol, double t, const InitialConditionOverride *initial_condition_override)
std::shared_ptr< assembler::ViscousDamping > damping_assembler_
io::OutputSpace output_space() const override
Get the output space of the variational formulation, for output purposes.
void init_solve_data(Eigen::MatrixXd &sol, double t, const std::string &state_prefix, const InitialConditionOverride *initial_condition_override=nullptr)
bool is_contact_enabled() const override
Check if contact is enabled for the variational formulation, for output purposes.
std::vector< std::shared_ptr< solver::Form > > forms
std::shared_ptr< assembler::PressureAssembler > build_pressure_assembler() const
void prepare()
Prepare all discretization and assembly data without running a solve.
Definition VarForm.cpp:259
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
Definition VarForm.hpp:261
void solve(Eigen::MatrixXd &sol, const InitialConditionOverride *initial_condition_override=nullptr, const ForwardStepCallback &post_step={})
Solve the variational formulation and store the solution in the given matrix.
Definition VarForm.cpp:594
std::unique_ptr< mesh::Mesh > mesh_
Definition VarForm.hpp:273
io::OutStatsData stats
Definition VarForm.hpp:265
void notify_time_step(const int t, const int time_steps, const double t0, const double dt) const
Definition VarForm.cpp:1105
io::OutGeometryData::ExportOptions export_options(const io::OutputSpace &space) const
Definition VarForm.cpp:835
io::OutGeometryData output_geometry_
Definition VarForm.hpp:277
void save_subsolve(const int i, const int t, const Eigen::MatrixXd &solution) const
Definition VarForm.cpp:1086
io::OutputFieldFunction output_field_function(const Eigen::MatrixXd &solution, const io::OutGeometryData::ExportOptions &opts) const
Definition VarForm.cpp:844
QuadratureOrders n_boundary_samples(const int discr_order, const int discr_orderq, const int gdiscr_order) const
Definition VarForm.cpp:185
std::string resolve_output_path(const std::string &path) const
Definition VarForm.cpp:1116
void ensure_output_sampler() const
Definition VarForm.cpp:821
void save_timestep(const double time, const int t, const double t0, const double dt, const Eigen::MatrixXd &solution) const
Definition VarForm.cpp:1047
io::OutRuntimeData timings
runtime statistics
Definition VarForm.hpp:268
const io::ResourceIO & resources_
Definition VarForm.hpp:283
void set_materials(assembler::Assembler &assembler, const int size) const
Definition VarForm.cpp:806
std::vector< int > count_invalid(const int dim, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXd &u, const unsigned max_iter)
Definition Jacobian.cpp:122
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
std::function< void(int step, const Eigen::MatrixXd &solution)> ForwardStepCallback
Definition VarForm.hpp:53
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
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:13
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24
const mesh::Mesh * mesh
Temporary compatibility wrapper for boundary data belonging to one FE space.
Definition FESpace.hpp:152
std::vector< mesh::LocalBoundary > local_boundary
Definition FESpace.hpp:155
std::vector< mesh::LocalBoundary > local_neumann_boundary
Definition FESpace.hpp:156
std::vector< mesh::LocalBoundary > total_local_boundary
Definition FESpace.hpp:154
std::vector< mesh::LocalBoundary > local_pressure_boundary
Definition FESpace.hpp:157
std::unordered_map< int, std::vector< mesh::LocalBoundary > > local_pressure_cavity
Definition FESpace.hpp:158