34#include <spdlog/fmt/fmt.h>
35#include <paraviewo/VTMWriter.hpp>
42 bool should_use_iso_parametric(
const mesh::Mesh &mesh,
const json &args)
47 if (args[
"space"][
"basis_type"] ==
"Bernstein")
50 if (args[
"space"][
"basis_type"] ==
"Spline")
53 if (mesh.is_rational())
56 if (args[
"space"][
"use_p_ref"])
59 if (mesh.orders().size() <= 0)
61 if (args[
"space"][
"discr_order"] == 1)
63 return args[
"space"][
"advanced"][
"isoparametric"];
66 if (mesh.orders().minCoeff() != mesh.orders().maxCoeff())
69 if (args[
"space"][
"discr_order"] == mesh.orders().minCoeff())
72 return args[
"space"][
"advanced"][
"isoparametric"];
75 bool build_in_primitive_to_primitive(
76 const mesh::Mesh &mesh,
const mesh::MeshNodes &mesh_nodes,
77 const Eigen::VectorXi &in_ordered_vertices,
78 const Eigen::MatrixXi &in_ordered_edges,
79 const Eigen::MatrixXi &in_ordered_faces,
80 Eigen::VectorXi &in_primitive_to_primitive)
83 const int num_vertex_nodes = mesh_nodes.num_vertex_nodes();
84 const int num_edge_nodes = mesh_nodes.num_edge_nodes();
85 const int num_face_nodes = mesh_nodes.num_face_nodes();
86 const int num_cell_nodes = mesh_nodes.num_cell_nodes();
87 const int num_nodes = num_vertex_nodes + num_edge_nodes + num_face_nodes + num_cell_nodes;
89 const long n_vertices = num_vertex_nodes;
90 const int num_in_primitives = n_vertices + mesh.n_edges() + mesh.n_faces() + mesh.n_cells();
91 const int num_primitives = mesh.n_vertices() + mesh.n_edges() + mesh.n_faces() + mesh.n_cells();
93 in_primitive_to_primitive.setLinSpaced(num_in_primitives, 0, num_in_primitives - 1);
101 if (in_ordered_vertices.rows() != n_vertices)
103 logger().warn(
"Node ordering disabled, in_ordered_vertices != n_vertices, {} != {}", in_ordered_vertices.rows(), n_vertices);
107 in_primitive_to_primitive.head(n_vertices) = in_ordered_vertices;
109 int in_offset = n_vertices;
110 int offset = mesh.n_vertices();
116 logger().trace(
"Building Mesh edges to IDs...");
118 const auto edges_to_ids = mesh.edges_to_ids();
119 if (in_ordered_edges.rows() != edges_to_ids.size())
121 logger().warn(
"Node ordering disabled, in_ordered_edges != edges_to_ids, {} != {}", in_ordered_edges.rows(), edges_to_ids.size());
125 logger().trace(
"Done (took {}s)", timer.getElapsedTime());
127 logger().trace(
"Building in-edge to edge mapping...");
129 for (
int in_ei = 0; in_ei < in_ordered_edges.rows(); in_ei++)
131 const std::pair<int, int> in_edge(
132 in_ordered_edges.row(in_ei).minCoeff(),
133 in_ordered_edges.row(in_ei).maxCoeff());
134 in_primitive_to_primitive[in_offset + in_ei] =
135 offset + edges_to_ids.at(in_edge);
138 logger().trace(
"Done (took {}s)", timer.getElapsedTime());
140 in_offset += mesh.n_edges();
141 offset += mesh.n_edges();
147 if (mesh.is_volume())
149 logger().trace(
"Building Mesh faces to IDs...");
151 const auto faces_to_ids = mesh.faces_to_ids();
152 if (in_ordered_faces.rows() != faces_to_ids.size())
154 logger().warn(
"Node ordering disabled, in_ordered_faces != faces_to_ids, {} != {}", in_ordered_faces.rows(), faces_to_ids.size());
158 logger().trace(
"Done (took {}s)", timer.getElapsedTime());
160 logger().trace(
"Building in-face to face mapping...");
162 for (
int in_fi = 0; in_fi < in_ordered_faces.rows(); in_fi++)
164 std::vector<int> in_face;
165 in_face.reserve(in_ordered_faces.cols());
166 for (
int i = 0; i < in_ordered_faces.cols(); i++)
167 if (in_ordered_faces(in_fi, i) >= 0)
168 in_face.push_back(in_ordered_faces(in_fi, i));
169 std::sort(in_face.begin(), in_face.end());
171 in_primitive_to_primitive[in_offset + in_fi] =
172 offset + faces_to_ids.at(in_face);
175 logger().trace(
"Done (took {}s)", timer.getElapsedTime());
177 in_offset += mesh.n_faces();
178 offset += mesh.n_faces();
188 const int n_b_samples_j =
args[
"space"][
"advanced"][
"n_boundary_samples"];
189 const int boundary_order = std::max({discr_order, discr_orderq, gdiscr_order});
191 return {{n_b_samples, n_b_samples}};
209 const std::string &formulation,
212 const std::string &out_path)
226 mesh_ = std::move(mesh);
251 const std::string &formulation,
254 const std::string &out_path)
const
266 mesh_->prepare_mesh();
276 const bool iso_parametric,
277 const Eigen::VectorXi &disc_orders,
278 const Eigen::VectorXi &disc_ordersq,
279 const std::string &basis_type,
280 const std::string &poly_basis_type,
283 const int quadrature_order,
284 const int mass_quadrature_order,
285 const bool use_corner_quadrature,
286 const int n_harmonic_samples,
287 const int integral_constraints,
290 std::shared_ptr<GeometryMapping> geometry)
292 using namespace mesh;
294 const std::string space_assembler_name = space_assembler.
name();
295 const bool build_geom_mapping = geometry ==
nullptr;
302 space.
bases = std::make_shared<std::vector<basis::ElementBases>>();
303 space.
geometry = build_geom_mapping ? std::make_shared<GeometryMapping>() : std::move(geometry);
309 Eigen::MatrixXi geom_disc_orders;
310 if (build_geom_mapping && !iso_parametric)
312 if (mesh.
orders().size() <= 0)
315 geom_disc_orders.setConstant(1);
318 geom_disc_orders = mesh.
orders();
320 space.
geometry->bases = std::make_shared<std::vector<basis::ElementBases>>();
321 space.
geometry->disc_orders = geom_disc_orders;
324 Eigen::MatrixXi geom_disc_ordersq = geom_disc_orders;
326 logger().info(
"Building {} basis...", (build_geom_mapping ? (iso_parametric ?
"isoparametric" :
"not isoparametric") :
"finite-element"));
331 const bool has_polys = mesh.
has_poly();
332 std::map<int, basis::InterfaceData> poly_edge_to_data_geom;
334 const bool use_continuous_gbasis =
true;
338 const Mesh3D &tmp_mesh =
dynamic_cast<const Mesh3D &
>(mesh);
340 if (basis_type ==
"Spline")
343 tmp_mesh, space_assembler_name, quadrature_order, mass_quadrature_order,
348 if (build_geom_mapping && !iso_parametric)
350 tmp_mesh, space_assembler_name, quadrature_order, mass_quadrature_order,
351 geom_disc_orders, geom_disc_ordersq,
false,
false, has_polys,
352 !use_continuous_gbasis, use_corner_quadrature,
357 tmp_mesh, space_assembler_name, quadrature_order, mass_quadrature_order,
359 basis_type ==
"Bernstein",
360 basis_type ==
"Serendipity",
361 has_polys,
false, use_corner_quadrature,
367 const Mesh2D &tmp_mesh =
dynamic_cast<const Mesh2D &
>(mesh);
369 if (basis_type ==
"Spline")
372 tmp_mesh, space_assembler_name, quadrature_order, mass_quadrature_order,
377 if (build_geom_mapping && !iso_parametric)
379 tmp_mesh, space_assembler_name, quadrature_order, mass_quadrature_order,
380 geom_disc_orders,
false,
false, has_polys,
381 !use_continuous_gbasis, use_corner_quadrature,
386 tmp_mesh, space_assembler_name, quadrature_order, mass_quadrature_order,
388 basis_type ==
"Bernstein",
389 basis_type ==
"Serendipity",
390 has_polys,
false, use_corner_quadrature,
395 const bool use_fe_space_as_geometry = build_geom_mapping ? iso_parametric : space.
is_iso_parametric();
397 use_fe_space_as_geometry,
399 mass_quadrature_order,
401 integral_constraints,
405 if (build_geom_mapping)
408 space.
geometry->init_from_fe_space(space);
412 assert(space.
geometry->n_bases > 0);
420 if (build_geom_mapping)
423 logger().debug(
"Building node mapping...");
427 logger().debug(
"Done (took {}s)", timer2.getElapsedTime());
440 const std::string &poly_basis_type,
443 const int quadrature_order,
444 const int mass_quadrature_order,
445 const int n_harmonic_samples,
446 const int integral_constraints,
456 const std::string space_assembler_name = space_assembler.
name();
460 logger().info(
"Computing polygonal basis...");
468 if (poly_basis_type ==
"MeanValue" || poly_basis_type ==
"Wachspress")
472 assert(linear_assembler);
479 mass_quadrature_order,
480 integral_constraints,
489 if (poly_basis_type ==
"MeanValue")
492 space_assembler.
name(), dim, mesh_2d, space.
n_bases,
494 mass_quadrature_order,
497 else if (poly_basis_type ==
"Wachspress")
500 space_assembler.
name(), dim, mesh_2d, space.
n_bases,
502 mass_quadrature_order,
508 assert(linear_assembler);
515 mass_quadrature_order,
516 integral_constraints,
530 if (poly_basis_type ==
"MeanValue" || poly_basis_type ==
"Wachspress")
534 assert(linear_assembler);
541 mass_quadrature_order,
542 integral_constraints,
551 if (poly_basis_type ==
"MeanValue")
554 space_assembler.
name(), dim, mesh_2d, space.
n_bases,
556 mass_quadrature_order,
559 else if (poly_basis_type ==
"Wachspress")
562 space_assembler.
name(), dim, mesh_2d, space.
n_bases,
564 mass_quadrature_order,
570 assert(linear_assembler);
577 mass_quadrature_order,
578 integral_constraints,
595 Eigen::MatrixXd &sol,
607 const std::string &basis_type,
609 Eigen::VectorXi &space_in_node_to_node,
610 Eigen::VectorXi &space_in_primitive_to_primitive)
const
612 space_in_node_to_node.resize(0);
613 space_in_primitive_to_primitive.resize(0);
615 if (basis_type ==
"Spline")
617 logger().warn(
"Node ordering disabled, it dosent work for splines!");
623 logger().warn(
"Node ordering disabled, it works only for p < 4 and uniform order!");
629 logger().warn(
"Node ordering disabled, not supported for non-conforming meshes!");
635 logger().warn(
"Node ordering disabled, not supported for polygonal meshes!");
641 logger().warn(
"Node ordering disabled, input vertices/edges/faces not computed!");
647 logger().warn(
"Node ordering disabled, FE space does not expose mesh nodes!");
653 logger().trace(
"Building in-primitive to primitive mapping...");
655 bool ok = build_in_primitive_to_primitive(
660 space_in_primitive_to_primitive);
662 logger().trace(
"Done (took {}s)", timer.getElapsedTime());
666 space_in_node_to_node.resize(0);
667 space_in_primitive_to_primitive.resize(0);
671 const auto &tmp = space.
mesh_nodes->in_ordered_vertices();
674 max_tmp = std::max(max_tmp, v);
676 space_in_node_to_node.resize(max_tmp + 1);
677 for (
int i = 0; i < tmp.size(); ++i)
680 space_in_node_to_node[tmp[i]] = i;
685 const json &space_args,
687 Eigen::VectorXi &disc_orders,
688 Eigen::VectorXi &disc_ordersq)
694 const json &space_args,
695 const int fe_space_id,
697 Eigen::VectorXi &disc_orders,
698 Eigen::VectorXi &disc_ordersq)
700 const auto assign_order = [&](
const json &order_json, Eigen::VectorXi &orders) {
703 if (order_json.is_number_integer())
705 orders.setConstant(order_json);
707 else if (order_json.is_string())
710 assert(tmp.size() == orders.size());
711 assert(tmp.cols() == 1);
714 else if (order_json.is_array())
717 std::map<int, int> body_orders;
718 bool has_matching_order =
false;
719 for (
const json &entry : order_json)
721 if (entry.contains(
"fe_space"))
723 const int entry_space_id = entry[
"fe_space"].get<
int>();
724 if (entry_space_id >= 0 && fe_space_id < 0)
726 if (entry_space_id >= 0 && entry_space_id != fe_space_id)
730 has_matching_order =
true;
731 const int order = entry[
"order"];
732 if (!entry.contains(
"id") || (entry[
"id"].is_number_integer() && entry[
"id"].get<
int>() < 0))
734 orders.setConstant(order);
738 for (
const int id : utils::json_as_array<int>(entry[
"id"]))
740 body_orders[id] = order;
741 logger().trace(
"bid {}, discr {}",
id, order);
745 if (!has_matching_order)
750 const auto order = body_orders.find(mesh.
get_body_id(e));
751 if (order != body_orders.end())
752 orders[e] = order->second;
761 assign_order(space_args[
"discr_order"], disc_orders);
763 const json &discr_orderq = space_args[
"discr_orderq"];
764 if (discr_orderq.is_number_integer() && discr_orderq.get<
int>() < 0)
765 disc_ordersq = disc_orders;
767 assign_order(discr_orderq, disc_ordersq);
769 int max_prism_order = 0;
773 max_prism_order = std::max({max_prism_order, disc_orders[e], disc_ordersq[e]});
776 if (max_prism_order > 0)
781 disc_orders[e] = max_prism_order;
786 "discretization orders: p=[{}, {}], q=[{}, {}]",
787 disc_orders.minCoeff(), disc_orders.maxCoeff(),
788 disc_ordersq.minCoeff(), disc_ordersq.maxCoeff());
794 if (out_path.empty())
797 std::ofstream file(out_path);
800 logger().error(
"Unable to save simulation JSON to {}", out_path);
808 assert(
mesh_ !=
nullptr);
814 std::vector<int> body_ids(
mesh_->n_elements());
815 for (
int i = 0; i <
mesh_->n_elements(); ++i)
816 body_ids[i] =
mesh_->get_body_id(i);
850 sample.requested_fields.empty() ? fields : sample.requested_fields});
867 const Eigen::MatrixXd &solution,
871 const std::string pattern =
args[
"output"][
"checkpoint"][
"path"];
876 continuation[
"time"][
"t0"] = t0 + dt * t;
877 continuation[
"time"][
"time_steps"] = std::max(0,
args[
"time"][
"time_steps"].get<int>() - t);
878 continuation[
"time"].erase(
"tend");
879 continuation[
"input"][
"checkpoint"][
"path"] =
"";
883 metadata.
time = t0 + dt * t;
899 const Eigen::MatrixXd &solution,
902 writer.
write_matrix(
"/checkpoint/state/solution", solution);
909 "Checkpoint formulation '{}' does not match '{}'.",
911 if (!reader.
exists(
"/checkpoint/state/solution"))
913 solution = reader.
read_matrix(
"/checkpoint/state/solution");
918 const std::shared_ptr<time_integrator::ImplicitTimeIntegrator> &integrator,
919 const std::string &group,
921 const std::string &ordering,
923 const int block_size)
const
928 log_and_throw_error(
"Checkpoint requires integrator state at {}, but no integrator was constructed.", group);
929 const auto reorder = [
this, &ordering, &space, block_size](Eigen::MatrixXd &value) {
933 block_size, 0, value);
940 const std::string &name,
944 if (ordering.size() == 0)
947 "/checkpoint/state/orderings/" +
name,
948 std::vector<int>(ordering.data(), ordering.data() + ordering.size()));
956 std::vector<int> nodes(space.
n_bases);
957 std::iota(nodes.begin(), nodes.end(), 0);
958 std::stable_sort(nodes.begin(), nodes.end(), [&space](
const int lhs,
const int rhs) {
959 const RowVectorNd left = space.mesh_nodes->node_position(lhs);
960 const RowVectorNd right = space.mesh_nodes->node_position(rhs);
961 for (int d = 0; d < left.size(); ++d)
963 if (left[d] < right[d])
965 if (left[d] > right[d])
971 return Eigen::Map<const Eigen::VectorXi>(nodes.data(), nodes.size());
974 bool VarForm::checkpoint_reorder_enabled()
const
976 return args.contains(
"input") && args[
"input"].is_object()
977 && args[
"input"].contains(
"checkpoint") && args[
"input"][
"checkpoint"].is_object()
978 && args[
"input"][
"checkpoint"].value(
"reorder",
false);
981 void VarForm::reorder_checkpoint_block(
983 const std::string &name,
985 const int block_size,
986 const int row_offset,
987 Eigen::MatrixXd &value)
const
989 const Eigen::VectorXi current_ordering = checkpoint_ordering(space);
990 const std::string path =
"/checkpoint/state/orderings/" + name;
993 if (checkpoint_reorder_enabled() || current_ordering.size() != 0)
997 if (block_size <= 0 || current_ordering.size() == 0)
998 log_and_throw_error(
"Checkpoint reordering is unavailable for the {} solution block.", name);
1001 const Eigen::VectorXi stored_ordering = Eigen::Map<const Eigen::VectorXi>(
1002 stored_values.data(), stored_values.size());
1003 if (stored_ordering.size() != current_ordering.size())
1005 "Checkpoint {} ordering has {} nodes; the current space has {}.",
1006 name, stored_ordering.size(), current_ordering.size());
1008 const auto validate_permutation = [&name](
const Eigen::VectorXi &permutation,
const std::string &
source) {
1009 std::vector<bool> seen(permutation.size(),
false);
1010 for (
const int index : permutation)
1012 if (index < 0 || index >= permutation.size() || seen[index])
1017 validate_permutation(stored_ordering,
"Checkpoint");
1018 validate_permutation(current_ordering,
"Current");
1019 if (!checkpoint_reorder_enabled())
1021 if (stored_ordering != current_ordering)
1023 "Checkpoint {} ordering differs from the reconstructed space; enable input.checkpoint.reorder.",
1028 const int rows = current_ordering.size() * block_size;
1029 if (row_offset < 0 || row_offset + rows > value.rows())
1032 value.middleRows(row_offset, rows), stored_ordering, -1, block_size);
1034 input_order, current_ordering, -1, block_size);
1037 void VarForm::validate_checkpoint_solution(
1038 const Eigen::MatrixXd &solution,
1039 const int expected_rows)
const
1041 if (solution.rows() != expected_rows || solution.cols() != 1)
1043 "Checkpoint solution for {} has dimensions {} x {}; expected {} x 1.",
1044 name(), solution.rows(), solution.cols(), expected_rows);
1047 void VarForm::save_timestep(
const double time,
const int t,
const double t0,
const double dt,
const Eigen::MatrixXd &solution)
const
1049 paraviewo::VTMWriter vtm(time);
1050 if (!save_timestep_to_vtm(time, t, dt, solution, vtm,
""))
1053 const int global_t = output_file_index(t);
1054 const std::string step_name = args[
"output"][
"advanced"][
"timestep_prefix"];
1055 vtm.save(resolve_output_path(fmt::format(step_name +
"{:d}.vtm", global_t)));
1057 output_geometry_.save_pvd(
1058 resolve_output_path(args[
"output"][
"paraview"][
"file_name"]),
1059 [step_name](
int i) {
return fmt::format(step_name +
"{:d}.vtm", i); },
1060 global_t, t0, dt, args[
"output"][
"paraview"][
"skip_frame"].get<
int>());
1063 bool VarForm::save_timestep_to_vtm(
1064 const double time,
const int t,
const double dt,
1065 const Eigen::MatrixXd &solution, paraviewo::VTMWriter &vtm,
1066 const std::string &block_prefix)
const
1069 if (!space.
mesh || !args[
"output"][
"advanced"][
"save_time_sequence"])
1071 const int global_t = output_file_index(t);
1072 if (global_t % args[
"output"][
"paraview"][
"skip_frame"].get<int>())
1075 ensure_output_sampler();
1076 logger().trace(
"Saving VTU...");
1077 const std::string step_name = args[
"output"][
"advanced"][
"timestep_prefix"];
1078 const auto opts = export_options(space);
1079 output_geometry_.save_vtu(
1080 resolve_output_path(fmt::format(step_name +
"{:d}.vtu", global_t)),
1081 space, output_field_function(solution, opts), time, dt,
1082 opts, vtm, block_prefix);
1086 void VarForm::save_subsolve(
const int i,
const int t,
const Eigen::MatrixXd &solution)
const
1089 if (!space.
mesh || !args[
"output"][
"advanced"][
"save_solve_sequence_debug"].get<
bool>())
1092 const bool has_time = args.contains(
"time") && !args[
"time"].is_null();
1095 dt = args[
"time"][
"dt"];
1097 ensure_output_sampler();
1098 const auto opts = export_options(space);
1099 output_geometry_.save_vtu(
1100 resolve_output_path(fmt::format(
"solve_{:d}.vtu", i)),
1101 space, output_field_function(solution, opts), t, dt,
1105 void VarForm::notify_time_step(
const int t,
const int time_steps,
const double t0,
const double dt)
const
1108 time_callback(t, time_steps, t0 + dt * t, t0 + dt * time_steps);
1111 int VarForm::output_file_index(
const int t)
const
1113 return t + output_index_offset_;
1116 std::string VarForm::resolve_output_path(
const std::string &path)
const
1118 if (output_path.empty() || path.empty() || std::filesystem::path(path).is_absolute())
1122 return std::filesystem::weakly_canonical(std::filesystem::path(output_path) / path).string();
1125 void VarForm::rebuild_node_positions(
1126 const std::vector<basis::ElementBases> &bases,
1127 const std::vector<int> &node_ids,
1128 std::vector<RowVectorNd> &positions)
1130 positions.resize(node_ids.size());
1131 for (
int n = 0; n < int(node_ids.size()); ++n)
1133 const int node_id = node_ids[n];
1135 for (
const auto &bs : bases)
1137 for (
const auto &b : bs.bases)
1139 for (
const auto &lg : b.global())
1141 if (lg.index == node_id)
1143 positions[n] = lg.node;
void set_materials(const std::vector< int > &body_ids, const json &body_params, const Units &units, const io::ResourceIO &resources)
virtual bool is_tensor() const
virtual std::string name() const =0
virtual void set_size(const int size)
static int quadrature_order(const std::string &assembler, const int basis_degree, const BasisType &b_type, const int dim)
utility for retrieving the needed quadrature order to precisely integrate the given form on the given...
assemble matrix based on the local assembler local assembler is eg Laplace, LinearElasticity etc
static int build_bases(const mesh::Mesh2D &mesh, const std::string &assembler, const int quadrature_order, const int mass_quadrature_order, const int discr_order, const bool bernstein, const bool serendipity, const bool has_polys, const bool is_geom_bases, const bool use_corner_quadrature, std::vector< ElementBases > &bases, std::vector< mesh::LocalBoundary > &local_boundary, std::map< int, InterfaceData > &poly_edge_to_data, std::shared_ptr< mesh::MeshNodes > &mesh_nodes)
Builds FE basis functions over the entire mesh (P1, P2 over triangles, Q1, Q2 over quads).
static int build_bases(const mesh::Mesh3D &mesh, const std::string &assembler, const int quadrature_order, const int mass_quadrature_order, const int discr_orderp, const int discr_orderq, const bool bernstein, const bool serendipity, const bool has_polys, const bool is_geom_bases, const bool use_corner_quadrature, std::vector< ElementBases > &bases, std::vector< mesh::LocalBoundary > &local_boundary, std::map< int, InterfaceData > &poly_face_to_data, std::shared_ptr< mesh::MeshNodes > &mesh_nodes)
Builds FE basis functions over the entire mesh (P1, P2 over tets, Q1, Q2 over hes).
static int build_bases(const std::string &assembler_name, const int dim, const mesh::Mesh2D &mesh, const int n_bases, const int quadrature_order, const int mass_quadrature_order, std::vector< ElementBases > &bases, std::vector< mesh::LocalBoundary > &local_boundary, std::map< int, Eigen::MatrixXd > &mapped_boundary)
static int build_bases(const assembler::LinearAssembler &assembler, const int n_samples_per_edge, const mesh::Mesh2D &mesh, const int n_bases, const int quadrature_order, const int mass_quadrature_order, const int integral_constraints, std::vector< ElementBases > &bases, const std::vector< ElementBases > &gbases, const std::map< int, InterfaceData > &poly_edge_to_data, std::map< int, Eigen::MatrixXd > &mapped_boundary)
Build bases over the remaining polygons of a mesh.
static int build_bases(const assembler::LinearAssembler &assembler, const int n_samples_per_edge, const mesh::Mesh3D &mesh, const int n_bases, const int quadrature_order, const int mass_quadrature_order, const int integral_constraints, std::vector< ElementBases > &bases, const std::vector< ElementBases > &gbases, const std::map< int, InterfaceData > &poly_face_to_data, std::map< int, std::pair< Eigen::MatrixXd, Eigen::MatrixXi > > &mapped_boundary)
Build bases over the remaining polygons of a mesh.
static int build_bases(const mesh::Mesh2D &mesh, const std::string &assembler, const int quadrature_order, const int mass_quadrature_order, std::vector< ElementBases > &bases, std::vector< mesh::LocalBoundary > &local_boundary, std::map< int, InterfaceData > &poly_edge_to_data)
static int build_bases(const mesh::Mesh3D &mesh, const std::string &assembler, const int quadrature_order, const int mass_quadrature_order, std::vector< ElementBases > &bases, std::vector< mesh::LocalBoundary > &local_boundary, std::map< int, InterfaceData > &poly_face_to_data)
static int build_bases(const std::string &assembler_name, const int dim, const mesh::Mesh2D &mesh, const int n_bases, const int quadrature_order, const int mass_quadrature_order, std::vector< ElementBases > &bases, std::vector< mesh::LocalBoundary > &local_boundary, std::map< int, Eigen::MatrixXd > &mapped_boundary)
Eigen::MatrixXd read_matrix(const std::string &path) const
bool exists(const std::string &path) const
std::vector< int > read_int_vector(const std::string &path) const
const CheckpointMetadata & metadata() const
void write_matrix(const std::string &path, const Eigen::MatrixXd &value)
void write_mesh(const std::string &group, const mesh::Mesh &mesh)
void embed_resources(const ResourceIO &resources)
void write_int_vector(const std::string &path, const std::vector< int > &value)
void build_grid(const polyfem::mesh::Mesh &mesh, const double spacing)
builds the grid to export the solution
void init_sampler(const polyfem::mesh::Mesh &mesh, const double vismesh_rel_area)
unitalize the ref element sampler
double loading_mesh_time
time to load the mesh
double building_basis_time
time to construct the basis
double computing_poly_basis_time
time to build the polygonal/polyhedral bases
void reset()
clears all stats
void compute_mesh_stats(const polyfem::mesh::Mesh &mesh)
compute stats (counts els type, mesh lenght, etc), step 1 of solve
virtual Eigen::MatrixXi read_int_matrix(const std::string &path) const =0
std::unique_ptr< Mesh > fem
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 int get_body_id(const int primitive) const
Get the volume selection of an element (cell in 3d, face in 2d)
const Eigen::MatrixXi & in_ordered_edges() const
Order of the input edges.
virtual bool is_conforming() const =0
if the mesh is conforming
const Eigen::MatrixXi & orders() const
order of each element
bool is_simplex(const int el_id) const
checks if element is simplex
bool has_prism() const
checks if the mesh has prisms
bool is_prism(const int el_id) const
checks if element is a prism
bool is_linear() const
check if the mesh is linear
virtual bool is_volume() const =0
checks if mesh is volume
bool has_poly() const
checks if the mesh has polytopes
const Eigen::VectorXi & in_ordered_vertices() const
Order of the input vertices.
int dimension() const
utily for dimension
bool is_pyramid(const int el_id) const
checks if element is a pyramid
const Eigen::MatrixXi & in_ordered_faces() const
Order of the input edges.
Implicit time integrator of a second order ODE (equivently a system of coupled first order ODEs).
void serialize_checkpoint(io::CheckpointWriter &writer, const std::string &group) const
std::function< std::vector< OutputField >(const OutputSample &)> OutputFieldFunction
Eigen::MatrixXd reorder_matrix(const Eigen::MatrixXd &in, const Eigen::VectorXi &in_to_out, int out_blocks=-1, const int block_size=1)
Reorder row blocks in a matrix.
bool is_param_valid(const json ¶ms, const std::string &key)
Determine if a key exists and is non-null in a json object.
Eigen::MatrixXd unreorder_matrix(const Eigen::MatrixXd &out, const Eigen::VectorXi &in_to_out, int in_blocks=-1, const int block_size=1)
Undo the reordering of row blocks in a matrix.
spdlog::logger & logger()
Retrieves the current logger.
std::array< int, 2 > QuadratureOrders
void log_and_throw_error(const std::string &msg)
std::vector< std::string > fields