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