18#include <polysolve/linear/FEMSolver.hpp>
22 using namespace varform::internal;
26 const Eigen::MatrixXd &solution,
36 Eigen::MatrixXd &solution)
42 mesh_->dimension(), 0, solution);
63 for (
const std::string field : {
"pressure_boundary",
"pressure_cavity"})
65 const json::json_pointer path(
"/boundary_conditions/" + field);
66 if (
args.contains(path) && !
args.at(path).empty())
71 const json &discr_orders =
args.at(
"space").at(
"discr_order");
73 const json &materials =
args.at(
"materials");
74 if (materials.is_array() && materials.empty())
76 const json &first_material = materials.is_array() ? materials.at(0) : materials;
80 log_and_throw_error(
"Incompressible displacement and pressure must use different FE space IDs.");
82 if (discr_orders.is_array())
84 bool has_displacement_space =
false;
85 bool has_pressure_space =
false;
86 for (
const json &entry : discr_orders)
88 const int fe_space_id = entry.at(
"fe_space").get<
int>();
92 if (!has_displacement_space || !has_pressure_space)
93 log_and_throw_error(
"Incompressible discretization-order lists must explicitly name the displacement and pressure FE spaces.");
96 if (materials.is_array())
98 for (
const json &material : materials)
102 log_and_throw_error(
"All incompressible materials must use the same displacement and pressure FE space IDs.");
116 logger().error(
"Load the mesh first!");
119 if (solution.size() <= 0)
121 logger().error(
"Solve the problem first!");
125 logger().info(
"Saving json...");
127 const Eigen::MatrixXd stats_solution =
128 solution.rows() >= primary_size
129 ? solution.topRows(primary_size).eval()
137 args[
"output"][
"advanced"][
"sol_at_node"], j);
138 out << j.dump(4) << std::endl;
143 if (!
args[
"output"][
"advanced"][
"compute_error"])
147 if (!
args[
"time"].is_null())
148 tend =
args[
"time"][
"tend"];
150 Eigen::MatrixXd displacement, pressure;
177 json rhs_solver_params =
args[
"solver"][
"linear"];
178 if (!rhs_solver_params.contains(
"Pardiso"))
179 rhs_solver_params[
"Pardiso"] = {};
180 rhs_solver_params[
"Pardiso"][
"mtype"] = -2;
187 args[
"space"][
"advanced"][
"bc_method"],
202 const bool use_corner_quadrature =
args[
"space"][
"advanced"][
"use_corner_quadrature"];
203 const int quadrature_order =
args[
"space"][
"advanced"][
"quadrature_order"].get<
int>();
204 const int mass_quadrature_order =
args[
"space"][
"advanced"][
"mass_quadrature_order"].get<
int>();
205 Eigen::VectorXi pressure_disc_orders, pressure_disc_ordersq;
208 const std::string pressure_basis_type =
args[
"space"][
"basis_type"].get<std::string>() ==
"Bernstein" ?
"Bernstein" :
"Lagrange";
212 pressure_disc_orders,
213 pressure_disc_ordersq,
215 args[
"space"][
"poly_basis_type"],
219 mass_quadrature_order,
220 use_corner_quadrature,
221 args[
"space"][
"advanced"][
"n_harmonic_samples"],
222 args[
"space"][
"advanced"][
"integral_constraints"],
236 for (
int d = 0; d < mesh.
dimension(); ++d)
254 const int prev_size =
rhs_.rows();
261 if (!
problem->is_time_dependent())
271 logger().info(
"Assembling mass mat...");
274 for (
int k = 0; k <
mass_.outerSize(); ++k)
275 for (StiffnessMatrix::InnerIterator it(
mass_, k); it; ++it)
277 assert(it.col() == k);
281 if (
args[
"solver"][
"advanced"][
"lump_mass_matrix"])
296 sol.conservativeResize(Eigen::NoChange, 1);
303 const int cols = std::max(1,
int(stacked.cols()));
306 const int primary_rows = std::min(
primary_ndof(),
int(stacked.rows()));
307 if (primary_rows > 0)
308 primary.topRows(primary_rows) = stacked.topRows(primary_rows);
312 if (pressure_rows > 0)
313 pressure.topRows(pressure_rows) = stacked.middleRows(
primary_ndof(), pressure_rows);
321 logger().info(
"Assembling stiffness mat...");
323 StiffnessMatrix elastic_stiffness, mixed_stiffness, pressure_stiffness;
330 elastic_stiffness, mixed_stiffness, pressure_stiffness, stiffness);
337 stats.
mat_size = (
long long)stiffness.rows() * (
long long)stiffness.cols();
342 const std::unique_ptr<polysolve::linear::Solver> &solver,
345 const bool compute_spectrum,
346 Eigen::MatrixXd &sol)
356 args[
"output"][
"data"][
"stiffness_mat"],
366 auto solver = polysolve::linear::Solver::create(
args[
"solver"][
"linear"],
logger());
367 logger().info(
"{}...", solver->name());
371 Eigen::VectorXd b =
rhs_;
377 auto solver = polysolve::linear::Solver::create(
args[
"solver"][
"linear"],
logger());
378 logger().info(
"{}...", solver->name());
380 Eigen::MatrixXd displacement, pressure;
383 args[
"time"][
"integrator"]);
386 Eigen::MatrixXd::Zero(displacement.rows(), displacement.cols()),
387 Eigen::MatrixXd::Zero(displacement.rows(), displacement.cols()),
396 Eigen::MatrixXd current_rhs =
rhs_;
403 const double time =
t0 + t *
dt;
412 const int old_rows = current_rhs.rows();
413 current_rhs.conservativeResize(
stacked_ndof(), current_rhs.cols());
415 current_rhs.bottomRows(
stacked_ndof() - old_rows).setZero();
420 Eigen::VectorXd b = Eigen::VectorXd::Zero(
stacked_ndof());
428 bdf->update_quantities(displacement.col(0));
438 Eigen::MatrixXd &sol,
442 assert(!initial_condition_override &&
"Incompressible elasticity does not support initial-condition overrides");
443 assert(!post_step &&
"Incompressible elasticity does not support post-step callbacks");
450 if (
problem->is_time_dependent())
464 const Eigen::MatrixXd &solution,
467 Eigen::MatrixXd displacement, pressure;
469 const std::vector<std::pair<std::string, std::shared_ptr<solver::Form>>> named_forms;
471 sample, displacement, options,
nullptr,
time_integrator.get(), named_forms,
nullptr);
472 const bool export_pressure_gradient =
476 Eigen::MatrixXd values, gradients;
479 export_pressure_gradient ? &gradients :
nullptr))
483 if (export_pressure_gradient)
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
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
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
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
virtual bool is_volume() const =0
checks if mesh is volume
int dimension() const
utily for dimension
static std::shared_ptr< BDF > construct_bdf_integrator(const json ¶ms, DynamicOrder dynamic_order=DynamicOrder::Second)
Construct a BDF integrator for algorithms using BDF-specific operations.
Eigen::SparseMatrix< double > lump_matrix(const Eigen::SparseMatrix< double > &M)
Lump each row of a matrix into the diagonal.
spdlog::logger & logger()
Retrieves the current logger.
void log_and_throw_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
bool export_field(const std::string &field) const
std::vector< std::string > fields