OGS
GmshReader.cpp
Go to the documentation of this file.
1 
10 #include "GmshReader.h"
11 
12 #include <fstream>
13 #include <map>
14 #include <vector>
15 
16 #include "BaseLib/FileTools.h"
18 #include "MeshLib/Elements/Hex.h"
19 #include "MeshLib/Elements/Line.h"
20 #include "MeshLib/Elements/Prism.h"
22 #include "MeshLib/Elements/Quad.h"
23 #include "MeshLib/Elements/Tet.h"
24 #include "MeshLib/Elements/Tri.h"
25 #include "MeshLib/Mesh.h"
27 #include "MeshLib/Node.h"
28 
29 namespace FileIO
30 {
31 namespace GMSH
32 {
33 bool isGMSHMeshFile(const std::string& fname)
34 {
35  std::ifstream input(fname.c_str());
36 
37  if (!input)
38  {
39  ERR("isGMSHMeshFile(): Could not open file {:s}.", fname);
40  return false;
41  }
42 
43  std::string header_first_line;
44  input >> header_first_line;
45  if (header_first_line.find("$MeshFormat") != std::string::npos)
46  {
47  // read version
48  std::string version;
49  getline(input, version);
50  getline(input, version);
51  INFO("isGMSHMeshFile(): Found GMSH mesh file version: {:s}.", version);
52  input.close();
53  return true;
54  }
55 
56  return false;
57 }
58 
59 void readNodeIDs(std::ifstream& in, unsigned n_nodes,
60  std::vector<unsigned>& node_ids,
61  std::map<unsigned, unsigned> const& id_map)
62 {
63  unsigned idx;
64  for (unsigned i = 0; i < n_nodes; i++)
65  {
66  in >> idx;
67  node_ids.push_back(id_map.at(idx));
68  }
69 }
70 
71 std::pair<MeshLib::Element*, int> readElement(
72  std::ifstream& in, std::vector<MeshLib::Node*> const& nodes,
73  std::map<unsigned, unsigned> const& id_map)
74 {
75  unsigned idx;
76  unsigned type;
77  unsigned n_tags;
78  unsigned dummy;
79  int mat_id;
80  std::vector<unsigned> node_ids;
81 
82  // element format is structured like this:
83  // element-id element-type n-tags physical-entity elementary entity node-ids
84  in >> idx >> type >> n_tags >> dummy >> mat_id;
85 
86  switch (type)
87  {
88  case 1:
89  {
90  readNodeIDs(in, 2, node_ids, id_map);
91  // edge_nodes array will be deleted from Line object
92  auto edge_nodes = new MeshLib::Node*[2];
93  edge_nodes[0] = nodes[node_ids[0]];
94  edge_nodes[1] = nodes[node_ids[1]];
95  return std::make_pair(new MeshLib::Line(edge_nodes), mat_id);
96  }
97  case 2:
98  {
99  readNodeIDs(in, 3, node_ids, id_map);
100  auto tri_nodes = new MeshLib::Node*[3];
101  tri_nodes[0] = nodes[node_ids[2]];
102  tri_nodes[1] = nodes[node_ids[1]];
103  tri_nodes[2] = nodes[node_ids[0]];
104  return std::make_pair(new MeshLib::Tri(tri_nodes), mat_id);
105  }
106  case 3:
107  {
108  readNodeIDs(in, 4, node_ids, id_map);
109  auto quad_nodes = new MeshLib::Node*[4];
110  for (unsigned k(0); k < 4; k++)
111  {
112  quad_nodes[k] = nodes[node_ids[k]];
113  }
114  return std::make_pair(new MeshLib::Quad(quad_nodes), mat_id);
115  }
116  case 4:
117  {
118  readNodeIDs(in, 4, node_ids, id_map);
119  auto tet_nodes = new MeshLib::Node*[5];
120  for (unsigned k(0); k < 4; k++)
121  {
122  tet_nodes[k] = nodes[node_ids[k]];
123  }
124  return std::make_pair(new MeshLib::Tet(tet_nodes), mat_id);
125  }
126  case 5:
127  {
128  readNodeIDs(in, 8, node_ids, id_map);
129  auto hex_nodes = new MeshLib::Node*[8];
130  for (unsigned k(0); k < 8; k++)
131  {
132  hex_nodes[k] = nodes[node_ids[k]];
133  }
134  return std::make_pair(new MeshLib::Hex(hex_nodes), mat_id);
135  }
136  case 6:
137  {
138  readNodeIDs(in, 6, node_ids, id_map);
139  auto prism_nodes = new MeshLib::Node*[6];
140  for (unsigned k(0); k < 6; k++)
141  {
142  prism_nodes[k] = nodes[node_ids[k]];
143  }
144  return std::make_pair(new MeshLib::Prism(prism_nodes), mat_id);
145  }
146  case 7:
147  {
148  readNodeIDs(in, 5, node_ids, id_map);
149  auto pyramid_nodes = new MeshLib::Node*[5];
150  for (unsigned k(0); k < 5; k++)
151  {
152  pyramid_nodes[k] = nodes[node_ids[k]];
153  }
154  return std::make_pair(new MeshLib::Pyramid(pyramid_nodes), mat_id);
155  }
156  case 15:
157  in >> dummy; // skip rest of line
158  break;
159  default:
160  WARN("readGMSHMesh(): Unknown element type {:d}.", type);
161  break;
162  }
163  return std::make_pair(nullptr, -1);
164 }
165 
166 MeshLib::Mesh* readGMSHMesh(std::string const& fname)
167 {
168  std::string line;
169  std::ifstream in(fname.c_str(), std::ios::in);
170  if (!in.is_open())
171  {
172  WARN("readGMSHMesh() - Could not open file {:s}.", fname);
173  return nullptr;
174  }
175 
176  getline(in, line); // $MeshFormat keyword
177  if (line.find("$MeshFormat") == std::string::npos)
178  {
179  in.close();
180  WARN("No GMSH file format recognized.");
181  return nullptr;
182  }
183 
184  getline(in, line); // version-number file-type data-size
185  if (line.substr(0, 3) != "2.2")
186  {
187  WARN("Wrong gmsh file format version '{:s}'.", line.substr(0, 3));
188  return nullptr;
189  }
190 
191  if (line[4] != '0')
192  {
193  WARN("Currently reading gmsh binary file type is not supported.");
194  return nullptr;
195  }
196  getline(in, line); //$EndMeshFormat
197 
198  std::vector<MeshLib::Node*> nodes;
199  std::vector<MeshLib::Element*> elements;
200  std::vector<int> materials;
201  std::map<unsigned, unsigned> id_map;
202  while (line.find("$EndElements") == std::string::npos)
203  {
204  // Node data
205  getline(in, line); //$Nodes Keywords
206  if (line.find("$Nodes") != std::string::npos)
207  {
208  std::size_t n_nodes(0);
209  long id;
210  double x;
211  double y;
212  double z;
213  in >> n_nodes >> std::ws;
214  nodes.resize(n_nodes);
215  for (std::size_t i = 0; i < n_nodes; i++)
216  {
217  in >> id >> x >> y >> z >> std::ws;
218  id_map.insert(std::map<unsigned, unsigned>::value_type(id, i));
219  nodes[i] = new MeshLib::Node(x, y, z, id);
220  }
221  getline(in, line); // End Node keyword $EndNodes
222  }
223 
224  // Element data
225  if (line.find("$Elements") != std::string::npos)
226  {
227  std::size_t n_elements(0);
228  if (!(in >> n_elements >> std::ws))
229  { // number-of-elements
230  ERR("Read GMSH mesh does not contain any elements");
231  }
232  elements.reserve(n_elements);
233  materials.reserve(n_elements);
234  for (std::size_t i = 0; i < n_elements; i++)
235  {
236  MeshLib::Element* elem(nullptr);
237  int mat_id(0);
238  std::tie(elem, mat_id) = readElement(in, nodes, id_map);
239 
240  if (elem)
241  {
242  elements.push_back(elem);
243  materials.push_back(mat_id);
244  }
245  }
246  getline(in, line); // END keyword
247  }
248 
249  if (line.find("PhysicalNames") != std::string::npos)
250  {
251  std::size_t n_lines(0);
252  in >> n_lines >> std::ws; // number-of-lines
253  for (std::size_t i = 0; i < n_lines; i++)
254  {
255  getline(in, line);
256  }
257  getline(in, line); // END keyword
258  }
259  }
260  in.close();
261  if (elements.empty())
262  {
263  for (auto& node : nodes)
264  {
265  delete node;
266  }
267  return nullptr;
268  }
269 
270  MeshLib::Mesh* mesh(new MeshLib::Mesh(
271  BaseLib::extractBaseNameWithoutExtension(fname), nodes, elements));
272 
273  auto* const material_ids =
275  "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
276  if (!material_ids)
277  {
278  WARN("Could not create PropertyVector for MaterialIDs in Mesh.");
279  }
280  else
281  {
282  material_ids->insert(material_ids->end(), materials.cbegin(),
283  materials.cend());
284  }
285 
287 
288  INFO("\t... finished.");
289  INFO("Nr. Nodes: {:d}.", nodes.size());
290  INFO("Nr. Elements: {:d}.", elements.size());
291 
292  return mesh;
293 }
294 
295 } // end namespace GMSH
296 } // end namespace FileIO
Definition of the ElementValueModification class.
Definition of the Element class.
Filename manipulation routines.
Definition of the Hex class.
Definition of the Line class.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:37
Definition of the Mesh class.
Definition of the Node class.
Definition of the Prism class.
Definition of the Pyramid class.
Definition of the Quad class.
Definition of the Tet class.
Definition of the Tri class.
static std::size_t condense(MeshLib::Mesh &mesh)
Properties & getProperties()
Definition: Mesh.h:123
PropertyVector< T > * createNewPropertyVector(std::string const &name, MeshItemType mesh_item_type, std::size_t n_components=1)
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180
std::pair< MeshLib::Element *, int > readElement(std::ifstream &in, std::vector< MeshLib::Node * > const &nodes, std::map< unsigned, unsigned > const &id_map)
Definition: GmshReader.cpp:71
bool isGMSHMeshFile(const std::string &fname)
Definition: GmshReader.cpp:33
MeshLib::Mesh * readGMSHMesh(std::string const &fname)
Definition: GmshReader.cpp:166
void readNodeIDs(std::ifstream &in, unsigned n_nodes, std::vector< unsigned > &node_ids, std::map< unsigned, unsigned > const &id_map)
Definition: GmshReader.cpp:59