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