PolyFEM
Loading...
Searching...
No Matches
IncompressibleElasticVarForm.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <numeric>
5#include <algorithm>
6
17
18#include <polysolve/linear/FEMSolver.hpp>
19
20namespace polyfem::varform
21{
22 using namespace varform::internal;
23
26 const Eigen::MatrixXd &solution,
27 const io::CheckpointMetadata &metadata) const
28 {
29 VarForm::serialize_checkpoint(writer, solution, metadata);
30 write_checkpoint_ordering(writer, "primary", space_);
31 write_checkpoint_ordering(writer, "pressure", pressure_space_);
32 }
33
35 const io::CheckpointReader &reader,
36 Eigen::MatrixXd &solution)
37 {
38 VarForm::deserialize_checkpoint(reader, solution);
41 reader, "primary", space_,
42 mesh_->dimension(), 0, solution);
44 reader, "pressure", pressure_space_,
45 1, primary_ndof(), solution);
46 }
47
60
61 void IncompressibleElasticVarForm::init(const std::string &formulation, const Units &units, const json &args, const std::string &out_path)
62 {
63 ElasticVarForm::init(formulation, units, args, out_path);
64 const json &discr_orders = args.at("space").at("discr_order");
65
66 const json &materials = args.at("materials");
67 if (materials.is_array() && materials.empty())
68 log_and_throw_error("Incompressible elasticity requires at least one material.");
69 const json &first_material = materials.is_array() ? materials.at(0) : materials;
70 displacement_space_id_ = first_material.at("displacement_space_id").get<int>();
71 pressure_space_id_ = first_material.at("pressure_space_id").get<int>();
73 log_and_throw_error("Incompressible displacement and pressure must use different FE space IDs.");
74
75 if (discr_orders.is_array())
76 {
77 bool has_displacement_space = false;
78 bool has_pressure_space = false;
79 for (const json &entry : discr_orders)
80 {
81 const int fe_space_id = entry.at("fe_space").get<int>();
82 has_displacement_space |= fe_space_id == displacement_space_id_;
83 has_pressure_space |= fe_space_id == pressure_space_id_;
84 }
85 if (!has_displacement_space || !has_pressure_space)
86 log_and_throw_error("Incompressible discretization-order lists must explicitly name the displacement and pressure FE spaces.");
87 }
88
89 if (materials.is_array())
90 {
91 for (const json &material : materials)
92 {
93 if (material.at("displacement_space_id").get<int>() != displacement_space_id_
94 || material.at("pressure_space_id").get<int>() != pressure_space_id_)
95 log_and_throw_error("All incompressible materials must use the same displacement and pressure FE space IDs.");
96 }
97 }
98
101 assert(primary_assembler_->is_linear());
102 assert(primary_assembler_->is_tensor());
103 }
104
105 void IncompressibleElasticVarForm::save_json(const Eigen::MatrixXd &solution, std::ostream &out) const
106 {
107 if (!mesh_)
108 {
109 logger().error("Load the mesh first!");
110 return;
111 }
112 if (solution.size() <= 0)
113 {
114 logger().error("Solve the problem first!");
115 return;
116 }
117
118 logger().info("Saving json...");
119 const int primary_size = primary_ndof();
120 const Eigen::MatrixXd stats_solution =
121 solution.rows() >= primary_size
122 ? solution.topRows(primary_size).eval()
123 : solution;
124
125 nlohmann::json j;
128 stats_solution, *mesh_, space_.disc_orders, space_.disc_ordersq, *problem,
130 args["output"]["advanced"]["sol_at_node"], j);
131 out << j.dump(4) << std::endl;
132 }
133
135 {
136 if (!args["output"]["advanced"]["compute_error"])
137 return stats;
138
139 double tend = 0;
140 if (!args["time"].is_null())
141 tend = args["time"]["tend"];
142
143 Eigen::MatrixXd displacement, pressure;
144 split_solution(solution, displacement, pressure);
146 return stats;
147 }
148
157
159 {
160 return mesh_ ? space_.n_bases * mesh_->dimension() : 0;
161 }
162
167
169 {
170 json rhs_solver_params = args["solver"]["linear"];
171 if (!rhs_solver_params.contains("Pardiso"))
172 rhs_solver_params["Pardiso"] = {};
173 rhs_solver_params["Pardiso"]["mtype"] = -2;
174
175 rhs_assembler_ = std::make_shared<assembler::RhsAssembler>(
176 *primary_assembler_, *mesh_, nullptr,
180 args["space"]["advanced"]["bc_method"],
181 rhs_solver_params,
183 }
184
185 void IncompressibleElasticVarForm::build_basis(mesh::Mesh &mesh, const bool iso_parametric, const json &args)
186 {
187 build_elastic_basis(mesh, iso_parametric, args, displacement_space_id_);
188
189 if (space_.disc_orders.maxCoeff() != space_.disc_orders.minCoeff())
190 log_and_throw_error("p refinement not supported in mixed formulation!");
191 if (!space_.poly_edge_to_data.empty())
192 log_and_throw_error("Polygonal bases are not supported in mixed formulations!");
193
194 const auto &all_boundary = boundary_.total_local_boundary;
195 const int prev_bases = space_.n_bases;
196 const bool use_corner_quadrature = args["space"]["advanced"]["use_corner_quadrature"];
197 const int quadrature_order = args["space"]["advanced"]["quadrature_order"].get<int>();
198 const int mass_quadrature_order = args["space"]["advanced"]["mass_quadrature_order"].get<int>();
199 Eigen::VectorXi pressure_disc_orders, pressure_disc_ordersq;
200 assign_discr_orders(args["space"], pressure_space_id_, mesh, pressure_disc_orders, pressure_disc_ordersq);
201 // to avoid serendipity
202 const std::string pressure_basis_type = args["space"]["basis_type"].get<std::string>() == "Bernstein" ? "Bernstein" : "Lagrange";
204 mesh,
205 /*iso_parametric=*/true,
206 pressure_disc_orders,
207 pressure_disc_ordersq,
208 pressure_basis_type,
209 args["space"]["poly_basis_type"],
211 /*value_dim=*/1,
212 quadrature_order,
213 mass_quadrature_order,
214 use_corner_quadrature,
215 args["space"]["advanced"]["n_harmonic_samples"],
216 args["space"]["advanced"]["integral_constraints"],
220
221 assert(space_.basis_list().size() == pressure_space_.basis_list().size());
222 for (int i = 0; i < int(pressure_space_.basis_list().size()); ++i)
223 {
225 space_.basis_list()[i].compute_quadrature(b_quad);
226 (*pressure_space_.bases)[i].set_quadrature([b_quad](quadrature::Quadrature &quad) { quad = b_quad; });
227 }
228
230 for (const auto &lb : all_boundary)
231 boundary_.local_boundary.emplace_back(lb);
233
234 problem->setup_bc(
235 mesh, space_.n_bases,
245
248
249 for (int i = prev_bases; i < space_.n_bases; ++i)
250 for (int d = 0; d < mesh.dimension(); ++d)
251 boundary_.boundary_nodes.push_back(i * mesh.dimension() + d);
252
254
255 if (space_.n_bases <= args["solver"]["advanced"]["cache_size"])
257 else
259
261
262 logger().info("n pressure bases: {}", pressure_space_.n_bases);
263 }
264
266 {
268 const int prev_size = rhs_.rows();
269 rhs_.conservativeResize(prev_size + pressure_space_.n_bases, rhs_.cols());
270 rhs_.bottomRows(pressure_space_.n_bases).setZero();
271 }
272
274 {
275 if (!problem->is_time_dependent())
276 {
277 avg_mass_ = 1;
279 return;
280 }
281
282 mass_.resize(0, 0);
283 igl::Timer timer;
284 timer.start();
285 logger().info("Assembling mass mat...");
287 avg_mass_ = 0;
288 for (int k = 0; k < mass_.outerSize(); ++k)
289 for (StiffnessMatrix::InnerIterator it(mass_, k); it; ++it)
290 {
291 assert(it.col() == k);
292 avg_mass_ += it.value();
293 }
294 avg_mass_ /= std::max(1, int(mass_.rows()));
295 if (args["solver"]["advanced"]["lump_mass_matrix"])
297 timer.stop();
298 timings.assembling_mass_mat_time = timer.getElapsedTime();
299 logger().info(" took {}s", timings.assembling_mass_mat_time);
300 stats.nn_zero = mass_.nonZeros();
301 stats.num_dofs = mass_.rows();
302 stats.mat_size = (long long)mass_.rows() * (long long)mass_.cols();
303 }
304
306 {
307 if (sol.size() <= 0)
308 initial_solution(sol);
309 if (sol.cols() > 1)
310 sol.conservativeResize(Eigen::NoChange, 1);
311 sol.conservativeResize(stacked_ndof(), sol.cols());
312 sol.bottomRows(pressure_space_.n_bases).setZero();
313 }
314
315 void IncompressibleElasticVarForm::split_solution(const Eigen::MatrixXd &stacked, Eigen::MatrixXd &primary, Eigen::MatrixXd &pressure) const
316 {
317 const int cols = std::max(1, int(stacked.cols()));
318 primary.setZero(primary_ndof(), cols);
319 pressure.setZero(pressure_space_.n_bases, cols);
320 const int primary_rows = std::min(primary_ndof(), int(stacked.rows()));
321 if (primary_rows > 0)
322 primary.topRows(primary_rows) = stacked.topRows(primary_rows);
323 if (stacked.rows() > primary_ndof())
324 {
325 const int pressure_rows = std::min(pressure_space_.n_bases, int(stacked.rows()) - primary_ndof());
326 if (pressure_rows > 0)
327 pressure.topRows(pressure_rows) = stacked.middleRows(primary_ndof(), pressure_rows);
328 }
329 }
330
332 {
333 igl::Timer timer;
334 timer.start();
335 logger().info("Assembling stiffness mat...");
336
337 StiffnessMatrix elastic_stiffness, mixed_stiffness, pressure_stiffness;
338 primary_assembler_->assemble(mesh_->is_volume(), space_.n_bases, space_.basis_list(), space_.geometry_basis_list(), ass_vals_cache_, 0, elastic_stiffness);
341
343 space_.n_bases, pressure_space_.n_bases, mesh_->dimension(), /*add_average=*/false,
344 elastic_stiffness, mixed_stiffness, pressure_stiffness, stiffness);
345
346 timer.stop();
347 timings.assembling_stiffness_mat_time = timer.getElapsedTime();
348 logger().info(" took {}s", timings.assembling_stiffness_mat_time);
349 stats.nn_zero = stiffness.nonZeros();
350 stats.num_dofs = stiffness.rows();
351 stats.mat_size = (long long)stiffness.rows() * (long long)stiffness.cols();
352 write_matrix_market(args, stiffness);
353 }
354
356 const std::unique_ptr<polysolve::linear::Solver> &solver,
358 Eigen::VectorXd &b,
359 const bool compute_spectrum,
360 Eigen::MatrixXd &sol)
361 {
362 Eigen::VectorXd x;
363 stats.spectrum = dirichlet_solve(
364 *solver,
365 A,
366 b,
368 x,
369 primary_ndof(),
370 args["output"]["data"]["stiffness_mat"],
371 compute_spectrum,
372 /*is_fluid=*/false,
373 /*use_avg_pressure=*/false);
374 sol = x;
375 solver->get_info(stats.solver_info);
376 }
377
379 {
380 auto solver = polysolve::linear::Solver::create(args["solver"]["linear"], logger());
381 logger().info("{}...", solver->name());
385 Eigen::VectorXd b = rhs_;
386 solve_linear_system(solver, A, b, args["output"]["advanced"]["spectrum"], sol);
387 }
388
390 {
391 auto solver = polysolve::linear::Solver::create(args["solver"]["linear"], logger());
392 logger().info("{}...", solver->name());
393
394 Eigen::MatrixXd displacement, pressure;
395 split_solution(sol, displacement, pressure);
397 args["time"]["integrator"]);
398 bdf->init(
399 displacement,
400 Eigen::MatrixXd::Zero(displacement.rows(), displacement.cols()),
401 Eigen::MatrixXd::Zero(displacement.rows(), displacement.cols()),
402 dt);
403 time_integrator = bdf;
405 time_integrator, "/checkpoint/state/primary_integrator", dt,
406 "primary", space_, mesh_->dimension());
407
408 save_timestep(t0, 0, t0, dt, sol);
409
410 Eigen::MatrixXd current_rhs = rhs_;
411 StiffnessMatrix stiffness, expanded_mass;
412 build_stiffness_mat(stiffness);
413 expand_primary_matrix(stacked_ndof(), mass_, expanded_mass);
414
415 for (int t = 1; t <= time_steps; ++t)
416 {
417 const double time = t0 + t * dt;
418 rhs_assembler_->compute_energy_grad(
420 current_rhs);
421 rhs_assembler_->set_bc(
423
424 if (current_rhs.rows() != stacked_ndof())
425 {
426 const int old_rows = current_rhs.rows();
427 current_rhs.conservativeResize(stacked_ndof(), current_rhs.cols());
428 if (stacked_ndof() > old_rows)
429 current_rhs.bottomRows(stacked_ndof() - old_rows).setZero();
430 }
431 current_rhs.bottomRows(pressure_space_.n_bases).setZero();
432
433 StiffnessMatrix A = expanded_mass / bdf->beta_dt() + stiffness;
434 Eigen::VectorXd b = Eigen::VectorXd::Zero(stacked_ndof());
435 b.head(primary_ndof()) = (mass_ * bdf->weighted_sum_x_prevs()) / bdf->beta_dt();
436 for (int i : boundary_.boundary_nodes)
437 b[i] = 0;
438 b += current_rhs;
439
440 solve_linear_system(solver, A, b, args["output"]["advanced"]["spectrum"].get<bool>() && t == time_steps, sol);
441 split_solution(sol, displacement, pressure);
442 bdf->update_quantities(displacement.col(0));
443
444 save_timestep(time, t, t0, dt, sol);
446 logger().info("{}/{} t={}", t, time_steps, time);
448 }
449 }
450
452 Eigen::MatrixXd &sol,
453 const InitialConditionOverride *initial_condition_override,
454 const ForwardStepCallback &post_step)
455 {
456 assert(!initial_condition_override && "Incompressible elasticity does not support initial-condition overrides");
457 assert(!post_step && "Incompressible elasticity does not support post-step callbacks");
458
459 stats.spectrum.setZero();
460 igl::Timer timer;
461 timer.start();
462 logger().info("Solving {}", primary_assembler_->name());
464 if (problem->is_time_dependent())
466 else
467 {
468 time_integrator = nullptr;
470 }
471 timer.stop();
472 timings.solving_time = timer.getElapsedTime();
473 logger().info(" took {}s", timings.solving_time);
474 }
475
477 const io::OutputSample &sample,
478 const Eigen::MatrixXd &solution,
479 const io::OutputFieldOptions &options) const
480 {
481 Eigen::MatrixXd displacement, pressure;
482 split_solution(solution, displacement, pressure);
483 const std::vector<std::pair<std::string, std::shared_ptr<solver::Form>>> named_forms;
484 auto fields = elastic_output_fields(
485 sample, displacement, options, nullptr, time_integrator.get(), named_forms, nullptr);
486 const bool export_pressure_gradient =
487 !options.fields.empty() && options.export_field("pressure_gradient");
488 if (mesh_ && (options.export_field("pressure") || export_pressure_gradient))
489 {
490 Eigen::MatrixXd values, gradients;
492 *mesh_, pressure_space_.basis_list(), space_.geometry_basis_list(), sample, pressure, values,
493 export_pressure_gradient ? &gradients : nullptr))
494 {
495 if (options.export_field("pressure"))
496 fields.push_back({"pressure", values, io::OutputField::Association::Point});
497 if (export_pressure_gradient)
498 fields.push_back({"pressure_gradient", gradients, io::OutputField::Association::Point});
499 }
500 }
501 return fields;
502 }
503} // namespace polyfem::varform
int x
static std::shared_ptr< MixedAssembler > make_mixed_assembler(const std::string &formulation)
static std::string other_assembler_name(const std::string &formulation)
static void merge_mixed_matrices(const int n_bases, const int n_pressure_bases, const int problem_dim, const bool add_average, const StiffnessMatrix &velocity_stiffness, const StiffnessMatrix &mixed_stiffness, const StiffnessMatrix &pressure_stiffness, StiffnessMatrix &stiffness)
utility to merge 3 blocks of mixed matrices, A=velocity_stiffness, B=mixed_stiffness,...
static std::shared_ptr< Assembler > make_assembler(const std::string &formulation)
void init(const bool is_volume, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const bool is_mass=false)
computes the basis evaluation and geometric mapping for each of the given ElementBases in bases initi...
void init_empty(const bool is_mass=false)
initialize an empty cache.
double assembling_stiffness_mat_time
time to assembly
double assembling_mass_mat_time
time to assembly mass
double solving_time
time to solve
all stats from polyfem
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)
void compute_errors(const int n_bases, const std::vector< polyfem::basis::ElementBases > &bases, const std::vector< polyfem::basis::ElementBases > &gbases, const polyfem::mesh::Mesh &mesh, const assembler::Problem &problem, const double tend, const Eigen::MatrixXd &sol)
compute errors
Definition OutData.cpp:2860
long long nn_zero
non zeros and sytem matrix size num dof is the total dof in the system
void save_json(const nlohmann::json &args, const int n_bases, const int n_pressure_bases, const Eigen::MatrixXd &sol, const mesh::Mesh &mesh, const Eigen::VectorXi &disc_orders, const Eigen::VectorXi &disc_ordersq, const assembler::Problem &problem, const OutRuntimeData &runtime, const std::string &formulation, const bool isoparametric, const int sol_at_node_id, nlohmann::json &j) const
saves the output statistic to a json object
Definition OutData.cpp:3103
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
virtual bool is_volume() const =0
checks if mesh is volume
int dimension() const
utily for dimension
Definition Mesh.hpp:138
static std::shared_ptr< BDF > construct_bdf_integrator(const json &params, DynamicOrder dynamic_order=DynamicOrder::Second)
Construct a BDF integrator for algorithms using BDF-specific operations.
void build_elastic_basis(mesh::Mesh &mesh, const bool iso_parametric, const json &args, const int fe_space_id)
std::shared_ptr< assembler::Assembler > primary_assembler_
void init(const std::string &formulation, const Units &units, const json &args, const std::string &out_path) override
Initialize the variational formulation with the given parameters.
QuadratureOrders elastic_boundary_samples() const
assembler::AssemblyValsCache ass_vals_cache_
std::vector< io::OutputField > elastic_output_fields(const io::OutputSample &sample, const Eigen::MatrixXd &solution, const io::OutputFieldOptions &options, const mesh::Obstacle *obstacle, const time_integrator::ImplicitTimeIntegrator *time_integrator, const std::vector< std::pair< std::string, std::shared_ptr< solver::Form > > > &named_forms, const solver::Form *elastic_form, const solver::ContactForm *contact_form=nullptr) const
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 load_mesh(const mesh::Mesh &mesh, const json &args) override
void initial_solution(Eigen::MatrixXd &solution, const InitialConditionOverride *override=nullptr, const std::string &state_prefix="") const
void assemble_rhs(const mesh::Mesh &mesh) override
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
std::shared_ptr< GeometryMapping > geometry
Geometric mapping used to integrate this FE space.
Definition FESpace.hpp:89
Eigen::VectorXi disc_orders
Primary polynomial degree for each mesh element.
Definition FESpace.hpp:71
Eigen::VectorXi disc_ordersq
Secondary polynomial degree for anisotropic bases, e.g. prisms.
Definition FESpace.hpp:74
int n_bases
Number of globally indexed scalar basis functions in the space.
Definition FESpace.hpp:65
std::map< int, basis::InterfaceData > poly_edge_to_data
Polygonal-basis construction data, indexed by element ID.
Definition FESpace.hpp:77
const std::vector< basis::ElementBases > & basis_list() const
Definition FESpace.hpp:109
bool is_iso_parametric() const
Definition FESpace.hpp:104
std::vector< io::OutputField > output_fields(const io::OutputSample &sample, const Eigen::MatrixXd &solution, const io::OutputFieldOptions &options) const override
Get the output fields of the variational formulation, for output purposes.
void serialize_checkpoint(io::CheckpointWriter &writer, const Eigen::MatrixXd &solution, const io::CheckpointMetadata &metadata) const override
void assemble_mass_mat(const mesh::Mesh &mesh, const json &args) override
void deserialize_checkpoint(const io::CheckpointReader &reader, Eigen::MatrixXd &solution) override
std::shared_ptr< time_integrator::ImplicitTimeIntegrator > time_integrator
void solve_problem(Eigen::MatrixXd &sol, const InitialConditionOverride *initial_condition_override, const ForwardStepCallback &post_step) override
void save_json(const Eigen::MatrixXd &solution, std::ostream &out) const override
Save the solution to a JSON file, for output purposes.
void solve_linear_system(const std::unique_ptr< polysolve::linear::Solver > &solver, StiffnessMatrix &A, Eigen::VectorXd &b, const bool compute_spectrum, Eigen::MatrixXd &sol)
std::string name() const override
Get the name of the variational formulation.
std::shared_ptr< assembler::MixedAssembler > mixed_assembler_
void load_mesh(const mesh::Mesh &mesh, const json &args) override
void split_solution(const Eigen::MatrixXd &stacked, Eigen::MatrixXd &primary, Eigen::MatrixXd &pressure) const
void build_basis(mesh::Mesh &mesh, const bool iso_parametric, const json &args) override
std::shared_ptr< assembler::Assembler > pressure_assembler_
io::OutStatsData compute_errors(const Eigen::MatrixXd &solution) override
Get the error statistics of the variational formulation, for output purposes.
void init(const std::string &formulation, const Units &units, const json &args, const std::string &out_path) override
Initialize the variational formulation with the given parameters.
void reorder_checkpoint_block(const io::CheckpointReader &reader, const std::string &name, const FESpace &space, int block_size, int row_offset, Eigen::MatrixXd &value) const
Definition VarForm.cpp:981
static void rebuild_node_positions(const std::vector< basis::ElementBases > &bases, const std::vector< int > &node_ids, std::vector< RowVectorNd > &positions)
Definition VarForm.cpp:1125
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
Definition VarForm.hpp:261
void write_checkpoint_ordering(io::CheckpointWriter &writer, const std::string &name, const FESpace &space) const
Definition VarForm.cpp:938
virtual void deserialize_checkpoint(const io::CheckpointReader &reader, Eigen::MatrixXd &solution)
Definition VarForm.cpp:905
std::unique_ptr< mesh::Mesh > mesh_
Definition VarForm.hpp:273
void assign_discr_orders(const json &space_args, const mesh::Mesh &mesh, Eigen::VectorXi &disc_orders, Eigen::VectorXi &disc_ordersq)
Definition VarForm.cpp:684
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
void restore_checkpoint_integrator(const std::shared_ptr< time_integrator::ImplicitTimeIntegrator > &integrator, const std::string &group, double dt, const std::string &ordering, const FESpace &space, int block_size) const
Definition VarForm.cpp:917
virtual void serialize_checkpoint(io::CheckpointWriter &writer, const Eigen::MatrixXd &solution, const io::CheckpointMetadata &metadata) const
Definition VarForm.cpp:897
void build_fe_space(mesh::Mesh &mesh, const bool iso_parametric, const Eigen::VectorXi &disc_orders, const Eigen::VectorXi &disc_ordersq, const std::string &basis_type, const std::string &poly_basis_type, const assembler::Assembler &space_assembler, const int value_dim, const int quadrature_order, const int mass_quadrature_order, const bool use_corner_quadrature, const int n_harmonic_samples, const int integral_constraints, FESpace &space, VarFormBoundaryState &boundary, std::shared_ptr< GeometryMapping > geometry=nullptr)
Definition VarForm.cpp:274
void save_timestep(const double time, const int t, const double t0, const double dt, const Eigen::MatrixXd &solution) const
Definition VarForm.cpp:1047
void validate_checkpoint_solution(const Eigen::MatrixXd &solution, int expected_rows) const
Definition VarForm.cpp:1037
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
Eigen::SparseMatrix< double > lump_matrix(const Eigen::SparseMatrix< double > &M)
Lump each row of a matrix into the diagonal.
bool write_matrix_market(const json &args, const StiffnessMatrix &stiffness)
bool sample_scalar_field(const mesh::Mesh &mesh, const std::vector< basis::ElementBases > &field_bases, const std::vector< basis::ElementBases > &gbases, const io::OutputSample &sample, const Eigen::MatrixXd &dof_values, Eigen::MatrixXd &values, Eigen::MatrixXd *gradients=nullptr)
void expand_primary_matrix(const int full_size, const StiffnessMatrix &primary, StiffnessMatrix &expanded)
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
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24
bool export_field(const std::string &field) const
Definition OutData.cpp:56
std::vector< std::string > fields
std::vector< RowVectorNd > neumann_nodes_position
Definition FESpace.hpp:163
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< RowVectorNd > dirichlet_nodes_position
Definition FESpace.hpp:161
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