PolyFEM
Loading...
Searching...
No Matches
MshWriter.cpp
Go to the documentation of this file.
1#include "MshWriter.hpp"
2
3#include <mshio/mshio.h>
4
5namespace polyfem::io
6{
8 const std::string &path,
9 const mesh::Mesh &mesh,
10 const bool binary)
11 {
12 Eigen::MatrixXd points(mesh.n_vertices(), mesh.dimension());
13 for (int i = 0; i < mesh.n_vertices(); ++i)
14 points.col(i) = mesh.point(i);
15
16 std::vector<std::vector<int>> cells(mesh.n_elements());
17 for (int i = 0; i < mesh.n_elements(); ++i)
18 {
19 cells[i].resize(mesh.n_cell_vertices(i));
20 for (int j = 0; j < cells[i].size(); ++j)
21 cells[i][j] = mesh.cell_vertex(i, j);
22 }
23
24 return write(path, points, cells, mesh.get_body_ids(), mesh.is_volume(), binary);
25 }
26
28 const std::string &path,
29 const Eigen::MatrixXd &points,
30 const Eigen::MatrixXi &cells,
31 const std::vector<int> &body_ids,
32 const bool is_volume,
33 const bool binary)
34 {
35 std::vector<std::vector<int>> cells_vector(cells.rows(), std::vector<int>(cells.cols()));
36 for (int i = 0; i < cells.rows(); ++i)
37 for (int j = 0; j < cells.cols(); ++j)
38 cells_vector[i][j] = cells(i, j);
39
40 return write(path, points, cells_vector, body_ids, is_volume, binary);
41 }
42
44 const std::string &path,
45 const Eigen::MatrixXd &points,
46 const std::vector<std::vector<int>> &cells,
47 const std::vector<int> &body_ids,
48 const bool is_volume,
49 const bool binary)
50 {
51 assert(body_ids.size() == 0 || body_ids.size() == cells.size());
52
53 mshio::MshSpec out;
54
55 auto &format = out.mesh_format;
56 format.version = "4.1"; // Only version "2.2" and "4.1" are supported.
57 format.file_type = binary ? 1 : 0; // 0: ASCII, 1: binary.
58 format.data_size = sizeof(size_t); // Size of data, defined as sizeof(size_t) = 8.
59
60 auto &nodes = out.nodes;
61 nodes.num_entity_blocks = 1; // Number of node blocks.
62 nodes.num_nodes = points.rows(); // Total number of nodes.
63 nodes.min_node_tag = 1;
64 nodes.max_node_tag = points.rows();
65 nodes.entity_blocks.resize(1); // A std::vector of node blocks.
66 {
67 auto &block = nodes.entity_blocks[0];
68 block.entity_dim = points.cols(); // The dimension of the entity.
69 block.entity_tag = 1; // The entity these nodes belongs to.
70 block.parametric = 0; // 0: non-parametric, 1: parametric.
71 block.num_nodes_in_block = points.rows(); // The number of nodes in block.
72
73 for (int i = 0; i < points.rows(); ++i)
74 {
75 block.tags.push_back(i + 1); // A std::vector of unique, positive node tags.
76 const auto p = points.row(i);
77 block.data.push_back(p(0));
78 block.data.push_back(p(1)); // A std::vector of coordinates (x,y,z,<u>,<points>,<w>,...)
79 block.data.push_back(is_volume ? p(2) : 0);
80 }
81 }
82
83 auto &elements = out.elements;
84 elements.num_entity_blocks = cells.size(); // Number of element blocks.
85 elements.num_elements = cells.size(); // Total number of elmeents.
86 elements.min_element_tag = 1;
87 elements.max_element_tag = cells.size();
88 elements.entity_blocks.resize(cells.size()); // A std::vector of element blocks.
89
90 for (int i = 0; i < cells.size(); ++i)
91 {
92 auto &block = elements.entity_blocks[i];
93 block.entity_dim = points.cols(); // The dimension of the elements.
94 block.entity_tag = 1; // The entity these elements belongs to.
95 const int n_local_v = cells[i].size();
96 // only tet and tri for the moment
97 assert(n_local_v == 3 || n_local_v == 4);
98
99 block.element_type = n_local_v == 3 ? 2 : 4; // See element type table below.
100 block.num_elements_in_block = 1; // The number of elements in this block.
101 block.data.push_back(i + 1);
102 for (int j = 0; j < n_local_v; ++j)
103 block.data.push_back(cells[i][j] + 1); // See more detail below.
104
105 // block.entity_tag = body_ids.empty() ? 0 : body_ids[i];
106 }
107
108 // Add physical groups based on body ids
109 // std::vector<int> unique_body_ids = body_ids;
110 // if (unique_body_ids.size() == 0)
111 // unique_body_ids.push_back(0); // default body id
112 // std::sort(unique_body_ids.begin(), unique_body_ids.end());
113 // unique_body_ids.erase(std::unique(unique_body_ids.begin(), unique_body_ids.end()), unique_body_ids.end());
114 // for (const int body_id : body_ids)
115 // {
116 // if (points.cols() == 2)
117 // {
118 // out.entities.surfaces.emplace_back();
119 // out.entities.surfaces.back().tag = body_id;
120 // out.entities.surfaces.back().physical_group_tags.push_back(body_id);
121 // }
122 // else
123 // {
124 // out.entities.volumes.emplace_back();
125 // out.entities.volumes.back().tag = body_id;
126 // out.entities.volumes.back().physical_group_tags.push_back(body_id);
127 // }
128 // }
129
130 mshio::save_msh(path, out);
131 }
132} // namespace polyfem::io
static void write(const std::string &path, const mesh::Mesh &mesh, const bool binary)
saves the mesh
Definition MshWriter.cpp:7
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:39
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
Definition Mesh.hpp:161
virtual int n_vertices() const =0
number of vertices
virtual RowVectorNd point(const int global_index) const =0
point coordinates
virtual bool is_volume() const =0
checks if mesh is volume
int dimension() const
utily for dimension
Definition Mesh.hpp:151
virtual const std::vector< int > & get_body_ids() const
Get the volume selection of all elements (cells in 3d, faces in 2d)
Definition Mesh.hpp:510
virtual int cell_vertex(const int f_id, const int lv_id) const =0
id of the vertex of a cell
virtual int n_cell_vertices(const int c_id) const =0
number of vertices of a cell