12#ifndef DUMUX_FACETCOUPLING_GMSH_READER_HH
13#define DUMUX_FACETCOUPLING_GMSH_READER_HH
21#include <unordered_map>
23#include <dune/common/timer.hh>
24#include <dune/common/fvector.hh>
25#include <dune/geometry/type.hh>
48template <
class BulkGr
id,
int numGr
ids>
52 static constexpr int bulkDim = BulkGrid::dimension;
53 static constexpr int bulkDimWorld = BulkGrid::dimensionworld;
54 using ctype =
typename BulkGrid::ctype;
56 using GlobalPosition = Dune::FieldVector<ctype, bulkDimWorld>;
59 static constexpr int minGridDim = BulkGrid::dimension - numGrids + 1;
60 static_assert(minGridDim >= 1,
"Grids with dim < 1 cannot be read!");
63 using VertexIndexSet = std::vector<GridIndexType>;
66 Dune::GeometryType gt;
67 VertexIndexSet cornerIndices;
73 void read(
const std::string& fileName,
bool verbose =
false)
75 read(fileName, 0, verbose);
79 void read(
const std::string& fileName, std::size_t boundarySegThresh,
bool verbose =
false)
82 if (verbose) std::cout <<
"Opening " << fileName << std::endl;
83 std::ifstream gridFile(fileName);
85 DUNE_THROW(Dune::InvalidStateException,
"Could not open the given .msh file. Make sure it exists");
89 std::getline(gridFile,
line);
90 if (
line.find(
"$MeshFormat") == std::string::npos)
91 DUNE_THROW(Dune::InvalidStateException,
"Expected $MeshFormat in the first line of the grid file!");
92 std::getline(gridFile,
line);
93 if (
line.find_first_of(
"2") != 0)
94 DUNE_THROW(Dune::InvalidStateException,
"Currently only Gmsh mesh file format version 2 is supported!");
97 while (
line.find(
"$Nodes") == std::string::npos)
98 std::getline(gridFile,
line);
101 std::getline(gridFile,
line);
102 const auto numVertices = convertString<std::size_t>(
line);
103 gridVertices_.resize(numVertices);
105 std::getline(gridFile,
line);
106 std::size_t vertexCount = 0;
107 while (
line.find(
"$EndNodes") == std::string::npos)
110 std::istringstream stream(
line);
111 std::string buf; stream >> buf;
113 for (
auto& coord : v)
116 if (stream.fail()) DUNE_THROW(Dune::IOError,
"Could not read vertex coordinate");
120 gridVertices_[vertexCount++] = v;
121 std::getline(gridFile,
line);
125 if (vertexCount != numVertices)
126 DUNE_THROW(Dune::InvalidStateException,
"Couldn't find as many vertices as stated in the .msh file");
129 while(
line.find(
"$Elements") == std::string::npos)
130 std::getline(gridFile,
line);
133 std::getline(gridFile,
line);
134 const auto numElements = convertString<std::size_t>(
line);
137 std::array<std::size_t, numGrids> elementCount;
138 std::fill(elementCount.begin(), elementCount.end(), 0);
142 std::size_t elemCount = 0;
143 std::array<std::size_t, numGrids> gridVertexCount;
144 std::array<std::vector<GridIndexType>, numGrids> gridVertexMap;
145 std::array<std::vector<bool>, numGrids> idxIsAssigned;
146 std::fill(gridVertexCount.begin(), gridVertexCount.end(), 0);
147 std::fill(gridVertexMap.begin(), gridVertexMap.end(), std::vector<GridIndexType>(vertexCount));
148 std::fill(idxIsAssigned.begin(), idxIsAssigned.end(), std::vector<bool>(vertexCount,
false));
149 std::getline(gridFile,
line);
150 while (
line.find(
"$EndElements") == std::string::npos)
153 std::istringstream stream(
line);
155 std::vector<std::size_t> lineData;
156 while (stream >> buf) lineData.push_back(convertString<std::size_t>(buf));
157 assert(lineData.size() >= 4 &&
"Grid format erroneous or unsupported");
160 const auto gt = obtainGeometryType( lineData[1] );
161 const std::size_t physicalIndex = lineData[3];
162 const auto geoDim = gt.dim();
163 const bool isBoundarySeg = geoDim != bulkDim && physicalIndex < boundarySegThresh;
164 if (geoDim >= minGridDim-1)
167 if ((isBoundarySeg || geoDim == minGridDim-1))
169 const unsigned int nextLevelGridIdx = bulkDim-geoDim-1;
171 VertexIndexSet corners;
172 auto it = lineData.begin()+2+lineData[2]+1;
173 for (; it != lineData.end(); ++it)
178 if (!idxIsAssigned[nextLevelGridIdx][*it])
180 gridVertexMap[nextLevelGridIdx][*it] = gridVertexCount[nextLevelGridIdx]++;
181 idxIsAssigned[nextLevelGridIdx][*it] =
true;
182 vertexIndices_[nextLevelGridIdx].push_back(*it);
185 corners.push_back(gridVertexMap[nextLevelGridIdx][*it]);
189 boundaryMarkerMaps_[nextLevelGridIdx].push_back(physicalIndex);
190 boundarySegments_[nextLevelGridIdx].push_back(corners);
196 const unsigned int gridIdx = bulkDim-geoDim;
198 VertexIndexSet corners;
199 auto it = lineData.begin()+2+lineData[2]+1;
200 for (; it != lineData.end(); ++it)
205 if (!idxIsAssigned[gridIdx][*it])
207 gridVertexMap[gridIdx][*it] = gridVertexCount[gridIdx]++;
208 idxIsAssigned[gridIdx][*it] =
true;
209 vertexIndices_[gridIdx].push_back(*it);
212 corners.push_back(gridVertexMap[gridIdx][*it]);
216 if (geoDim > minGridDim)
218 const auto gridElemCount = elementData_[gridIdx].size();
219 const auto& embeddedVIndices = vertexIndices_[gridIdx+1];
220 const auto& embeddedIndicesAssigned = idxIsAssigned[gridIdx+1];
222 VertexIndexSet cornerIndicesGlobal(corners.size());
223 for (
unsigned int i = 0; i < corners.size(); ++i)
224 cornerIndicesGlobal[i] = vertexIndices_[gridIdx][corners[i]];
225 addEmbeddings(cornerIndicesGlobal, gridIdx, gridElemCount, embeddedVIndices, embeddedIndicesAssigned);
229 reorder(gt, corners);
232 elementMarkerMaps_[gridIdx].push_back(physicalIndex);
233 elementData_[gridIdx].emplace_back(ElementData({gt, corners}));
238 std::getline(gridFile,
line);
243 if (elemCount != numElements)
244 DUNE_THROW(Dune::InvalidStateException,
"Didn't read as many elements as stated in the .msh file");
248 std::cout <<
"Finished reading gmsh file" << std::endl;
249 for (std::size_t
id = 0;
id < numGrids; ++id)
251 std::cout << elementData_[id].size() <<
" "
252 << bulkDim-
id <<
"-dimensional elements comprising of "
253 << gridVertexCount[id] <<
" vertices";
254 if (
id < numGrids-1) std::cout <<
"," << std::endl;
256 std::cout <<
" have been read in " << watch.elapsed() <<
" seconds." << std::endl;
262 {
return gridVertices_; }
267 assert(
id < numGrids &&
"Index exceeds number of grids provided");
268 return vertexIndices_[id];
274 assert(
id < numGrids &&
"Index exceeds number of grids provided");
275 return elementData_[id];
281 assert(
id < numGrids &&
"Index exceeds number of grids provided");
282 return boundarySegments_[id];
288 assert(
id < numGrids &&
"Index exceeds number of grids provided");
289 return elementMarkerMaps_[id];
295 assert(
id < numGrids &&
"Index exceeds number of grids provided");
296 return boundaryMarkerMaps_[id];
300 std::unordered_map< GridIndexType, std::vector<GridIndexType> >&
embeddedEntityMap(std::size_t
id)
302 assert(
id < numGrids &&
"Index exceeds number of grids provided");
303 return embeddedEntityMaps_[id];
307 std::unordered_map< GridIndexType, std::vector<GridIndexType> >&
adjoinedEntityMap(std::size_t
id)
309 assert(
id < numGrids &&
"Index exceeds number of grids provided");
310 return adjoinedEntityMaps_[id];
316 T convertString(
const std::string&
string)
const
319 std::istringstream stream(
string);
322 DUNE_THROW(Dune::InvalidStateException,
"Couldn't convert string: " <<
string <<
"to type: " <<
typeid(T).name());
327 Dune::GeometryType obtainGeometryType(std::size_t gmshElemType)
const
329 switch (gmshElemType)
331 case 15:
return Dune::GeometryTypes::vertex;
333 case 2:
return Dune::GeometryTypes::triangle;
334 case 3:
return Dune::GeometryTypes::quadrilateral;
335 case 4:
return Dune::GeometryTypes::tetrahedron;
336 case 5:
return Dune::GeometryTypes::hexahedron;
338 DUNE_THROW(Dune::NotImplemented,
"FacetCoupling gmsh reader for gmsh element type " << gmshElemType);
343 void reorder(
const Dune::GeometryType gt, VertexIndexSet& cornerIndices)
const
346 if (gt == Dune::GeometryTypes::hexahedron)
349 assert(cornerIndices.size() == 8);
350 swap(cornerIndices[2], cornerIndices[3]);
351 swap(cornerIndices[6], cornerIndices[7]);
353 else if (gt == Dune::GeometryTypes::quadrilateral)
356 assert(cornerIndices.size() == 4);
357 swap(cornerIndices[2], cornerIndices[3]);
362 void addEmbeddings(
const VertexIndexSet& globalCornerIndices,
363 unsigned int gridIdx,
364 std::size_t curElemIdx,
365 const std::vector<GridIndexType>& embeddedVIndices,
366 const std::vector<bool>& embededIndexIsAssigned)
368 const unsigned int embeddedGridIdx = gridIdx+1;
371 for (
auto globalCornerIdx : globalCornerIndices)
373 if (embededIndexIsAssigned[globalCornerIdx])
375 for (std::size_t i = 0; i < elementData_[embeddedGridIdx].size(); ++i)
377 const auto& e = elementData_[embeddedGridIdx][i];
379 auto vertIsContained = [&embeddedVIndices, &globalCornerIndices] (
auto eCornerIdx)
381 return std::find(globalCornerIndices.begin(),
382 globalCornerIndices.end(),
383 embeddedVIndices[eCornerIdx]) != globalCornerIndices.end();
387 if ( std::all_of(e.cornerIndices.begin(), e.cornerIndices.end(), vertIsContained) )
389 embeddedEntityMaps_[gridIdx][curElemIdx].push_back(i);
390 adjoinedEntityMaps_[embeddedGridIdx][i].push_back(curElemIdx);
400 std::vector<GlobalPosition> gridVertices_;
401 std::array<VertexIndexSet, numGrids> vertexIndices_;
402 std::array<std::vector<ElementData>, numGrids> elementData_;
403 std::array<std::vector<VertexIndexSet>, numGrids> boundarySegments_;
406 std::array< std::unordered_map< GridIndexType, std::vector<GridIndexType> >, numGrids > embeddedEntityMaps_;
407 std::array< std::unordered_map< GridIndexType, std::vector<GridIndexType> >, numGrids > adjoinedEntityMaps_;
410 std::array< std::vector<int>, numGrids > elementMarkerMaps_;
411 std::array< std::vector<int>, numGrids > boundaryMarkerMaps_;
Reads gmsh files where (n-1)-dimensional grids are defined on the faces or edges of n-dimensional gri...
Definition: gmshreader.hh:50
const std::vector< VertexIndexSet > & boundarySegmentData(std::size_t id) const
Returns the vector of read elements for a grid.
Definition: gmshreader.hh:279
std::unordered_map< GridIndexType, std::vector< GridIndexType > > & embeddedEntityMap(std::size_t id)
Returns the maps of the embedded entities.
Definition: gmshreader.hh:300
void read(const std::string &fileName, bool verbose=false)
Definition: gmshreader.hh:73
std::vector< int > & elementMarkerMap(std::size_t id)
Returns the maps of element markers.
Definition: gmshreader.hh:286
void read(const std::string &fileName, std::size_t boundarySegThresh, bool verbose=false)
Reads the data from a given mesh file.
Definition: gmshreader.hh:79
std::unordered_map< GridIndexType, std::vector< GridIndexType > > & adjoinedEntityMap(std::size_t id)
Returns the maps of the embedments.
Definition: gmshreader.hh:307
const std::vector< ElementData > & elementData(std::size_t id) const
Returns the vector of read elements for a grid.
Definition: gmshreader.hh:272
const std::vector< GlobalPosition > & gridVertices() const
Returns the vector with all grid vertices (entire hierarchy)
Definition: gmshreader.hh:261
std::vector< int > & boundaryMarkerMap(std::size_t id)
Returns the maps of domain markers.
Definition: gmshreader.hh:293
VertexIndexSet & vertexIndices(std::size_t id)
Returns a grid's vertex indices.
Definition: gmshreader.hh:265
constexpr Line line
Definition: couplingmanager1d3d_line.hh:31
typename GridView::IndexSet::IndexType GridIndex
Definition: indextraits.hh:27