OGS
MeshIO.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "MeshIO.h"
5
6#include <fstream>
7#include <iomanip>
8#include <memory>
9#include <sstream>
10
11#include "BaseLib/Error.h"
12#include "BaseLib/FileTools.h"
13#include "BaseLib/Logging.h"
14#include "BaseLib/StringTools.h"
16#include "MeshLib/Node.h"
18
19namespace
20{
21int readMaterialID(std::istream& in)
22{
23 unsigned index;
24 unsigned material_id;
25
26 if (!(in >> index >> material_id) ||
27 material_id > static_cast<unsigned>(std::numeric_limits<int>::max()))
28 {
29 // If read incorrectly or the material_id is not safely convertible to
30 // int.
31 return std::numeric_limits<int>::max();
32 }
33 // Safe conversion was checked above.
34 return static_cast<int>(material_id);
35}
36
37MeshLib::Element* readElement(std::istream& in,
38 const std::vector<MeshLib::Node*>& nodes)
39{
40 std::string elem_type_str;
42
43 do
44 {
45 if (!(in >> elem_type_str))
46 {
47 return nullptr;
48 }
49 elem_type = MeshLib::String2MeshElemType(elem_type_str);
50 } while (elem_type == MeshLib::MeshElemType::INVALID);
51
52 auto* idx = new unsigned[8];
53 MeshLib::Element* elem;
54
55 switch (elem_type)
56 {
58 {
59 for (int i = 0; i < 2; ++i)
60 {
61 if (!(in >> idx[i]))
62 {
63 return nullptr;
64 }
65 }
66 // edge_nodes array will be deleted from Line object
67 auto** edge_nodes = new MeshLib::Node*[2];
68 for (unsigned k(0); k < 2; ++k)
69 {
70 edge_nodes[k] = nodes[idx[k]];
71 }
72 elem = new MeshLib::Line(edge_nodes);
73 break;
74 }
76 {
77 for (int i = 0; i < 3; ++i)
78 {
79 if (!(in >> idx[i]))
80 {
81 return nullptr;
82 }
83 }
84 auto** tri_nodes = new MeshLib::Node*[3];
85 for (unsigned k(0); k < 3; ++k)
86 {
87 tri_nodes[k] = nodes[idx[k]];
88 }
89 elem = new MeshLib::Tri(tri_nodes);
90 break;
91 }
93 {
94 for (int i = 0; i < 4; ++i)
95 {
96 if (!(in >> idx[i]))
97 {
98 return nullptr;
99 }
100 }
101 auto** quad_nodes = new MeshLib::Node*[4];
102 for (unsigned k(0); k < 4; ++k)
103 {
104 quad_nodes[k] = nodes[idx[k]];
105 }
106 elem = new MeshLib::Quad(quad_nodes);
107 break;
108 }
110 {
111 for (int i = 0; i < 4; ++i)
112 {
113 if (!(in >> idx[i]))
114 {
115 return nullptr;
116 }
117 }
118 auto** tet_nodes = new MeshLib::Node*[4];
119 for (unsigned k(0); k < 4; ++k)
120 {
121 tet_nodes[k] = nodes[idx[k]];
122 }
123 elem = new MeshLib::Tet(tet_nodes);
124 break;
125 }
127 {
128 for (int i = 0; i < 8; ++i)
129 {
130 if (!(in >> idx[i]))
131 {
132 return nullptr;
133 }
134 }
135 auto** hex_nodes = new MeshLib::Node*[8];
136 for (unsigned k(0); k < 8; ++k)
137 {
138 hex_nodes[k] = nodes[idx[k]];
139 }
140 elem = new MeshLib::Hex(hex_nodes);
141 break;
142 }
144 {
145 for (int i = 0; i < 5; ++i)
146 {
147 if (!(in >> idx[i]))
148 {
149 return nullptr;
150 }
151 }
152 auto** pyramid_nodes = new MeshLib::Node*[5];
153 for (unsigned k(0); k < 5; ++k)
154 {
155 pyramid_nodes[k] = nodes[idx[k]];
156 }
157 elem = new MeshLib::Pyramid(pyramid_nodes);
158 break;
159 }
161 {
162 for (int i = 0; i < 6; ++i)
163 {
164 if (!(in >> idx[i]))
165 {
166 return nullptr;
167 }
168 }
169 auto** prism_nodes = new MeshLib::Node*[6];
170 for (unsigned k(0); k < 6; ++k)
171 {
172 prism_nodes[k] = nodes[idx[k]];
173 }
174 elem = new MeshLib::Prism(prism_nodes);
175 break;
176 }
177 default:
178 elem = nullptr;
179 break;
180 }
181
182 delete[] idx;
183
184 return elem;
185}
186
188{
190 {
191 return "line";
192 }
194 {
195 return "quad";
196 }
198 {
199 return "hex";
200 }
202 {
203 return "tri";
204 }
206 {
207 return "tet";
208 }
210 {
211 return "pris";
212 }
214 {
215 return "pyra";
216 }
217 return "none";
218}
219
220void writeElements(std::vector<MeshLib::Element*> const& ele_vec,
221 MeshLib::PropertyVector<int> const* const material_ids,
222 std::ostream& out)
223{
224 const std::size_t ele_vector_size(ele_vec.size());
225
226 out << ele_vector_size << "\n";
227 for (std::size_t i(0); i < ele_vector_size; ++i)
228 {
229 auto const& element = *ele_vec[i];
230 if (element.getNumberOfBaseNodes() != element.getNumberOfNodes())
231 {
232 OGS_FATAL(
233 "Found high order element in the mesh that is not required by "
234 "OGS 5 input. High order elements are generated in OGS 5 on "
235 "demand.");
236 }
237
238 out << i << " ";
239 if (!material_ids)
240 {
241 out << "0 ";
242 }
243 else
244 {
245 out << (*material_ids)[i] << " ";
246 }
247 out << ElemType2StringOutput(element.getGeomType()) << " ";
248 unsigned nElemNodes(element.getNumberOfBaseNodes());
249 for (std::size_t j = 0; j < nElemNodes; ++j)
250 {
251 out << element.getNode(j)->getID() << " ";
252 }
253 out << "\n";
254 }
255}
256
257} // namespace
258
259namespace MeshLib
260{
261namespace IO
262{
263namespace Legacy
264{
265MeshIO::MeshIO() = default;
266
267MeshLib::Mesh* MeshIO::loadMeshFromFile(const std::string& file_name)
268{
269 INFO("Reading OGS legacy mesh ... ");
270
271 std::ifstream in(file_name.c_str(), std::ios::in);
272 if (!in.is_open())
273 {
274 WARN("MeshIO::loadMeshFromFile() - Could not open file {:s}.",
275 file_name);
276 return nullptr;
277 }
278
279 std::string line_string;
280 std::getline(in, line_string);
281
282 if (line_string.find("#FEM_MSH") != std::string::npos) // OGS mesh file
283 {
284 std::vector<MeshLib::Node*> nodes;
285 std::vector<MeshLib::Element*> elements;
286 std::vector<int> materials;
287
288 while (!in.eof())
289 {
290 std::getline(in, line_string);
291
292 // check keywords
293 if (line_string.find("#STOP") != std::string::npos)
294 {
295 break;
296 }
297 if (line_string.find("$NODES") != std::string::npos)
298 {
299 std::getline(in, line_string);
300 BaseLib::trim(line_string);
301 unsigned nNodes = atoi(line_string.c_str());
302 for (unsigned i = 0; i < nNodes; ++i)
303 {
304 std::getline(in, line_string);
305 std::stringstream iss(line_string);
306 unsigned idx;
307 double x;
308 double y;
309 double z;
310 iss >> idx >> x >> y >> z;
311 auto* node(new MeshLib::Node(x, y, z, idx));
312 nodes.push_back(node);
313 std::string s;
314 iss >> s;
315 if (s.find("$AREA") != std::string::npos)
316 {
317 double double_dummy;
318 iss >> double_dummy;
319 }
320 }
321 }
322 else if (line_string.find("$ELEMENTS") != std::string::npos)
323 {
324 std::getline(in, line_string);
325 BaseLib::trim(line_string);
326 unsigned nElements = atoi(line_string.c_str());
327 for (unsigned i = 0; i < nElements; ++i)
328 {
329 std::getline(in, line_string);
330 std::stringstream ss(line_string);
331 materials.push_back(readMaterialID(ss));
332 MeshLib::Element* elem(readElement(ss, nodes));
333 if (elem == nullptr)
334 {
335 ERR("Reading mesh element {:d} from file '{:s}' "
336 "failed.",
337 i, file_name);
338 // clean up the elements vector
339 std::for_each(elements.begin(), elements.end(),
340 std::default_delete<MeshLib::Element>());
341 // clean up the nodes vector
342 std::for_each(nodes.begin(), nodes.end(),
343 std::default_delete<MeshLib::Node>());
344 return nullptr;
345 }
346 elements.push_back(elem);
347 }
348 }
349 }
350
351 if (elements.empty())
352 {
353 ERR("MeshIO::loadMeshFromFile() - File did not contain element "
354 "information.");
355 for (auto& node : nodes)
356 {
357 delete node;
358 }
359 return nullptr;
360 }
361
364 elements, true /* compute_element_neighbors */));
365
366 auto* const material_ids =
368 "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
369 if (!material_ids)
370 {
371 WARN("Could not create PropertyVector for MaterialIDs in Mesh.");
372 }
373 else
374 {
375 material_ids->assign(materials);
376 }
377 INFO("\t... finished.");
378 INFO("Nr. Nodes: {:d}.", nodes.size());
379 INFO("Nr. Elements: {:d}.", elements.size());
380
381 in.close();
382 return mesh;
383 }
384
385 in.close();
386 return nullptr;
387}
388
390{
391 if (!_mesh)
392 {
393 WARN("MeshIO::write(): Cannot write: no mesh object specified.");
394 return false;
395 }
396
397 out << "#FEM_MSH\n"
398 << "$PCS_TYPE\n"
399 << " NO_PCS\n"
400 << "$NODES\n"
401 << " ";
402 const std::size_t n_nodes(_mesh->getNumberOfNodes());
403 out << n_nodes << "\n";
404 for (std::size_t i(0); i < n_nodes; ++i)
405 {
406 out << i << " " << *(_mesh->getNode(i)) << "\n";
407 }
408
409 out << "$ELEMENTS\n"
410 << " ";
411
412 if (!_mesh->getProperties().existsPropertyVector<int>("MaterialIDs"))
413 {
414 writeElements(_mesh->getElements(), nullptr, out);
415 }
416 else
417 {
418 writeElements(
419 _mesh->getElements(),
420 _mesh->getProperties().getPropertyVector<int>("MaterialIDs"), out);
421 }
422 out << "#STOP\n";
423
424 return true;
425}
426
428{
429 _mesh = mesh;
430}
431
432} // end namespace Legacy
433} // end namespace IO
434} // namespace MeshLib
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
std::ostringstream out
The stream to write to.
Definition Writer.h:36
bool write() override
Write mesh to stream.
Definition MeshIO.cpp:389
MeshLib::Mesh * loadMeshFromFile(const std::string &file_name)
Read mesh from file.
Definition MeshIO.cpp:267
const MeshLib::Mesh * _mesh
Definition MeshIO.h:44
void setMesh(const MeshLib::Mesh *mesh)
Set mesh for writing.
Definition MeshIO.cpp:427
Properties & getProperties()
Definition Mesh.h:125
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
void trim(std::string &str, char ch)
std::string extractBaseNameWithoutExtension(std::string const &pathname)
MeshElemType String2MeshElemType(const std::string &s)
Given a string of the shortened name of the element type, this returns the corresponding MeshElemType...
Definition MeshEnums.cpp:84
TemplateElement< MeshLib::TetRule4 > Tet
Definition Tet.h:14
TemplateElement< MeshLib::LineRule2 > Line
Definition Line.h:14
TemplateElement< MeshLib::QuadRule4 > Quad
Definition Quad.h:17
TemplateElement< MeshLib::TriRule3 > Tri
Definition Tri.h:15
TemplateElement< MeshLib::PyramidRule5 > Pyramid
Definition Pyramid.h:14
TemplateElement< MeshLib::PrismRule6 > Prism
Definition Prism.h:14
MeshElemType
Types of mesh elements supported by OpenGeoSys. Values are from VTKCellType enum.
Definition MeshEnums.h:37
TemplateElement< MeshLib::HexRule8 > Hex
Definition Hex.h:14
MeshLib::Element * readElement(std::istream &in, const std::vector< MeshLib::Node * > &nodes)
Definition MeshIO.cpp:37
std::string ElemType2StringOutput(const MeshLib::MeshElemType t)
Definition MeshIO.cpp:187
void writeElements(std::vector< MeshLib::Element * > const &ele_vec, MeshLib::PropertyVector< int > const *const material_ids, std::ostream &out)
Definition MeshIO.cpp:220
int readMaterialID(std::istream &in)
Definition MeshIO.cpp:21