24#ifndef DUMUX_FACETCOUPLING_GMSH_READER_HH
25#define DUMUX_FACETCOUPLING_GMSH_READER_HH
33#include <unordered_map>
35#include <dune/common/timer.hh>
36#include <dune/common/fvector.hh>
37#include <dune/geometry/type.hh>
60template <
class BulkGr
id,
int numGr
ids>
64 static constexpr int bulkDim = BulkGrid::dimension;
65 static constexpr int bulkDimWorld = BulkGrid::dimensionworld;
66 using ctype =
typename BulkGrid::ctype;
68 using GlobalPosition = Dune::FieldVector<ctype, bulkDimWorld>;
71 static constexpr int minGridDim = BulkGrid::dimension - numGrids + 1;
72 static_assert(minGridDim >= 1,
"Grids with dim < 1 cannot be read!");
75 using VertexIndexSet = std::vector<GridIndexType>;
78 Dune::GeometryType gt;
79 VertexIndexSet cornerIndices;
85 void read(
const std::string& fileName,
bool verbose =
false)
87 read(fileName, 0, verbose);
91 void read(
const std::string& fileName, std::size_t boundarySegThresh,
bool verbose =
false)
94 if (verbose) std::cout <<
"Opening " << fileName << std::endl;
95 std::ifstream gridFile(fileName);
97 DUNE_THROW(Dune::InvalidStateException,
"Could not open the given .msh file. Make sure it exists");
101 std::getline(gridFile,
line);
102 if (
line.find(
"$MeshFormat") == std::string::npos)
103 DUNE_THROW(Dune::InvalidStateException,
"Expected $MeshFormat in the first line of the grid file!");
104 std::getline(gridFile,
line);
105 if (
line.find_first_of(
"2") != 0)
106 DUNE_THROW(Dune::InvalidStateException,
"Currently only Gmsh mesh file format version 2 is supported!");
109 while (
line.find(
"$Nodes") == std::string::npos)
110 std::getline(gridFile,
line);
113 std::getline(gridFile,
line);
114 const auto numVertices = convertString<std::size_t>(
line);
115 gridVertices_.resize(numVertices);
117 std::getline(gridFile,
line);
118 std::size_t vertexCount = 0;
119 while (
line.find(
"$EndNodes") == std::string::npos)
122 std::istringstream stream(
line);
123 std::string buf; stream >> buf;
125 for (
auto& coord : v)
128 if (stream.fail()) DUNE_THROW(Dune::IOError,
"Could not read vertex coordinate");
132 gridVertices_[vertexCount++] = v;
133 std::getline(gridFile,
line);
137 if (vertexCount != numVertices)
138 DUNE_THROW(Dune::InvalidStateException,
"Couldn't find as many vertices as stated in the .msh file");
141 while(
line.find(
"$Elements") == std::string::npos)
142 std::getline(gridFile,
line);
145 std::getline(gridFile,
line);
146 const auto numElements = convertString<std::size_t>(
line);
149 std::array<std::size_t, numGrids> elementCount;
150 std::fill(elementCount.begin(), elementCount.end(), 0);
154 std::size_t elemCount = 0;
155 std::array<std::size_t, numGrids> gridVertexCount;
156 std::array<std::vector<GridIndexType>, numGrids> gridVertexMap;
157 std::array<std::vector<bool>, numGrids> idxIsAssigned;
158 std::fill(gridVertexCount.begin(), gridVertexCount.end(), 0);
159 std::fill(gridVertexMap.begin(), gridVertexMap.end(), std::vector<GridIndexType>(vertexCount));
160 std::fill(idxIsAssigned.begin(), idxIsAssigned.end(), std::vector<bool>(vertexCount,
false));
161 std::getline(gridFile,
line);
162 while (
line.find(
"$EndElements") == std::string::npos)
165 std::istringstream stream(
line);
167 std::vector<std::size_t> lineData;
168 while (stream >> buf) lineData.push_back(convertString<std::size_t>(buf));
169 assert(lineData.size() >= 4 &&
"Grid format erroneous or unsupported");
172 const auto gt = obtainGeometryType( lineData[1] );
173 const std::size_t physicalIndex = lineData[3];
174 const auto geoDim = gt.dim();
175 const bool isBoundarySeg = geoDim != bulkDim && physicalIndex < boundarySegThresh;
176 if (geoDim >= minGridDim-1)
179 if ((isBoundarySeg || geoDim == minGridDim-1))
181 const unsigned int nextLevelGridIdx = bulkDim-geoDim-1;
183 VertexIndexSet corners;
184 auto it = lineData.begin()+2+lineData[2]+1;
185 for (; it != lineData.end(); ++it)
190 if (!idxIsAssigned[nextLevelGridIdx][*it])
192 gridVertexMap[nextLevelGridIdx][*it] = gridVertexCount[nextLevelGridIdx]++;
193 idxIsAssigned[nextLevelGridIdx][*it] =
true;
194 vertexIndices_[nextLevelGridIdx].push_back(*it);
197 corners.push_back(gridVertexMap[nextLevelGridIdx][*it]);
201 boundaryMarkerMaps_[nextLevelGridIdx].push_back(physicalIndex);
202 boundarySegments_[nextLevelGridIdx].push_back(corners);
208 const unsigned int gridIdx = bulkDim-geoDim;
210 VertexIndexSet corners;
211 auto it = lineData.begin()+2+lineData[2]+1;
212 for (; it != lineData.end(); ++it)
217 if (!idxIsAssigned[gridIdx][*it])
219 gridVertexMap[gridIdx][*it] = gridVertexCount[gridIdx]++;
220 idxIsAssigned[gridIdx][*it] =
true;
221 vertexIndices_[gridIdx].push_back(*it);
224 corners.push_back(gridVertexMap[gridIdx][*it]);
228 if (geoDim > minGridDim)
230 const auto gridElemCount = elementData_[gridIdx].size();
231 const auto& embeddedVIndices = vertexIndices_[gridIdx+1];
232 const auto& embeddedIndicesAssigned = idxIsAssigned[gridIdx+1];
234 VertexIndexSet cornerIndicesGlobal(corners.size());
235 for (
unsigned int i = 0; i < corners.size(); ++i)
236 cornerIndicesGlobal[i] = vertexIndices_[gridIdx][corners[i]];
237 addEmbeddings(cornerIndicesGlobal, gridIdx, gridElemCount, embeddedVIndices, embeddedIndicesAssigned);
241 reorder(gt, corners);
244 elementMarkerMaps_[gridIdx].push_back(physicalIndex);
245 elementData_[gridIdx].emplace_back(ElementData({gt, corners}));
250 std::getline(gridFile,
line);
255 if (elemCount != numElements)
256 DUNE_THROW(Dune::InvalidStateException,
"Didn't read as many elements as stated in the .msh file");
260 std::cout <<
"Finished reading gmsh file" << std::endl;
261 for (std::size_t
id = 0;
id < numGrids; ++id)
263 std::cout << elementData_[id].size() <<
" "
264 << bulkDim-
id <<
"-dimensional elements comprising of "
265 << gridVertexCount[id] <<
" vertices";
266 if (
id < numGrids-1) std::cout <<
"," << std::endl;
268 std::cout <<
" have been read in " << watch.elapsed() <<
" seconds." << std::endl;
274 {
return gridVertices_; }
279 assert(
id < numGrids &&
"Index exceeds number of grids provided");
280 return vertexIndices_[id];
286 assert(
id < numGrids &&
"Index exceeds number of grids provided");
287 return elementData_[id];
293 assert(
id < numGrids &&
"Index exceeds number of grids provided");
294 return boundarySegments_[id];
300 assert(
id < numGrids &&
"Index exceeds number of grids provided");
301 return elementMarkerMaps_[id];
307 assert(
id < numGrids &&
"Index exceeds number of grids provided");
308 return boundaryMarkerMaps_[id];
312 std::unordered_map< GridIndexType, std::vector<GridIndexType> >&
embeddedEntityMap(std::size_t
id)
314 assert(
id < numGrids &&
"Index exceeds number of grids provided");
315 return embeddedEntityMaps_[id];
319 std::unordered_map< GridIndexType, std::vector<GridIndexType> >&
adjoinedEntityMap(std::size_t
id)
321 assert(
id < numGrids &&
"Index exceeds number of grids provided");
322 return adjoinedEntityMaps_[id];
328 T convertString(
const std::string&
string)
const
331 std::istringstream stream(
string);
334 DUNE_THROW(Dune::InvalidStateException,
"Couldn't convert string: " <<
string <<
"to type: " <<
typeid(T).name());
339 Dune::GeometryType obtainGeometryType(std::size_t gmshElemType)
const
341 switch (gmshElemType)
343 case 15:
return Dune::GeometryTypes::vertex;
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.
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
constexpr Line line
Definition: couplingmanager1d3d_line.hh:43
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:62
const std::vector< VertexIndexSet > & boundarySegmentData(std::size_t id) const
Returns the vector of read elements for a grid.
Definition: gmshreader.hh:291
std::unordered_map< GridIndexType, std::vector< GridIndexType > > & embeddedEntityMap(std::size_t id)
Returns the maps of the embedded entities.
Definition: gmshreader.hh:312
void read(const std::string &fileName, bool verbose=false)
Definition: gmshreader.hh:85
std::vector< int > & elementMarkerMap(std::size_t id)
Returns the maps of element markers.
Definition: gmshreader.hh:298
void read(const std::string &fileName, std::size_t boundarySegThresh, bool verbose=false)
Reads the data from a given mesh file.
Definition: gmshreader.hh:91
std::unordered_map< GridIndexType, std::vector< GridIndexType > > & adjoinedEntityMap(std::size_t id)
Returns the maps of the embedments.
Definition: gmshreader.hh:319
const std::vector< ElementData > & elementData(std::size_t id) const
Returns the vector of read elements for a grid.
Definition: gmshreader.hh:284
const std::vector< GlobalPosition > & gridVertices() const
Returns the vector with all grid vertices (entire hierarchy)
Definition: gmshreader.hh:273
std::vector< int > & boundaryMarkerMap(std::size_t id)
Returns the maps of domain markers.
Definition: gmshreader.hh:305
VertexIndexSet & vertexIndices(std::size_t id)
Returns a grid's vertex indices.
Definition: gmshreader.hh:277