18#include <polysolve/linear/FEMSolver.hpp>
22 using namespace varform::internal;
40 const json &discr_orders =
args.at(
"space").at(
"discr_order");
42 const json &materials =
args.at(
"materials");
43 if (materials.is_array() && materials.empty())
45 const json &first_material = materials.is_array() ? materials.at(0) : materials;
49 log_and_throw_error(
"Incompressible displacement and pressure must use different FE space IDs.");
51 if (discr_orders.is_array())
53 bool has_displacement_space =
false;
54 bool has_pressure_space =
false;
55 for (
const json &entry : discr_orders)
57 const int fe_space_id = entry.at(
"fe_space").get<
int>();
61 if (!has_displacement_space || !has_pressure_space)
62 log_and_throw_error(
"Incompressible discretization-order lists must explicitly name the displacement and pressure FE spaces.");
65 if (materials.is_array())
67 for (
const json &material : materials)
71 log_and_throw_error(
"All incompressible materials must use the same displacement and pressure FE space IDs.");
85 logger().error(
"Load the mesh first!");
88 if (solution.size() <= 0)
90 logger().error(
"Solve the problem first!");
94 logger().info(
"Saving json...");
96 const Eigen::MatrixXd stats_solution =
97 solution.rows() >= primary_size
98 ? solution.topRows(primary_size).eval()
106 args[
"output"][
"advanced"][
"sol_at_node"], j);
107 out << j.dump(4) << std::endl;
112 if (!
args[
"output"][
"advanced"][
"compute_error"])
116 if (!
args[
"time"].is_null())
117 tend =
args[
"time"][
"tend"];
119 Eigen::MatrixXd displacement, pressure;
146 json rhs_solver_params =
args[
"solver"][
"linear"];
147 if (!rhs_solver_params.contains(
"Pardiso"))
148 rhs_solver_params[
"Pardiso"] = {};
149 rhs_solver_params[
"Pardiso"][
"mtype"] = -2;
156 args[
"space"][
"advanced"][
"bc_method"],
172 const bool use_corner_quadrature =
args[
"space"][
"advanced"][
"use_corner_quadrature"];
173 const int quadrature_order =
args[
"space"][
"advanced"][
"quadrature_order"].get<
int>();
174 const int mass_quadrature_order =
args[
"space"][
"advanced"][
"mass_quadrature_order"].get<
int>();
175 Eigen::VectorXi pressure_disc_orders;
178 const std::string pressure_basis_type =
args[
"space"][
"basis_type"].get<std::string>() ==
"Bernstein" ?
"Bernstein" :
"Lagrange";
182 pressure_disc_orders,
184 args[
"space"][
"poly_basis_type"],
188 mass_quadrature_order,
189 use_corner_quadrature,
190 args[
"space"][
"advanced"][
"n_harmonic_samples"],
191 args[
"space"][
"advanced"][
"integral_constraints"],
205 for (
const auto &lb : all_boundary)
225 for (
int d = 0; d < mesh.
dimension(); ++d)
243 const int prev_size =
rhs_.rows();
250 if (!
problem->is_time_dependent())
260 logger().info(
"Assembling mass mat...");
263 for (
int k = 0; k <
mass_.outerSize(); ++k)
264 for (StiffnessMatrix::InnerIterator it(
mass_, k); it; ++it)
266 assert(it.col() == k);
270 if (
args[
"solver"][
"advanced"][
"lump_mass_matrix"])
285 sol.conservativeResize(Eigen::NoChange, 1);
292 const int cols = std::max(1,
int(stacked.cols()));
295 const int primary_rows = std::min(
primary_ndof(),
int(stacked.rows()));
296 if (primary_rows > 0)
297 primary.topRows(primary_rows) = stacked.topRows(primary_rows);
301 if (pressure_rows > 0)
302 pressure.topRows(pressure_rows) = stacked.middleRows(
primary_ndof(), pressure_rows);
310 logger().info(
"Assembling stiffness mat...");
312 StiffnessMatrix elastic_stiffness, mixed_stiffness, pressure_stiffness;
319 elastic_stiffness, mixed_stiffness, pressure_stiffness, stiffness);
326 stats.
mat_size = (
long long)stiffness.rows() * (
long long)stiffness.cols();
331 const std::unique_ptr<polysolve::linear::Solver> &solver,
334 const bool compute_spectrum,
335 Eigen::MatrixXd &sol)
345 args[
"output"][
"data"][
"stiffness_mat"],
355 auto solver = polysolve::linear::Solver::create(
args[
"solver"][
"linear"],
logger());
356 logger().info(
"{}...", solver->name());
360 Eigen::VectorXd b =
rhs_;
366 auto solver = polysolve::linear::Solver::create(
args[
"solver"][
"linear"],
logger());
367 logger().info(
"{}...", solver->name());
369 Eigen::MatrixXd displacement, pressure;
372 args[
"time"][
"integrator"]);
375 Eigen::MatrixXd::Zero(displacement.rows(), displacement.cols()),
376 Eigen::MatrixXd::Zero(displacement.rows(), displacement.cols()),
382 Eigen::MatrixXd current_rhs =
rhs_;
389 const double time =
t0 + t *
dt;
398 const int old_rows = current_rhs.rows();
399 current_rhs.conservativeResize(
stacked_ndof(), current_rhs.cols());
401 current_rhs.bottomRows(
stacked_ndof() - old_rows).setZero();
406 Eigen::VectorXd b = Eigen::VectorXd::Zero(
stacked_ndof());
414 bdf->update_quantities(displacement.col(0));
430 if (
problem->is_time_dependent())
444 const Eigen::MatrixXd &solution,
447 Eigen::MatrixXd displacement, pressure;
449 const std::vector<std::pair<std::string, std::shared_ptr<solver::Form>>> named_forms;
451 sample, displacement, options,
nullptr,
time_integrator.get(), named_forms,
nullptr);
452 const bool export_pressure_gradient =
456 Eigen::MatrixXd values, gradients;
459 export_pressure_gradient ? &gradients :
nullptr))
463 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