38 const std::string msh_filename,
39 const bool decoupled_edges
43 std::ifstream file(msh_filename);
45 throw std::runtime_error(
"Could not open mesh file: " + msh_filename);
49 std::getline(file, line);
50 if (line !=
"$MeshFormat")
51 throw std::runtime_error(
"Invalid Gmsh file format: missing $MeshFormat header");
53 std::getline(file, line);
54 std::istringstream iss (line);
56 int file_type, data_size;
57 iss >> version >> file_type >> data_size;
59 if (version < 2.0 || version >= 3.0)
60 throw std::runtime_error(
".msh file version must be 2.x");
62 std::getline(file, line);
65 std::size_t num_vertices = 0;
66 std::size_t num_faces = 0;
67 std::size_t num_physical_names = 0;
69 bool in_nodes =
false;
70 bool in_elements =
false;
71 bool in_physical_names =
false;
73 std::map<Index, Index> surface_to_num_elems;
74 std::map<Index, Index> physical_to_num_elems;
75 std::vector<std::string> physical_names;
79 while (std::getline(file, line))
84 std::getline(file, line);
85 num_vertices = std::stoull(line);
88 if (line ==
"$EndNodes")
93 if (line ==
"$Elements")
96 std::getline(file, line);
99 if (line ==
"$EndElements")
104 if (line ==
"$PhysicalNames")
106 in_physical_names =
true;
107 std::getline(file, line);
108 num_physical_names = std::stoull(line);
111 if (line ==
"$EndPhysicalNames")
113 in_physical_names =
false;
117 if (in_physical_names)
119 std::istringstream iss(line);
122 iss >> n1 >> n2 >> name;
123 name.erase(std::remove(name.begin(), name.end(),
'\"' ), name.end());
124 physical_names.push_back(name);
130 std::istringstream iss(line);
131 std::size_t elm_id, elm_type, num_tags, phys_tag, surf_tag;
132 iss >> elm_id >> elm_type >> num_tags >> phys_tag >> surf_tag;
137 if (elm_type == elm_map)
141 bool inserted_surface = surface_to_num_elems.insert(std::make_pair(surf_tag, 1)).second;
142 if (!inserted_surface)
143 surface_to_num_elems[surf_tag]++;
145 bool inserted_physical = physical_to_num_elems.insert(std::make_pair(phys_tag, 1)).second;
146 if (!inserted_physical)
147 physical_to_num_elems[phys_tag]++;
156 std::map<Index, EigRowVec<Index>> surface_elems;
157 std::map<Index, Index> surface_elem_counters;
158 for (
auto& [key, value]: surface_to_num_elems)
161 surface_elem_counters[key] = 0;
164 std::map<Index, EigRowVec<Index>> physical_elems;
165 std::map<Index, Index> physical_elem_counters;
166 for (
auto& [key, value]: physical_to_num_elems)
169 physical_elem_counters[key] = 0;
177 while (std::getline(file, line) && line !=
"$Nodes") {}
178 std::getline(file, line);
181 std::size_t vertex_idx = 0;
182 while (std::getline(file, line) && line !=
"$EndNodes")
184 std::istringstream iss(line);
185 std::size_t vertex_id;
187 iss >> vertex_id >> x >> y >> z;
188 verts.col(vertex_idx++) << x, y, z;
192 while (std::getline(file, line) && line !=
"$Elements") {}
193 std::getline(file, line);
196 std::size_t face_idx = 0;
197 while (std::getline(file, line) && line !=
"$EndElements")
199 std::istringstream iss(line);
200 std::size_t elm_id, elm_type, num_tags;
201 iss >> elm_id >> elm_type >> num_tags;
204 throw std::runtime_error(
205 "Unexpected number of tags in file " + msh_filename +
" for element " + std::to_string(elm_id)
208 std::vector<std::size_t> tags (num_tags);
209 for (std::size_t ii = 0; ii < num_tags; ++ii)
212 std::size_t ptag = tags[0] - 1;
213 std::size_t stag = tags[1] - 1;
216 if (elm_type == elm_map)
218 physical_elems[ptag][physical_elem_counters[ptag]++] = face_idx;
219 surface_elems[stag][surface_elem_counters[stag]++] = face_idx;
221 for (std::size_t ii = 0; ii < 3; ++ii)
226 elems(ii, face_idx) = v - 1;
229 elem_tags[face_idx] = ptag;
234 structure.mesh().set_data(verts, elems, elem_tags, decoupled_edges);
236 for (
const auto& [key, value]: surface_elems)
238 MeshView view (structure.mesh(), value,
"surface_id_" + std::to_string(key));
240 structure.add_metacomponent(metacomp);
242 for (
const auto& [key, value]: physical_elems)
244 std::string name = physical_names[key] +
"_physical_id_" + std::to_string(key);
245 MeshView view (structure.mesh(), value, name);
247 structure.add_component(comp);
257 const std::string msh_filename,
258 const std::string extension
262 std::ofstream file(msh_filename +
"." + extension);
264 throw std::runtime_error(
"Could not open mesh file: " + msh_filename +
"." + extension);
267 file <<
"$MeshFormat\n";
269 file <<
"$EndMeshFormat\n";
272 file <<
"$PhysicalNames\n";
273 file << structure.components().size() <<
"\n";
274 for (
Index ii = 0; ii < structure.components().size(); ++ii)
275 file <<
"2 " << ii + 1 <<
" \"" << structure.components()[ii].name() <<
"\"\n";
276 file <<
"$EndPhysicalNames\n";
280 file << structure.mesh().num_verts() <<
"\n";
281 for (
Index ii = 0; ii < structure.mesh().num_verts(); ++ii)
284 file << (ii + 1) <<
" " << v[0] <<
" " << v[1] <<
" " << v[2] <<
"\n";
286 file <<
"$EndNodes\n";
290 for (
Index jj = 0; jj < structure.components().size(); ++jj)
291 num_elems += structure.components()[jj].mesh_view().elem_inds().size();
293 file <<
"$Elements\n";
294 file << num_elems <<
"\n";
296 for (
Index jj = 0; jj < structure.components().size(); ++jj)
298 for (
Index ii = 0; ii < structure.components()[jj].mesh_view().elem_inds().size(); ++ii)
301 structure.components()[jj].mesh_view().elem_inds()[ii]
303 file << elem_idx++ <<
" 2 2 ";
304 file << jj + 1 <<
" " << jj + 1 <<
" ";
305 file << (fv[0] + 1) <<
" " << (fv[1] + 1) <<
" " << (fv[2] + 1) <<
"\n";
308 file <<
"$EndElements\n";