Loading [MathJax]/extensions/tex2jax.js

dune-mmesh (unstable)

gmshgridfactory.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_MMESH_GRID_GMSHGRIDFACTORY_HH
4#define DUNE_MMESH_GRID_GMSHGRIDFACTORY_HH
5
6// System includes
7#include <memory>
8#include <utility>
9#include <vector>
10
11// Dune includes
12#include <dune/grid/common/intersection.hh>
13
14// MMesh includes
15#include <dune/mmesh/grid/explicitgridfactory.hh>
16#include <dune/mmesh/grid/implicitgridfactory.hh>
17
18namespace Dune {
19
20// External Forward Declarations
21// -----------------------------
22template <class GridImp, class IntersectionImp>
23class Intersection;
24
25// GmshGridFactory for MMesh
26// ------------------------
27template <class Grid, bool useImplicitGridFactory = false>
28struct GmshGridFactory {
29 const static int dimension = Grid::dimension;
30 typedef MPIHelper::MPICommunicator MPICommunicatorType;
31 typedef typename Grid::template Codim<0>::Entity Element;
32 typedef typename Grid::template Codim<dimension>::Entity Vertex;
33 typedef typename Grid::FieldType FieldType;
34 typedef FieldVector<FieldType, dimension> GlobalPosition;
35
36 // Choose explicit or implicit grid factory
37 typedef std::conditional_t<useImplicitGridFactory,
38 MMeshImplicitGridFactory<Grid>,
39 MMeshExplicitGridFactory<Grid> >
40 GridFactory;
41
43 explicit GmshGridFactory(std::istream &input) {
44 input.clear();
45 input.seekg(0);
46 if (!input) DUNE_THROW(DGFException, "Error resetting input stream.");
47 generate(input);
48 }
49
51 explicit GmshGridFactory(const std::string &filename) {
52 factory_ = new GridFactory();
53 std::ifstream input(filename.c_str());
54 if (!input)
55 DUNE_THROW(DGFException, "Macrofile " << filename << " not found.");
56 if (!generate(input))
57 DUNE_THROW(DGFException,
58 "Could not generate MMesh from macrofile " << filename);
59 input.close();
60 }
61
62 explicit GmshGridFactory(Dune::GridFactory<Grid> &gridFactory,
63 const std::string &filename) {
64 factory_ = &gridFactory;
65 std::ifstream input(filename.c_str());
66 if (!input)
67 DUNE_THROW(DGFException, "Macrofile " << filename << " not found.");
68 if (!generate(input))
69 DUNE_THROW(DGFException,
70 "Could not generate MMesh from macrofile " << filename);
71 input.close();
72 }
73
75 std::shared_ptr<Grid> grid() const {
76 if (!grid_) grid_ = factory_->createGrid();
77
78 return grid_;
79 }
80
82 template <class Intersection>
83 bool wasInserted(const Intersection &intersection) const {
84 return factory_->wasInserted(intersection);
85 }
86
87 private:
88 bool generate(std::istream &gridFile) {
89 // read file until we get to the list of nodes
90 std::string line;
91 std::getline(gridFile, line);
92 while (line.find("$Nodes") == std::string::npos) {
93 if (!std::getline(gridFile, line))
94 DUNE_THROW(IOError, "Gmsh file not valid!");
95 }
96
97 // read all vertices
98 std::getline(gridFile, line);
99 const auto numVertices = convertString<std::size_t>(line);
100
101 std::getline(gridFile, line);
102 std::size_t vertexCount = 0;
103 while (line.find("$EndNodes") == std::string::npos) {
104 // drop first entry in line (vertex index) and read coordinates
105 std::istringstream stream(line);
106 std::string buf;
107 stream >> buf;
108 GlobalPosition v;
109 for (auto &coord : v) {
110 stream >> coord;
111 if (stream.fail())
112 DUNE_THROW(Dune::IOError, "Could not read vertex coordinate");
113 }
114
115 // insert vertex and move to next line
116 factory_->insertVertex(v);
117 if (!std::getline(gridFile, line))
118 DUNE_THROW(IOError, "Gmsh file not valid!");
119 vertexCount++;
120 }
121
122 // we should always find as many vertices as the mesh file states
123 if (vertexCount != numVertices)
124 DUNE_THROW(Dune::InvalidStateException,
125 "Couldn't find as many vertices as stated in the .msh file");
126
127 // read file until we get to the list of elements
128 while (line.find("$Elements") == std::string::npos)
129 if (!std::getline(gridFile, line))
130 DUNE_THROW(IOError, "Gmsh file not valid!");
131
132 // read elements
133 std::getline(gridFile, line);
134 const auto numElements = convertString<std::size_t>(line);
135
136 std::size_t elemCount = 0;
137 std::getline(gridFile, line);
138 while (line.find("$EndElements") == std::string::npos) {
139 // pass all indices into vector
140 std::istringstream stream(line);
141 std::string buf;
142 std::vector<std::size_t> lineData;
143 while (stream >> buf) lineData.push_back(convertString<std::size_t>(buf));
144 assert(lineData.size() >= 4 && "Grid format erroneous or unsupported");
145
146 // obtain geometry type
147 const auto gt = obtainGeometryType(lineData[1]);
148
149 std::vector<unsigned int> cornersIndices;
150 auto it = lineData.begin() + 2 + lineData[2] + 1;
151 for (; it != lineData.end(); ++it)
152 cornersIndices.push_back(*it - 1); // gmsh indices start from 1
153
154 // insert element
155 if (gt.dim() == dimension)
156 factory_->insertElement(gt, cornersIndices, lineData[2 + lineData[2]]);
157
158 // insert interface/boundary segments
159 if (gt.dim() == dimension - 1) {
160 factory_->insertInterface(cornersIndices, lineData[2 + lineData[2]]);
161 factory_->insertBoundarySegment(cornersIndices);
162 }
163
164 // insert interface's boundary segments
165 if (gt.dim() == dimension - 2)
166 factory_->insertInterfaceBoundarySegment(cornersIndices);
167
168 // get next line
169 if (!std::getline(gridFile, line))
170 DUNE_THROW(IOError, "Gmsh file not valid!");
171 elemCount++;
172 }
173
174 // make sure we read all elements
175 if (elemCount != numElements)
176 DUNE_THROW(Dune::InvalidStateException,
177 "Didn't read as many elements as stated in the .msh file");
178
179 return true;
180 }
181
182 private:
184 template <class T>
185 T convertString(const std::string &string) const {
186 T value;
187 std::istringstream stream(string);
188 stream >> value;
189 if (stream.fail())
190 DUNE_THROW(Dune::InvalidStateException,
191 "Couldn't convert string: " << string << "to type: "
192 << typeid(T).name());
193 return value;
194 }
195
197 Dune::GeometryType obtainGeometryType(std::size_t gmshElemType) const {
198 switch (gmshElemType) {
199 case 15:
200 return Dune::GeometryTypes::vertex; // points
201 case 1:
202 return Dune::GeometryTypes::line; // lines
203 case 2:
204 return Dune::GeometryTypes::triangle; // triangle
205 case 3:
206 return Dune::GeometryTypes::quadrilateral; // quadrilateral
207 case 4:
208 return Dune::GeometryTypes::tetrahedron; // tetrahedron
209 case 5:
210 return Dune::GeometryTypes::hexahedron; // hexahedron
211 default:
212 DUNE_THROW(
213 Dune::NotImplemented,
214 "FacetCoupling gmsh reader for gmsh element type " << gmshElemType);
215 }
216 }
217
218 mutable std::shared_ptr<Grid> grid_;
219 GridFactory *factory_;
220};
221
222} // end namespace Dune
223
224#endif
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Mar 17, 23:30, 2025)