23#include <polysolve/linear/FEMSolver.hpp>
27 using namespace varform::internal;
60 const bool is_time_dependent =
args.contains(
"time") && !
args[
"time"].is_null();
68 if (!
args.contains(
"preset_problem"))
70 problem = std::make_shared<assembler::GenericTensorProblem>(
"GenericTensor");
74 tmp[
"is_time_dependent"] = is_time_dependent;
77 auto bc =
args[
"boundary_conditions"];
85 if (
args[
"preset_problem"][
"type"] ==
"Kernel")
100 t0 = is_time_dependent ?
args[
"time"][
"t0"].get<
double>() : 0.0;
101 time_steps = is_time_dependent ?
args[
"time"][
"time_steps"].get<
int>() : 0;
102 dt = is_time_dependent ?
args[
"time"][
"dt"].get<
double>() : 0.0;
111 logger().error(
"Load the mesh first!");
114 if (solution.size() <= 0)
116 logger().error(
"Solve the problem first!");
120 logger().info(
"Saving json...");
122 const Eigen::MatrixXd stats_solution =
123 solution.rows() >= primary_size
124 ? solution.topRows(primary_size).eval()
132 args[
"output"][
"advanced"][
"sol_at_node"], j);
133 out << j.dump(4) << std::endl;
141 for (
int e = 0; e < output_orders.size(); ++e)
143 if (
mesh_->is_prism(e))
163 if (!
args[
"output"][
"advanced"][
"compute_error"])
167 if (!
args[
"time"].is_null())
168 tend =
args[
"time"][
"tend"];
170 Eigen::MatrixXd velocity, pressure;
181 logger().error(
"Load the mesh first!");
184 if (solution.size() <= 0)
186 logger().error(
"Solve the problem first!");
193 const bool has_time =
args.contains(
"time") && !
args[
"time"].is_null();
194 double tend = has_time ?
args[
"time"][
"tend"].get<
double>() : 1.0;
208 Eigen::MatrixXd velocity, pressure;
212 if (!solution_path.empty())
214 const int primary_rows = std::min<int>(velocity.rows(),
primary_ndof());
215 const Eigen::MatrixXd primary_solution = velocity.topRows(primary_rows);
219 Eigen::MatrixXd reordered = Eigen::MatrixXd::Zero(nodal_solution.rows(), nodal_solution.cols());
223 if (node >= 0 && node < nodal_solution.rows() && input_node < reordered.rows())
224 reordered.row(input_node) = nodal_solution.row(node);
235 if (!nodes_path.empty())
240 for (
const auto &global : basis.global())
241 nodes.row(global.index) = global.node;
249 Eigen::MatrixXd stress;
250 Eigen::VectorXd mises;
255 if (!stress_path.empty())
257 if (!mises_path.empty())
292 json rhs_solver_params =
args[
"solver"][
"linear"];
293 if (!rhs_solver_params.contains(
"Pardiso"))
294 rhs_solver_params[
"Pardiso"] = {};
295 rhs_solver_params[
"Pardiso"][
"mtype"] = -2;
302 args[
"space"][
"advanced"][
"bc_method"],
313 Eigen::VectorXi space_disc_orders;
316 if (
args[
"space"][
"use_p_ref"])
320 args[
"space"][
"advanced"][
"B"],
321 args[
"space"][
"advanced"][
"h1_formula"],
322 args[
"space"][
"discr_order"],
323 args[
"space"][
"advanced"][
"discr_order_max"],
327 logger().info(
"min p: {} max p: {}", space_disc_orders.minCoeff(), space_disc_orders.maxCoeff());
334 args[
"space"][
"basis_type"],
335 args[
"space"][
"poly_basis_type"],
338 args[
"space"][
"advanced"][
"quadrature_order"],
339 args[
"space"][
"advanced"][
"mass_quadrature_order"],
340 args[
"space"][
"advanced"][
"use_corner_quadrature"],
341 args[
"space"][
"advanced"][
"n_harmonic_samples"],
342 args[
"space"][
"advanced"][
"integral_constraints"],
350 if (
args[
"space"][
"advanced"][
"count_flipped_els"])
353 const int n_samples = 10;
366 igl::Timer cache_timer;
368 logger().info(
"Building cache...");
372 logger().info(
" took {}s", cache_timer.getElapsedTime());
383 const int prev_b_size = int(all_boundary.size());
384 const bool use_corner_quadrature =
args[
"space"][
"advanced"][
"use_corner_quadrature"];
385 const int quadrature_order =
args[
"space"][
"advanced"][
"quadrature_order"].get<
int>();
386 const int mass_quadrature_order =
args[
"space"][
"advanced"][
"mass_quadrature_order"].get<
int>();
387 const int order =
args[
"space"][
"pressure_discr_order"];
388 Eigen::VectorXi pressure_disc_orders(mesh.
n_elements());
389 pressure_disc_orders.setConstant(order);
391 const std::string pressure_basis_type =
args[
"space"][
"basis_type"].get<std::string>() ==
"Bernstein" ?
"Bernstein" :
"Lagrange";
395 pressure_disc_orders,
397 args[
"space"][
"poly_basis_type"],
401 mass_quadrature_order,
402 use_corner_quadrature,
403 args[
"space"][
"advanced"][
"n_harmonic_samples"],
404 args[
"space"][
"advanced"][
"integral_constraints"],
418 for (
const auto &lb : all_boundary)
441 for (
int d = 0; d < mesh.
dimension(); ++d)
467 delta = (max - min) / 2. + min;
469 p_params[
"bbox_center"] = {delta(0), delta(1), delta(2)};
471 p_params[
"bbox_center"] = {delta(0), delta(1)};
478 logger().info(
"Assigning rhs...");
487 const int prev_size =
rhs_.rows();
494 if (!
problem->is_time_dependent())
506 logger().info(
"Assembling mass mat...");
513 std::vector<Eigen::Triplet<double>> blocks;
514 blocks.reserve(velocity_mass.nonZeros());
515 for (
int k = 0; k < velocity_mass.outerSize(); ++k)
516 for (StiffnessMatrix::InnerIterator it(velocity_mass, k); it; ++it)
517 blocks.emplace_back(it.row(), it.col(), it.value());
520 mass_.setFromTriplets(blocks.begin(), blocks.end());
521 mass_.makeCompressed();
524 for (
int k = 0; k < velocity_mass.outerSize(); ++k)
525 for (StiffnessMatrix::InnerIterator it(velocity_mass, k); it; ++it)
527 assert(it.col() == k);
530 avg_mass_ /= std::max(1,
int(velocity_mass.rows()));
533 if (
args[
"solver"][
"advanced"][
"lump_mass_matrix"])
554 mesh_->dimension(), sol);
556 if (!was_solution_loaded)
558 if (
problem->is_time_dependent())
562 sol.resize(
rhs_.size(), 1);
568 sol.conservativeResize(Eigen::NoChange, 1);
575 const int cols = std::max(1,
int(stacked.cols()));
579 const int primary_rows = std::min(
primary_ndof(),
int(stacked.rows()));
580 if (primary_rows > 0)
581 primary.topRows(primary_rows) = stacked.topRows(primary_rows);
586 if (pressure_rows > 0)
587 pressure.topRows(pressure_rows) = stacked.middleRows(
primary_ndof(), pressure_rows);
595 logger().info(
"Assembling stiffness mat...");
597 StiffnessMatrix velocity_stiffness, mixed_stiffness, pressure_stiffness;
604 velocity_stiffness, mixed_stiffness, pressure_stiffness, stiffness);
612 stats.
mat_size = (
long long)stiffness.rows() * (
long long)stiffness.cols();
619 const std::unique_ptr<polysolve::linear::Solver> &solver,
622 const bool compute_spectrum,
623 Eigen::MatrixXd &sol)
633 args[
"output"][
"data"][
"stiffness_mat"],
641 const double error = (A *
x - b).norm();
643 logger().error(
"Solver error: {}", error);
645 logger().debug(
"Solver error: {}", error);
650 const Eigen::MatrixXd &solution,
653 std::vector<io::OutputField> fields;
657 Eigen::MatrixXd velocity, pressure;
660 const int field_dim =
mesh_->dimension();
663 const bool export_solution_gradient =
665 const bool export_pressure_gradient =
668 const auto resize_to_output_rows = [&](Eigen::MatrixXd &values) {
669 if (output_rows <= values.rows())
672 const int previous_rows = values.rows();
673 values.conservativeResize(output_rows, values.cols());
674 values.bottomRows(output_rows - previous_rows).setZero();
677 const auto sample_vector_field = [&](
const Eigen::MatrixXd &dof_values, Eigen::MatrixXd &values, Eigen::MatrixXd *gradients =
nullptr) ->
bool {
678 if (dof_values.size() <= 0 || field_dim <= 0)
681 if (has_element_samples)
691 values.row(i).setZero();
693 gradients->row(i).setZero();
697 Eigen::MatrixXd local_sol, local_grad;
700 element_id, sample.
local_points.row(i), dof_values, local_sol, local_grad);
702 for (
int d = 0; d < field_dim; ++d)
703 values(i, d) = local_sol(d);
705 gradients->row(i) = local_grad;
708 resize_to_output_rows(values);
710 resize_to_output_rows(*gradients);
716 values.resize(sample.
node_ids.size(), field_dim);
717 for (
int i = 0; i < sample.
node_ids.size(); ++i)
719 const int node_id = sample.
node_ids(i);
720 for (
int d = 0; d < field_dim; ++d)
722 const int dof = node_id * field_dim + d;
723 if (dof < 0 || dof >= dof_values.rows())
725 values(i, d) = dof_values(dof);
728 return sample.
points.rows() == 0 || sample.
points.rows() == values.rows();
734 Eigen::MatrixXd velocity_values, velocity_gradients;
735 const bool sampled_velocity = sample_vector_field(
736 velocity, velocity_values,
737 export_solution_gradient ? &velocity_gradients :
nullptr);
738 if (sampled_velocity && options.
export_field(
"velocity"))
740 if (sampled_velocity && options.export_field(
"solution"))
742 if (sampled_velocity && export_solution_gradient)
745 if (mesh_ && (options.export_field(
"pressure") || export_pressure_gradient))
747 Eigen::MatrixXd values, gradients;
748 if (sample_scalar_field(
749 *mesh_, pressure_space_.basis_list(),
space_.geometry_basis_list(), sample, pressure, values,
750 export_pressure_gradient ? &gradients : nullptr))
752 if (options.export_field(
"pressure"))
754 if (export_pressure_gradient)
759 const auto ¶view_options =
args[
"output"][
"paraview"][
"options"];
760 if (paraview_options[
"material"] && has_element_samples)
762 const auto ¶ms = primary_assembler_->parameters();
763 std::map<std::string, Eigen::MatrixXd> param_values;
764 for (
const auto &[p, _] : params)
765 param_values[p].setZero(output_rows, 1);
767 Eigen::MatrixXd rhos = Eigen::MatrixXd::Zero(output_rows, 1);
768 const auto &density = mass_assembler_->density();
769 for (
int i = 0; i < sample.local_points.rows(); ++i)
771 const int element_id = sample.element_ids(i);
775 for (
const auto &[p, func] : params)
776 param_values.at(p)(i) =
func(sample.local_points.row(i), sample.
points.row(i), sample.time, element_id);
777 rhos(i) = density(sample.local_points.row(i), sample.points.row(i), sample.time, element_id);
780 for (
const auto &[name, values] : param_values)
781 if (options.export_field(name))
783 if (options.export_field(
"rho"))
787 if (paraview_options[
"body_ids"] && options.export_field(
"body_ids") && has_element_samples)
789 Eigen::MatrixXd ids = Eigen::MatrixXd::Zero(output_rows, 1);
790 for (
int i = 0; i < sample.element_ids.size(); ++i)
792 const int element_id = sample.element_ids(i);
794 ids(i) = mesh_->get_body_id(element_id);
802 void StokesVarForm::solve_static_linear(Eigen::MatrixXd &sol)
804 auto solver = polysolve::linear::Solver::create(args[
"solver"][
"linear"],
logger());
805 logger().info(
"{}...", solver->name());
807 const int gdiscr_order = mesh_->orders().size() <= 0 ? 1 : mesh_->orders().maxCoeff();
808 const QuadratureOrders boundary_samples = n_boundary_samples(
space_.disc_orders.maxCoeff(), gdiscr_order);
809 rhs_assembler_->set_bc(
810 boundary_.local_boundary, boundary_.boundary_nodes, boundary_samples,
811 boundary_.local_neumann_boundary, rhs_);
814 build_stiffness_mat(A);
815 Eigen::VectorXd b = rhs_;
816 solve_linear_system(solver, A, b, args[
"output"][
"advanced"][
"spectrum"], sol);
819 void StokesVarForm::solve_transient_linear(Eigen::MatrixXd &sol)
821 auto solver = polysolve::linear::Solver::create(args[
"solver"][
"linear"],
logger());
822 logger().info(
"{}...", solver->name());
824 Eigen::MatrixXd velocity, pressure;
825 split_solution(sol, velocity, pressure);
827 auto bdf = make_bdf_time_integrator();
830 Eigen::MatrixXd::Zero(velocity.rows(), velocity.cols()),
831 Eigen::MatrixXd::Zero(velocity.rows(), velocity.cols()),
833 time_integrator = bdf;
835 save_timestep(t0, 0, t0, dt, sol);
837 Eigen::MatrixXd current_rhs = rhs_;
839 build_stiffness_mat(stiffness);
841 const int gdiscr_order = mesh_->orders().size() <= 0 ? 1 : mesh_->orders().maxCoeff();
842 const QuadratureOrders boundary_samples = n_boundary_samples(
space_.disc_orders.maxCoeff(), gdiscr_order);
844 for (
int t = 1; t <= time_steps; ++t)
846 const double time = t0 + t * dt;
847 rhs_assembler_->compute_energy_grad(
848 boundary_.local_boundary, boundary_.boundary_nodes, mass_assembler_->density(), boundary_samples, boundary_.local_neumann_boundary, rhs_, time,
850 rhs_assembler_->set_bc(
851 boundary_.local_boundary, boundary_.boundary_nodes, boundary_samples, boundary_.local_neumann_boundary, current_rhs, velocity, time);
853 if (current_rhs.rows() != stacked_ndof())
855 const int old_rows = current_rhs.rows();
856 current_rhs.conservativeResize(stacked_ndof(), current_rhs.cols());
857 if (stacked_ndof() > old_rows)
858 current_rhs.bottomRows(stacked_ndof() - old_rows).setZero();
860 current_rhs.bottomRows(pressure_block_size()).setZero();
863 Eigen::VectorXd b = Eigen::VectorXd::Zero(stacked_ndof());
864 b.head(primary_ndof()) = (mass_ * bdf->weighted_sum_x_prevs()) / bdf->beta_dt();
865 for (
int i : boundary_.boundary_nodes)
869 solve_linear_system(solver, A, b, args[
"output"][
"advanced"][
"spectrum"].get<bool>() && t == time_steps, sol);
870 split_solution(sol, velocity, pressure);
871 bdf->update_quantities(velocity.col(0));
873 save_timestep(time, t, t0, dt, sol);
874 save_step_state(t0, dt, t, time_integrator.get());
875 logger().info(
"{}/{} t={}", t, time_steps, time);
876 notify_time_step(t, time_steps, t0, dt);
880 void StokesVarForm::solve_problem(Eigen::MatrixXd &sol)
882 stats.spectrum.setZero();
885 logger().info(
"Solving {}", primary_assembler_->name());
887 prepare_initial_solution(sol);
888 if (problem->is_time_dependent())
889 solve_transient_linear(sol);
892 time_integrator =
nullptr;
893 solve_static_linear(sol);
897 timings.solving_time = timer.getElapsedTime();
898 logger().info(
" took {}s", timings.solving_time);
901 void NavierStokesVarForm::solve_static(Eigen::MatrixXd &sol)
903 assert(rhs_assembler_ !=
nullptr);
904 const int gdiscr_order = mesh_->orders().size() <= 0 ? 1 : mesh_->orders().maxCoeff();
905 const QuadratureOrders boundary_samples = n_boundary_samples(
space_.disc_orders.maxCoeff(), gdiscr_order);
906 rhs_assembler_->set_bc(
907 boundary_.local_boundary, boundary_.boundary_nodes, boundary_samples, boundary_.local_neumann_boundary, rhs_);
909 auto velocity_stokes_assembler = std::make_shared<assembler::StokesVelocity>();
910 set_materials(*velocity_stokes_assembler, mesh_->dimension());
915 space_.n_bases, pressure_space_.n_bases,
916 space_.basis_list(), pressure_space_.basis_list(),
917 space_.geometry_basis_list(),
918 *velocity_stokes_assembler,
921 *pressure_assembler_,
923 pressure_ass_vals_cache_,
924 boundary_.boundary_nodes,
931 ns_solver.
get_info(stats.solver_info);
934 void NavierStokesVarForm::solve_transient(Eigen::MatrixXd &sol)
937 Eigen::MatrixXd velocity, pressure;
938 split_solution(sol, velocity, pressure);
940 auto bdf = make_bdf_time_integrator();
943 Eigen::MatrixXd::Zero(velocity.rows(), velocity.cols()),
944 Eigen::MatrixXd::Zero(velocity.rows(), velocity.cols()),
946 time_integrator = bdf;
948 save_timestep(t0, 0, t0, dt, sol);
950 Eigen::MatrixXd current_rhs = rhs_;
952 mass_assembler_->assemble(mesh_->is_volume(),
space_.n_bases,
space_.basis_list(),
space_.geometry_basis_list(), mass_ass_vals_cache_, 0, velocity_mass,
true);
954 StiffnessMatrix velocity_stiffness, mixed_stiffness, pressure_stiffness;
955 auto velocity_stokes_assembler = std::make_shared<assembler::StokesVelocity>();
956 set_materials(*velocity_stokes_assembler, mesh_->dimension());
958 mixed_assembler_->assemble(mesh_->is_volume(), pressure_space_.n_bases,
space_.n_bases, pressure_space_.basis_list(),
space_.basis_list(),
space_.geometry_basis_list(), pressure_ass_vals_cache_, ass_vals_cache_, 0, mixed_stiffness);
959 pressure_assembler_->assemble(mesh_->is_volume(), pressure_space_.n_bases, pressure_space_.basis_list(),
space_.geometry_basis_list(), pressure_ass_vals_cache_, 0, pressure_stiffness);
962 for (
int t = 1; t <= time_steps; ++t)
964 const double time = t0 + t * dt;
965 velocity_stokes_assembler->assemble(mesh_->is_volume(),
space_.n_bases,
space_.basis_list(),
space_.geometry_basis_list(), ass_vals_cache_, time, velocity_stiffness);
967 logger().info(
"{}/{} steps, dt={}s t={}s", t, time_steps, dt, time);
969 const Eigen::VectorXd prev_sol = bdf->weighted_sum_x_prevs();
970 const int gdiscr_order = mesh_->orders().size() <= 0 ? 1 : mesh_->orders().maxCoeff();
971 const QuadratureOrders boundary_samples = n_boundary_samples(
space_.disc_orders.maxCoeff(), gdiscr_order);
972 rhs_assembler_->compute_energy_grad(
973 boundary_.local_boundary, boundary_.boundary_nodes, mass_assembler_->density(), boundary_samples, boundary_.local_neumann_boundary, rhs_, time, current_rhs);
974 rhs_assembler_->set_bc(
975 boundary_.local_boundary, boundary_.boundary_nodes, boundary_samples, boundary_.local_neumann_boundary, current_rhs, velocity, time);
977 if (current_rhs.rows() != stacked_ndof())
979 const int old_rows = current_rhs.rows();
980 current_rhs.conservativeResize(stacked_ndof(), current_rhs.cols());
981 if (stacked_ndof() > old_rows)
982 current_rhs.bottomRows(stacked_ndof() - old_rows).setZero();
984 current_rhs.bottomRows(pressure_block_size()).setZero();
986 Eigen::VectorXd tmp_sol;
988 space_.n_bases, pressure_space_.n_bases,
993 boundary_.boundary_nodes,
997 std::sqrt(bdf->acceleration_scaling()), prev_sol, velocity_stiffness, mixed_stiffness,
998 pressure_stiffness, velocity_mass, current_rhs, tmp_sol);
1000 split_solution(sol, velocity, pressure);
1001 bdf->update_quantities(velocity.col(0));
1002 save_timestep(time, t, t0, dt, sol);
1003 save_step_state(t0, dt, t, time_integrator.get());
1004 notify_time_step(t, time_steps, t0, dt);
1007 ns_solver.
get_info(stats.solver_info);
1010 void NavierStokesVarForm::solve_problem(Eigen::MatrixXd &sol)
1012 stats.spectrum.setZero();
1015 logger().info(
"Solving {}", primary_assembler_->name());
1017 prepare_initial_solution(sol);
1018 if (problem->is_time_dependent())
1019 solve_transient(sol);
1022 time_integrator =
nullptr;
1027 timings.solving_time = timer.getElapsedTime();
1028 logger().info(
" took {}s", timings.solving_time);
std::array< Matrix< int, 3, 3 >, 3 > space_
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.
Represents one basis function and its gradient.
Stores the basis functions for a given element in a mesh (facet in 2d, cell in 3d).
static void interpolate_at_local_vals(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const int el_index, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &fun, Eigen::MatrixXd &result, Eigen::MatrixXd &result_grad)
interpolate solution and gradient at element (calls interpolate_at_local_vals with sol)
static void compute_stress_at_quadrature_points(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXi &disc_orders, const Eigen::VectorXi &disc_ordersq, const assembler::Assembler &assembler, const Eigen::MatrixXd &fun, const double t, Eigen::MatrixXd &result, Eigen::VectorXd &von_mises)
compute von mises stress at quadrature points for the function fun, also compute the interpolated fun...
void export_data(const OutputSpace &space, const OutputFieldFunction &output_fields, const bool is_time_dependent, const double tend_in, const double dt, const ExportOptions &opts, const std::string &vis_mesh_path) const
exports everytihng, txt, vtu, etc
double assembling_stiffness_mat_time
time to assembly
double assigning_rhs_time
time to computing the rhs
double assembling_mass_mat_time
time to assembly mass
int n_flipped
number of flipped elements, compute only when using count_flipped_els (false by default)
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 count_flipped_elements(const polyfem::mesh::Mesh &mesh, const std::vector< polyfem::basis::ElementBases > &gbases)
counts the number of flipped elements
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
void compute_mesh_size(const polyfem::mesh::Mesh &mesh_in, const std::vector< polyfem::basis::ElementBases > &bases_in, const int n_samples, const bool use_curved_mesh_size)
computes the mesh size, it samples every edges n_samples times uses curved_mesh_size (false by defaul...
long long nn_zero
non zeros and sytem matrix size num dof is the total dof in the system
double mesh_size
max edge lenght
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.
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
virtual void bounding_box(RowVectorNd &min, RowVectorNd &max) const =0
computes the bbox of the mesh
virtual bool is_volume() const =0
checks if mesh is volume
void update_nodes(const Eigen::VectorXi &in_node_to_node)
Update the node ids to reorder them.
int dimension() const
utily for dimension
static const ProblemFactory & factory()
std::shared_ptr< assembler::Problem > get_problem(const std::string &problem) const
static void p_refine(const mesh::Mesh &mesh, const double B, const bool h1_formula, const int base_p, const int discr_order_max, io::OutStatsData &stats, Eigen::VectorXi &disc_orders)
compute a priori prefinement
void minimize(const int n_bases, const int n_pressure_bases, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &pressure_bases, const std::vector< basis::ElementBases > &gbases, const assembler::Assembler &velocity_stokes_assembler, assembler::NavierStokesVelocity &velocity_assembler, const assembler::MixedAssembler &mixed_assembler, const assembler::Assembler &pressure_assembler, const assembler::AssemblyValsCache &ass_vals_cache, const assembler::AssemblyValsCache &pressure_ass_vals_cache, const std::vector< int > &boundary_nodes, const bool use_avg_pressure, const int problem_dim, const bool is_volume, const Eigen::MatrixXd &rhs, Eigen::VectorXd &x)
void get_info(json ¶ms)
void minimize(const int n_bases, const int n_pressure_bases, const double t, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, assembler::NavierStokesVelocity &velocity_assembler, const assembler::AssemblyValsCache &ass_vals_cache, const std::vector< int > &boundary_nodes, const bool use_avg_pressure, const int problem_dim, const bool is_volume, const double beta_dt, const Eigen::VectorXd &prev_sol, const StiffnessMatrix &velocity_stiffness, const StiffnessMatrix &mixed_stiffness, const StiffnessMatrix &pressure_stiffness, const StiffnessMatrix &velocity_mass1, const Eigen::MatrixXd &rhs, Eigen::VectorXd &x)
void get_info(json ¶ms)
bool write_matrix(const std::string &path, const Mat &mat)
Writes a matrix to a file. Determines the file format based on the path's extension.
Eigen::SparseMatrix< double > lump_matrix(const Eigen::SparseMatrix< double > &M)
Lump each row of a matrix into the diagonal.
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
spdlog::logger & logger()
Retrieves the current logger.
std::array< int, 2 > QuadratureOrders
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
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
Eigen::VectorXi element_ids
Eigen::MatrixXd local_points