dune-mmesh (unstable)

explicitgridfactory.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4#ifndef DUNE_MMESH_GRID_EXPLICITGRIDFACTORY_HH
5#define DUNE_MMESH_GRID_EXPLICITGRIDFACTORY_HH
6
7// System includes
8#include <algorithm>
9#include <array>
10#include <limits>
11#include <map>
12#include <memory>
13
14// Dune includes
15#include <dune/geometry/referenceelements.hh>
16#include <dune/grid/common/boundarysegment.hh>
17#include <dune/grid/common/gridfactory.hh>
18
19// MMesh includes
22
23namespace Dune {
24
31template <class Grid>
32class MMeshExplicitGridFactory : public GridFactoryInterface<Grid> {
34 typedef GridFactoryInterface<Grid> Base;
35
36 public:
38 typedef typename Grid::ctype ctype;
40 typedef typename Grid::HostGridType HostGrid;
41
43 static const int dimension = Grid::dimension;
45 static const int dimensionworld = Grid::dimensionworld;
46
48 typedef FieldVector<ctype, dimensionworld> WorldVector;
50 typedef FieldMatrix<ctype, dimensionworld, dimensionworld> WorldMatrix;
51
53 typedef Dune::BoundarySegment<dimension, dimensionworld> BoundarySegment;
55 typedef typename Grid::IdType IdType;
56
58 typedef std::unordered_map<IdType, std::size_t> BoundarySegments;
59 typedef std::unordered_map<std::size_t, std::size_t> BoundaryIds;
60
62 typedef std::unordered_map<IdType, std::size_t> InterfaceSegments;
63
64 template <int codim>
65 struct Codim {
66 typedef typename Grid::template Codim<codim>::Entity Entity;
67 };
68
69 private:
70 typedef typename HostGrid::Point Point;
71 typedef typename HostGrid::Vertex_handle Vertex_handle;
72 typedef typename Grid::template HostGridEntity<0> Element_handle;
73
74 using Tuple = std::tuple<std::vector<unsigned int>, std::size_t, std::size_t>;
75
76 using Base::insertElement;
77
78 public:
80 static const bool supportsBoundaryIds = true;
82 static const bool supportPeriodicity = false;
83
85 MMeshExplicitGridFactory() { tr_.tds().clear(); }
86
92 void insertElement(const GeometryType& type,
93 const std::vector<unsigned int>& v) {
94 insertElement(type, v, 0);
95 }
96
103 void insertElement(const GeometryType& type,
104 const std::vector<unsigned int>& v,
105 const size_t domainMarker) {
106 assert(type == GeometryTypes::simplex(dimension));
107 assert(v.size() == dimension + 1);
108 auto w = v;
109
110 // Create element
111 storeElement(w, countElements, domainMarker);
112
113 // Increase element count
114 countElements++;
115
116 // Store vertices to check occurence of element later
117 elementVerticesList.push_back(w);
118 };
119
120 private:
122 void storeElement(std::vector<unsigned int>& v, const size_t insertionIndex,
123 const size_t domainMarker) {
124 elements_.push_back(std::make_tuple(v, insertionIndex, domainMarker));
125 }
126
132 template <int d = dimension>
133 std::enable_if_t<d == 2, void> createElement(std::vector<unsigned int>& v,
134 const size_t insertionIndex,
135 const size_t domainMarker) {
136 auto& p0 = vhs_[v[0]]->point();
137 auto& p1 = vhs_[v[1]]->point();
138 auto& p2 = vhs_[v[2]]->point();
139
140 // Check orientation of vertices
141 auto orientation = (p1.y() - p0.y()) * (p2.x() - p1.x()) -
142 (p1.x() - p0.x()) * (p2.y() - p1.y());
143 // if clockwise, swap two vertices
144 if (orientation > 0.0) std::swap(v[0], v[1]);
145
146 auto&& v0 = vhs_[v[0]];
147 auto&& v1 = vhs_[v[1]];
148 auto&& v2 = vhs_[v[2]];
149
150 // Create face with vertices v0, v1, v2
151 Element_handle face = tr_.tds().create_face(v0, v1, v2);
152
153 // Set insertion index
154 face->info().insertionIndex = insertionIndex;
155 face->info().domainMarker = domainMarker;
156
157 // Set this face in vertices v0, v1, v2
158 v0->set_face(face);
159 v1->set_face(face);
160 v2->set_face(face);
161
162 // Add facets to neighbor map to obtain connectivity
163 addFacetToMap({v[0], v[1]}, face, 2);
164 addFacetToMap({v[0], v[2]}, face, 1);
165 addFacetToMap({v[1], v[2]}, face, 0);
166 }
167
173 template <int d = dimension>
174 std::enable_if_t<d == 3, void> createElement(
175 const std::vector<unsigned int>& v, const size_t insertionIndex,
176 const size_t domainMarker) {
177 auto&& v0 = vhs_[v[0]];
178 auto&& v1 = vhs_[v[1]];
179 auto&& v2 = vhs_[v[2]];
180 auto&& v3 = vhs_[v[3]];
181
182 // Create cell with vertices v0, v1, v2, v3
183 Element_handle cell = tr_.tds().create_cell(v0, v1, v2, v3);
184
185 // Set insertion index
186 cell->info().insertionIndex = insertionIndex;
187 cell->info().domainMarker = domainMarker;
188
189 // Set this cell in vertices v0, v1, v2, v3
190 v0->set_cell(cell);
191 v1->set_cell(cell);
192 v2->set_cell(cell);
193 v3->set_cell(cell);
194
195 // Add facets to neighbor map to obtain connectivity
196 addFacetToMap({v[0], v[1], v[2]}, cell, 3);
197 addFacetToMap({v[0], v[1], v[3]}, cell, 2);
198 addFacetToMap({v[0], v[2], v[3]}, cell, 1);
199 addFacetToMap({v[1], v[2], v[3]}, cell, 0);
200 }
201
210 void addFacetToMap(const std::vector<unsigned int>& v,
211 const Element_handle& element, const int fi) {
212 assert(v.size() == dimension);
213
214 // Make a set of the vertex indices
215 std::set<unsigned int> facetIndices(v.begin(), v.end());
216
217 // Try to insert this set into the neighborMap
218 auto entry = neighborMap.insert(
219 {facetIndices, std::pair<Element_handle, int>(element, fi)});
220
221 // If facetIndices was already in neighborMap, connect the neighbors and
222 // remove the entry
223 if (!entry.second) {
224 auto facet = entry.first->second;
225 Element_handle neighbor = facet.first;
226 int ni = facet.second;
227
228 element->set_neighbor(fi, neighbor);
229 neighbor->set_neighbor(ni, element);
230
231 neighborMap.erase(facetIndices);
232 }
233 }
234
235 public:
241 template <int d = dimension>
242 std::enable_if_t<d == 2, bool> isElement(
243 const std::vector<unsigned int>& v) const {
244 assert(v.size() == dimension + 1);
245 return tr_.is_face(vhs_[v[0]], vhs_[v[1]], vhs_[v[2]]);
246 }
247
253 template <int d = dimension>
254 std::enable_if_t<d == 3, bool> isElement(
255 const std::vector<unsigned int>& v) const {
256 assert(v.size() == dimension + 1);
257 Element_handle cell;
258 return tr_.is_cell(vhs_[v[0]], vhs_[v[1]], vhs_[v[2]], vhs_[v[3]], cell);
259 }
260
268 const std::vector<unsigned int>& vertices) {
269 assert(vertices.size() == dimension);
270
271 std::vector<std::size_t> sorted_vertices;
272 for (const auto& v : vertices)
273 sorted_vertices.push_back(vhs_[v]->info().id);
274 std::sort(sorted_vertices.begin(), sorted_vertices.end());
275
276 if (boundarySegments_.find(sorted_vertices) != boundarySegments_.end())
277 DUNE_THROW(GridError, "A boundary segment was inserted twice.");
278
279 boundarySegments_.insert(
280 std::make_pair(sorted_vertices, countBoundarySegments++));
281 }
282
284 const std::vector<unsigned int>& vertices,
285 const std::shared_ptr<BoundarySegment>& boundarySegment) {
286 DUNE_THROW(NotImplemented,
287 "insertBoundarySegments with Dune::BoundarySegment");
288 }
289
290 void insertInterfaceBoundarySegment(
291 const std::vector<unsigned int>& vertices) {
292 assert(vertices.size() == dimension - 1);
293
294 std::vector<std::size_t> sorted_vertices;
295 for (const auto& v : vertices)
296 sorted_vertices.push_back(vhs_[v]->info().id);
297 std::sort(sorted_vertices.begin(), sorted_vertices.end());
298
299 if (boundarySegments_.find(sorted_vertices) != boundarySegments_.end())
300 DUNE_THROW(GridError, "A boundary segment was inserted twice.");
301
302 interfaceBoundarySegments_.insert(
303 std::make_pair(sorted_vertices, countInterfaceBoundarySegments++));
304 }
305
312 void insertVertex(const WorldVector& pos) {
313 // Insert vertex
314 auto vh = tr_.tds().create_vertex();
315 vh->set_point(makePoint(pos));
316
317 // Store insertion index
318 vh->info().id = countVertices;
319 vh->info().idWasSet = true;
320
321 // Increase vertex counter
322 countVertices++;
323
324 // Store the inserted vertex handle for later use
325 vhs_.push_back(vh);
326 }
327
333 void insertInterface(const std::vector<unsigned int>& vertices,
334 const std::size_t marker = 1) {
335 assert(vertices.size() == dimension);
336
337 std::vector<std::size_t> sorted_vertices;
338 for (const auto& v : vertices)
339 sorted_vertices.push_back(vhs_[v]->info().id);
340 std::sort(sorted_vertices.begin(), sorted_vertices.end());
341 interfaceSegments_.insert(std::make_pair(sorted_vertices, marker));
342 }
343
348 unsigned int insertionIndex(const typename Codim<0>::Entity& entity) const {
349 return entity.impl().hostEntity()->info().insertionIndex;
350 }
351
356 unsigned int insertionIndex(
357 const typename Codim<dimension>::Entity& entity) const {
358 return entity.impl().hostEntity()->info().id;
359 }
360
365 unsigned int insertionIndex(
366 const typename Grid::LeafIntersection& intersection) const {
367 return intersection.impl().boundaryId();
368 }
369
371 const BoundarySegments& boundarySegments() const { return boundarySegments_; }
372
374 const BoundaryIds& boundaryIds() const { return boundaryIds_; }
375
377 void addBoundaryId(std::size_t boundarySegmentIndex, std::size_t boundaryId) {
378 boundaryIds_.insert(std::make_pair(boundarySegmentIndex, boundaryId));
379 }
380
389 std::unique_ptr<Grid> createGrid() {
390 // Sort elements by x-coordinate of center for partitioning
391 std::sort(elements_.begin(), elements_.end(),
392 [this](const auto& a, const auto& b) {
393 const auto& va = std::get<0>(a);
394 const auto& vb = std::get<0>(b);
395
396 double xa = 0.0;
397 double xb = 0.0;
398 for (int i = 0; i < dimensionworld + 1; ++i) {
399 xa += vhs_[va[i]]->point().x();
400 xb += vhs_[vb[i]]->point().x();
401 }
402 return xa < xb;
403 });
404
405 for (auto& t : elements_)
406 createElement(std::get<0>(t), std::get<1>(t), std::get<2>(t));
407
408 // Create the infinite cells (neighbors of boundary cells)
409 createInfiniteVertex();
410
411 // Create the infinite cells (neighbors of boundary cells)
412 createInfiniteCells();
413
414 // Remove interfaceSegments_ from boundarySegments_
415 for (const auto& interfaceSeg : interfaceSegments_)
416 boundarySegments_.erase(interfaceSeg.first);
417
418 // Mark interface vertices as isInterface
419 for (const auto& interfaceSeg : interfaceSegments_)
420 for (const auto& v : interfaceSeg.first.vt())
421 vhs_[v]->info().isInterface = true;
422
423 // Check if all inserted elements really exist in the triangulation
424 checkOccurenceOfAllElements();
425
426 // Return pointer to grid
427 return std::make_unique<Grid>(std::move(tr_), std::move(boundarySegments_),
428 std::move(interfaceBoundarySegments_),
429 std::move(boundaryIds_),
430 std::move(interfaceSegments_));
431 }
432
434 const std::vector<Vertex_handle>& vertexHandles() const { return vhs_; }
435
436 private:
440 void createInfiniteVertex() {
441 if (countElements > 0)
442 tr_.tds().set_dimension(dimension);
443 else
444 tr_.tds().set_dimension(0);
445
446 Vertex_handle infinite = tr_.tds().create_vertex();
447 infinite->info().id = std::size_t(-1);
448 tr_.set_infinite_vertex(infinite);
449 }
450
455 template <int d = dimension>
456 std::enable_if_t<d == 2, void> createInfiniteCells() {
457 // Iterate over all unique facets
458 for (const auto& entry : neighborMap) {
459 auto facet = entry.second;
460 Element_handle face = facet.first;
461 int fi = facet.second;
462
463 // Remove real boundary segments from interfaceSegments_
464 std::vector<std::size_t> vertices;
465 vertices.push_back(face->vertex((fi + 2) % 3)->info().id);
466 vertices.push_back(face->vertex((fi + 1) % 3)->info().id);
467 std::sort(vertices.begin(), vertices.end());
468
469 auto it = boundarySegments_.find(vertices);
470 if (it != boundarySegments_.end()) interfaceSegments_.erase(vertices);
471
472 // Create infinite face with correct orientation
473 Element_handle iface = tr_.tds().create_face(face->vertex((fi + 2) % 3),
474 face->vertex((fi + 1) % 3),
475 tr_.infinite_vertex());
476
477 tr_.infinite_vertex()->set_face(iface);
478
479 face->set_neighbor(fi, iface);
480 iface->set_neighbor(2, face);
481
482 // Map infinite neighbors
483 for (int i = 0; i < 2; ++i) {
484 std::set<std::size_t> vertexIndex({iface->vertex(i)->info().id});
485 auto entry = infiniteNeighborMap.insert(
486 {vertexIndex, std::pair<Element_handle, int>(iface, (i + 1) % 2)});
487
488 // If vertexIndex was already in map, connect neighbors and remove entry
489 if (!entry.second) {
490 auto pair = entry.first->second;
491 Element_handle neighbor = pair.first;
492 int ni = pair.second;
493
494 iface->set_neighbor((i + 1) % 2, neighbor);
495 neighbor->set_neighbor(ni, iface);
496
497 infiniteNeighborMap.erase(vertexIndex);
498 }
499 }
500 }
501
502 // Assert that all boundary facets are mapped
503 assert(infiniteNeighborMap.size() == 0);
504 }
505
510 template <int d = dimension>
511 std::enable_if_t<d == 3, void> createInfiniteCells() {
512 // Iterate over all unique facets
513 for (const auto& entry : neighborMap) {
514 auto facet = entry.second;
515 Element_handle cell = facet.first;
516 int fi = facet.second;
517
518 // Remove real boundary segments from interfaceSegments_
519 std::vector<std::size_t> vertices;
520 vertices.push_back(
521 cell->vertex((fi % 2 == 1) ? (fi + 2) & 3 : (fi + 1) & 3)->info().id);
522 vertices.push_back(
523 cell->vertex((fi % 2 == 1) ? (fi + 1) & 3 : (fi + 2) & 3)->info().id);
524 vertices.push_back(cell->vertex((fi + 3) & 3)->info().id);
525 std::sort(vertices.begin(), vertices.end());
526
527 auto it = boundarySegments_.find(vertices);
528 if (it != boundarySegments_.end()) interfaceSegments_.erase(vertices);
529
530 // Create infinite cell with correct orientation
531 Element_handle icell = tr_.tds().create_cell(
532 cell->vertex((fi % 2 == 1) ? (fi + 2) & 3 : (fi + 1) & 3),
533 cell->vertex((fi % 2 == 1) ? (fi + 1) & 3 : (fi + 2) & 3),
534 cell->vertex((fi + 3) & 3), tr_.infinite_vertex());
535
536 tr_.infinite_vertex()->set_cell(icell);
537
538 cell->set_neighbor(fi, icell);
539 icell->set_neighbor(3, cell);
540
541 // Map infinite neighbors
542 for (int i = 0; i < 3; ++i) {
543 std::set<std::size_t> edgeIndices(
544 {icell->vertex(i)->info().id,
545 icell->vertex((i + 1) % 3)->info().id});
546 auto entry = infiniteNeighborMap.insert(
547 {edgeIndices, std::pair<Element_handle, int>(icell, (i + 2) % 3)});
548
549 // If edgeIndices was already in map, connect neighbors and remove entry
550 if (!entry.second) {
551 auto pair = entry.first->second;
552 Element_handle neighbor = pair.first;
553 int ni = pair.second;
554
555 icell->set_neighbor((i + 2) % 3, neighbor);
556 neighbor->set_neighbor(ni, icell);
557
558 infiniteNeighborMap.erase(edgeIndices);
559 }
560 }
561 }
562
563 // Assert that all boundary facets are mapped
564 assert(infiniteNeighborMap.size() == 0);
565 }
566
569 void checkOccurenceOfAllElements() const {
570 for (const auto& v : elementVerticesList)
571 if (!isElement(v))
572 DUNE_THROW(InvalidStateException,
573 "Inserted element was not found in CGAL triangulation.");
574 }
575
577 HostGrid tr_;
578 std::vector<Vertex_handle> vhs_;
579 std::vector<Tuple> elements_;
580 BoundarySegments boundarySegments_, interfaceBoundarySegments_;
581 BoundaryIds boundaryIds_;
582 InterfaceSegments interfaceSegments_;
583 std::vector<std::vector<unsigned int> > elementVerticesList;
584 std::map<std::set<unsigned int>, std::pair<Element_handle, int> > neighborMap;
585 std::map<std::set<std::size_t>, std::pair<Element_handle, int> >
586 infiniteNeighborMap;
587 std::size_t countElements = 0, countVertices = 0;
588 std::size_t countBoundarySegments = 0, countInterfaceBoundarySegments = 0;
589};
590
591} // end namespace Dune
592
593#endif
specialization of the explicit GridFactory for MMesh
Definition: explicitgridfactory.hh:32
Dune::BoundarySegment< dimension, dimensionworld > BoundarySegment
type of a Dune boundary segment
Definition: explicitgridfactory.hh:53
const BoundarySegments & boundarySegments() const
returns the boundary segment to index map
Definition: explicitgridfactory.hh:371
const std::vector< Vertex_handle > & vertexHandles() const
return the vertex handles
Definition: explicitgridfactory.hh:434
FieldVector< ctype, dimensionworld > WorldVector
type of vector for world coordinates
Definition: explicitgridfactory.hh:48
static const bool supportsBoundaryIds
are boundary ids supported by this factory?
Definition: explicitgridfactory.hh:80
Grid::ctype ctype
type of (scalar) coordinates
Definition: explicitgridfactory.hh:38
FieldMatrix< ctype, dimensionworld, dimensionworld > WorldMatrix
type of matrix from world coordinates to world coordinates
Definition: explicitgridfactory.hh:50
void addBoundaryId(std::size_t boundarySegmentIndex, std::size_t boundaryId)
add a boundary id
Definition: explicitgridfactory.hh:377
std::enable_if_t< d==3, bool > isElement(const std::vector< unsigned int > &v) const
Returns if there is a cell with the given vertices in the triangulation3.
Definition: explicitgridfactory.hh:254
Grid::IdType IdType
type of an id
Definition: explicitgridfactory.hh:55
void insertVertex(const WorldVector &pos)
Insert a vertex into the macro grid.
Definition: explicitgridfactory.hh:312
void insertElement(const GeometryType &type, const std::vector< unsigned int > &v)
insert an element into the macro grid
Definition: explicitgridfactory.hh:92
virtual void insertBoundarySegment(const std::vector< unsigned int > &vertices)
insert a boundary segment into the macro grid
Definition: explicitgridfactory.hh:267
void insertInterface(const std::vector< unsigned int > &vertices, const std::size_t marker=1)
insert an interface into the macro grid
Definition: explicitgridfactory.hh:333
unsigned int insertionIndex(const typename Grid::LeafIntersection &intersection) const
return insertion index of boundary intersection
Definition: explicitgridfactory.hh:365
static const int dimension
dimension of the grid
Definition: explicitgridfactory.hh:43
void insertElement(const GeometryType &type, const std::vector< unsigned int > &v, const size_t domainMarker)
insert an element into the macro grid with a given domain marker
Definition: explicitgridfactory.hh:103
Grid::HostGridType HostGrid
type of the hostgrid
Definition: explicitgridfactory.hh:40
unsigned int insertionIndex(const typename Codim< 0 >::Entity &entity) const
return insertion index of entity
Definition: explicitgridfactory.hh:348
std::unordered_map< IdType, std::size_t > InterfaceSegments
type of the interface segment set
Definition: explicitgridfactory.hh:62
MMeshExplicitGridFactory()
Definition: explicitgridfactory.hh:85
unsigned int insertionIndex(const typename Codim< dimension >::Entity &entity) const
return insertion index of vertex entity
Definition: explicitgridfactory.hh:356
std::unique_ptr< Grid > createGrid()
finalize grid creation and hand over the grid
Definition: explicitgridfactory.hh:389
std::enable_if_t< d==2, bool > isElement(const std::vector< unsigned int > &v) const
Returns if there is a face with the given vertices in the triangulation2.
Definition: explicitgridfactory.hh:242
static const int dimensionworld
dimension of the world
Definition: explicitgridfactory.hh:45
std::unordered_map< IdType, std::size_t > BoundarySegments
type of the boundary segment id map
Definition: explicitgridfactory.hh:58
static const bool supportPeriodicity
the factory is not able to create periodic meshes
Definition: explicitgridfactory.hh:82
const BoundaryIds & boundaryIds() const
returns the boundary segment index to boundary id map
Definition: explicitgridfactory.hh:374
Some common helper methods.
The MMesh class.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Sep 5, 22:35, 2025)