22#ifndef DUMUX_FACETCOUPLING_GMSH_READER_HH
23#define DUMUX_FACETCOUPLING_GMSH_READER_HH
31#include <unordered_map>
33#include <dune/common/timer.hh>
34#include <dune/common/version.hh>
35#include <dune/common/fvector.hh>
36#include <dune/geometry/type.hh>
59template <
class BulkGr
id,
int numGr
ids>
63 static constexpr int bulkDim = BulkGrid::dimension;
64 static constexpr int bulkDimWorld = BulkGrid::dimensionworld;
65 using ctype =
typename BulkGrid::ctype;
67 using GlobalPosition = Dune::FieldVector<ctype, bulkDimWorld>;
70 static constexpr int minGridDim = BulkGrid::dimension - numGrids + 1;
71 static_assert(minGridDim >= 1,
"Grids with dim < 1 cannot be read!");
74 using VertexIndexSet = std::vector<GridIndexType>;
77 Dune::GeometryType gt;
78 VertexIndexSet cornerIndices;
84 void read(
const std::string& fileName,
bool verbose =
false)
86 read(fileName, 0, verbose);
90 void read(
const std::string& fileName, std::size_t boundarySegThresh,
bool verbose =
false)
93 if (verbose) std::cout <<
"Opening " << fileName << std::endl;
94 std::ifstream gridFile(fileName);
96 DUNE_THROW(Dune::InvalidStateException,
"Could not open the given .msh file. Make sure it exists");
100 std::getline(gridFile,
line);
101 if (
line.find(
"$MeshFormat") == std::string::npos)
102 DUNE_THROW(Dune::InvalidStateException,
"Expected $MeshFormat in the first line of the grid file!");
103 std::getline(gridFile,
line);
104 if (
line.find_first_of(
"2") != 0)
105 DUNE_THROW(Dune::InvalidStateException,
"Currently only Gmsh mesh file format version 2 is supported!");
108 while (
line.find(
"$Nodes") == std::string::npos)
109 std::getline(gridFile,
line);
112 std::getline(gridFile,
line);
113 const auto numVertices = convertString<std::size_t>(
line);
114 gridVertices_.resize(numVertices);
116 std::getline(gridFile,
line);
117 std::size_t vertexCount = 0;
118 while (
line.find(
"$EndNodes") == std::string::npos)
121 std::istringstream stream(
line);
122 std::string buf; stream >> buf;
124 for (
auto& coord : v)
127 if (stream.fail()) DUNE_THROW(Dune::IOError,
"Could not read vertex coordinate");
131 gridVertices_[vertexCount++] = v;
132 std::getline(gridFile,
line);
136 if (vertexCount != numVertices)
137 DUNE_THROW(Dune::InvalidStateException,
"Couldn't find as many vertices as stated in the .msh file");
140 while(
line.find(
"$Elements") == std::string::npos)
141 std::getline(gridFile,
line);
144 std::getline(gridFile,
line);
145 const auto numElements = convertString<std::size_t>(
line);
148 std::array<std::size_t, numGrids> elementCount;
149 std::fill(elementCount.begin(), elementCount.end(), 0);
153 std::size_t elemCount = 0;
154 std::array<std::size_t, numGrids> gridVertexCount;
155 std::array<std::vector<GridIndexType>, numGrids> gridVertexMap;
156 std::array<std::vector<bool>, numGrids> idxIsAssigned;
157 std::fill(gridVertexCount.begin(), gridVertexCount.end(), 0);
158 std::fill(gridVertexMap.begin(), gridVertexMap.end(), std::vector<GridIndexType>(vertexCount));
159 std::fill(idxIsAssigned.begin(), idxIsAssigned.end(), std::vector<bool>(vertexCount,
false));
160 std::getline(gridFile,
line);
161 while (
line.find(
"$EndElements") == std::string::npos)
164 std::istringstream stream(
line);
166 std::vector<std::size_t> lineData;
167 while (stream >> buf) lineData.push_back(convertString<std::size_t>(buf));
168 assert(lineData.size() >= 4 &&
"Grid format erroneous or unsupported");
171 const auto gt = obtainGeometryType( lineData[1] );
172 const std::size_t physicalIndex = lineData[3];
173 const auto geoDim = gt.dim();
174 const bool isBoundarySeg = geoDim != bulkDim && physicalIndex < boundarySegThresh;
175 if (geoDim >= minGridDim-1)
178 if ((isBoundarySeg || geoDim == minGridDim-1))
180 const unsigned int nextLevelGridIdx = bulkDim-geoDim-1;
182 VertexIndexSet corners;
183 auto it = lineData.begin()+2+lineData[2]+1;
184 for (; it != lineData.end(); ++it)
189 if (!idxIsAssigned[nextLevelGridIdx][*it])
191 gridVertexMap[nextLevelGridIdx][*it] = gridVertexCount[nextLevelGridIdx]++;
192 idxIsAssigned[nextLevelGridIdx][*it] =
true;
193 vertexIndices_[nextLevelGridIdx].push_back(*it);
196 corners.push_back(gridVertexMap[nextLevelGridIdx][*it]);
200 boundaryMarkerMaps_[nextLevelGridIdx].push_back(physicalIndex);
201 boundarySegments_[nextLevelGridIdx].push_back(corners);
207 const unsigned int gridIdx = bulkDim-geoDim;
209 VertexIndexSet corners;
210 auto it = lineData.begin()+2+lineData[2]+1;
211 for (; it != lineData.end(); ++it)
216 if (!idxIsAssigned[gridIdx][*it])
218 gridVertexMap[gridIdx][*it] = gridVertexCount[gridIdx]++;
219 idxIsAssigned[gridIdx][*it] =
true;
220 vertexIndices_[gridIdx].push_back(*it);
223 corners.push_back(gridVertexMap[gridIdx][*it]);
227 if (geoDim > minGridDim)
229 const auto gridElemCount = elementData_[gridIdx].size();
230 const auto& embeddedVIndices = vertexIndices_[gridIdx+1];
231 const auto& embeddedIndicesAssigned = idxIsAssigned[gridIdx+1];
233 VertexIndexSet cornerIndicesGlobal(corners.size());
234 for (
unsigned int i = 0; i < corners.size(); ++i)
235 cornerIndicesGlobal[i] = vertexIndices_[gridIdx][corners[i]];
236 addEmbeddings(cornerIndicesGlobal, gridIdx, gridElemCount, embeddedVIndices, embeddedIndicesAssigned);
240 reorder(gt, corners);
243 elementMarkerMaps_[gridIdx].push_back(physicalIndex);
244 elementData_[gridIdx].emplace_back(ElementData({gt, corners}));
249 std::getline(gridFile,
line);
254 if (elemCount != numElements)
255 DUNE_THROW(Dune::InvalidStateException,
"Didn't read as many elements as stated in the .msh file");
259 std::cout <<
"Finished reading gmsh file" << std::endl;
260 for (std::size_t
id = 0;
id < numGrids; ++id)
262 std::cout << elementData_[id].size() <<
" "
263 << bulkDim-
id <<
"-dimensional elements comprising of "
264 << gridVertexCount[id] <<
" vertices";
265 if (
id < numGrids-1) std::cout <<
"," << std::endl;
267 std::cout <<
" have been read in " << watch.elapsed() <<
" seconds." << std::endl;
273 {
return gridVertices_; }
278 assert(
id < numGrids &&
"Index exceeds number of grids provided");
279 return vertexIndices_[id];
285 assert(
id < numGrids &&
"Index exceeds number of grids provided");
286 return elementData_[id];
292 assert(
id < numGrids &&
"Index exceeds number of grids provided");
293 return boundarySegments_[id];
299 assert(
id < numGrids &&
"Index exceeds number of grids provided");
300 return elementMarkerMaps_[id];
306 assert(
id < numGrids &&
"Index exceeds number of grids provided");
307 return boundaryMarkerMaps_[id];
311 std::unordered_map< GridIndexType, std::vector<GridIndexType> >&
embeddedEntityMap(std::size_t
id)
313 assert(
id < numGrids &&
"Index exceeds number of grids provided");
314 return embeddedEntityMaps_[id];
318 std::unordered_map< GridIndexType, std::vector<GridIndexType> >&
adjoinedEntityMap(std::size_t
id)
320 assert(
id < numGrids &&
"Index exceeds number of grids provided");
321 return adjoinedEntityMaps_[id];
327 T convertString(
const std::string&
string)
const
330 std::istringstream stream(
string);
333 DUNE_THROW(Dune::InvalidStateException,
"Couldn't convert string: " <<
string <<
"to type: " <<
typeid(T).name());
338 Dune::GeometryType obtainGeometryType(std::size_t gmshElemType)
const
341 switch (gmshElemType)
343 case 15:
return Dune::GeometryTypes::vertex;
344 case 1:
return Dune::GeometryTypes::line;
345 case 2:
return Dune::GeometryTypes::triangle;
346 case 3:
return Dune::GeometryTypes::quadrilateral;
347 case 4:
return Dune::GeometryTypes::tetrahedron;
348 case 5:
return Dune::GeometryTypes::hexahedron;
350 DUNE_THROW(Dune::NotImplemented,
"FacetCoupling gmsh reader for gmsh element type " << gmshElemType);
355 void reorder(
const Dune::GeometryType gt, VertexIndexSet& cornerIndices)
const
358 if (gt == Dune::GeometryTypes::hexahedron)
361 assert(cornerIndices.size() == 8);
362 swap(cornerIndices[2], cornerIndices[3]);
363 swap(cornerIndices[6], cornerIndices[7]);
365 else if (gt == Dune::GeometryTypes::quadrilateral)
368 assert(cornerIndices.size() == 4);
369 swap(cornerIndices[2], cornerIndices[3]);
374 void addEmbeddings(
const VertexIndexSet& globalCornerIndices,
375 unsigned int gridIdx,
376 std::size_t curElemIdx,
377 const std::vector<GridIndexType>& embeddedVIndices,
378 const std::vector<bool>& embededIndexIsAssigned)
380 const unsigned int embeddedGridIdx = gridIdx+1;
383 for (
auto globalCornerIdx : globalCornerIndices)
385 if (embededIndexIsAssigned[globalCornerIdx])
387 for (std::size_t i = 0; i < elementData_[embeddedGridIdx].size(); ++i)
389 const auto& e = elementData_[embeddedGridIdx][i];
391 auto vertIsContained = [&embeddedVIndices, &globalCornerIndices] (
auto eCornerIdx)
393 return std::find(globalCornerIndices.begin(),
394 globalCornerIndices.end(),
395 embeddedVIndices[eCornerIdx]) != globalCornerIndices.end();
399 if ( std::all_of(e.cornerIndices.begin(), e.cornerIndices.end(), vertIsContained) )
401 embeddedEntityMaps_[gridIdx][curElemIdx].push_back(i);
402 adjoinedEntityMaps_[embeddedGridIdx][i].push_back(curElemIdx);
412 std::vector<GlobalPosition> gridVertices_;
413 std::array<VertexIndexSet, numGrids> vertexIndices_;
414 std::array<std::vector<ElementData>, numGrids> elementData_;
415 std::array<std::vector<VertexIndexSet>, numGrids> boundarySegments_;
418 std::array< std::unordered_map< GridIndexType, std::vector<GridIndexType> >, numGrids > embeddedEntityMaps_;
419 std::array< std::unordered_map< GridIndexType, std::vector<GridIndexType> >, numGrids > adjoinedEntityMaps_;
422 std::array< std::vector<int>, numGrids > elementMarkerMaps_;
423 std::array< std::vector<int>, numGrids > boundaryMarkerMaps_;
Defines the index types used for grid and local indices.
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
typename GridView::IndexSet::IndexType GridIndex
Definition: indextraits.hh:39
Reads gmsh files where (n-1)-dimensional grids are defined on the faces or edges of n-dimensional gri...
Definition: gmshreader.hh:61
const std::vector< VertexIndexSet > & boundarySegmentData(std::size_t id) const
Returns the vector of read elements for a grid.
Definition: gmshreader.hh:290
std::unordered_map< GridIndexType, std::vector< GridIndexType > > & embeddedEntityMap(std::size_t id)
Returns the maps of the embedded entities.
Definition: gmshreader.hh:311
void read(const std::string &fileName, bool verbose=false)
Definition: gmshreader.hh:84
std::vector< int > & elementMarkerMap(std::size_t id)
Returns the maps of element markers.
Definition: gmshreader.hh:297
void read(const std::string &fileName, std::size_t boundarySegThresh, bool verbose=false)
Reads the data from a given mesh file.
Definition: gmshreader.hh:90
std::unordered_map< GridIndexType, std::vector< GridIndexType > > & adjoinedEntityMap(std::size_t id)
Returns the maps of the embedments.
Definition: gmshreader.hh:318
const std::vector< ElementData > & elementData(std::size_t id) const
Returns the vector of read elements for a grid.
Definition: gmshreader.hh:283
const std::vector< GlobalPosition > & gridVertices() const
Returns the vector with all grid vertices (entire hierarchy)
Definition: gmshreader.hh:272
std::vector< int > & boundaryMarkerMap(std::size_t id)
Returns the maps of domain markers.
Definition: gmshreader.hh:304
VertexIndexSet & vertexIndices(std::size_t id)
Returns a grid's vertex indices.
Definition: gmshreader.hh:276