Loading [MathJax]/extensions/tex2jax.js

dune-mmesh (1.4)

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/gridfactory.hh>
17#include <dune/grid/common/boundarysegment.hh>
18
19// MMesh includes
22
23namespace Dune
24{
25
32 template< class Grid >
34 : public GridFactoryInterface< Grid >
35 {
37 typedef GridFactoryInterface< Grid > Base;
38
39 public:
41 typedef typename Grid::ctype ctype;
43 typedef typename Grid::HostGridType HostGrid;
44
46 static const int dimension = Grid::dimension;
48 static const int dimensionworld = Grid::dimensionworld;
49
51 typedef FieldVector< ctype, dimensionworld > WorldVector;
53 typedef FieldMatrix< ctype, dimensionworld, dimensionworld > WorldMatrix;
54
56 typedef Dune::BoundarySegment< dimension, dimensionworld > BoundarySegment;
58 typedef typename Grid::IdType IdType;
59
61 typedef std::unordered_map< IdType, std::size_t > BoundarySegments;
62 typedef std::unordered_map< std::size_t, std::size_t > BoundaryIds;
63
65 typedef std::unordered_map< IdType, std::size_t > InterfaceSegments;
66
67 template< int codim >
68 struct Codim
69 {
70 typedef typename Grid::template Codim< codim >::Entity Entity;
71 };
72
73 private:
74 typedef typename HostGrid::Point Point;
75 typedef typename HostGrid::Vertex_handle Vertex_handle;
76 typedef typename Grid::template HostGridEntity<0> Element_handle;
77
78 using Tuple = std::tuple<std::vector< unsigned int >, std::size_t, std::size_t>;
79
80 using Base::insertElement;
81 public:
83 static const bool supportsBoundaryIds = true;
85 static const bool supportPeriodicity = false;
86
89 {
90 tr_.tds().clear();
91 }
92
98 void insertElement ( const GeometryType &type,
99 const std::vector< unsigned int > &v )
100 {
101 insertElement( type, v, 0 );
102 }
103
110 void insertElement ( const GeometryType &type,
111 const std::vector< unsigned int > &v,
112 const size_t domainMarker )
113 {
114 assert( type == GeometryTypes::simplex(dimension) );
115 assert( v.size() == dimension+1 );
116 auto w = v;
117
118 // Create element
119 storeElement( w, countElements, domainMarker );
120
121 // Increase element count
122 countElements++;
123
124 // Store vertices to check occurence of element later
125 elementVerticesList.push_back( w );
126 };
127
128 private:
130 void storeElement( std::vector< unsigned int >& v, const size_t insertionIndex, const size_t domainMarker )
131 {
132 elements_.push_back( std::make_tuple(v, insertionIndex, domainMarker) );
133 }
134
140 template< int d = dimension >
141 std::enable_if_t< d == 2, void >
142 createElement( std::vector< unsigned int >& v, const size_t insertionIndex, const size_t domainMarker )
143 {
144 auto& p0 = vhs_[v[0]]->point();
145 auto& p1 = vhs_[v[1]]->point();
146 auto& p2 = vhs_[v[2]]->point();
147
148 // Check orientation of vertices
149 auto orientation = (p1.y() - p0.y()) * (p2.x() - p1.x()) - (p1.x() - p0.x()) * (p2.y() - p1.y());
150 // if clockwise, swap two vertices
151 if( orientation > 0.0 )
152 std::swap(v[0], v[1]);
153
154 auto&& v0 = vhs_[v[0]];
155 auto&& v1 = vhs_[v[1]];
156 auto&& v2 = vhs_[v[2]];
157
158 // Create face with vertices v0, v1, v2
159 Element_handle face = tr_.tds().create_face(v0, v1, v2);
160
161 // Set insertion index
162 face->info().insertionIndex = insertionIndex;
163 face->info().domainMarker = domainMarker;
164
165 // Set this face in vertices v0, v1, v2
166 v0->set_face(face);
167 v1->set_face(face);
168 v2->set_face(face);
169
170 // Add facets to neighbor map to obtain connectivity
171 addFacetToMap( { v[0], v[1] }, face, 2 );
172 addFacetToMap( { v[0], v[2] }, face, 1 );
173 addFacetToMap( { v[1], v[2] }, face, 0 );
174 }
175
181 template< int d = dimension >
182 std::enable_if_t< d == 3, void >
183 createElement( const std::vector< unsigned int >& v, const size_t insertionIndex, const size_t domainMarker )
184 {
185 auto&& v0 = vhs_[v[0]];
186 auto&& v1 = vhs_[v[1]];
187 auto&& v2 = vhs_[v[2]];
188 auto&& v3 = vhs_[v[3]];
189
190 // Create cell with vertices v0, v1, v2, v3
191 Element_handle cell = tr_.tds().create_cell(v0, v1, v2, v3);
192
193 // Set insertion index
194 cell->info().insertionIndex = insertionIndex;
195 cell->info().domainMarker = domainMarker;
196
197 // Set this cell in vertices v0, v1, v2, v3
198 v0->set_cell(cell);
199 v1->set_cell(cell);
200 v2->set_cell(cell);
201 v3->set_cell(cell);
202
203 // Add facets to neighbor map to obtain connectivity
204 addFacetToMap( { v[0], v[1], v[2] }, cell, 3 );
205 addFacetToMap( { v[0], v[1], v[3] }, cell, 2 );
206 addFacetToMap( { v[0], v[2], v[3] }, cell, 1 );
207 addFacetToMap( { v[1], v[2], v[3] }, cell, 0 );
208 }
209
216 void addFacetToMap( const std::vector< unsigned int >& v, const Element_handle& element, const int fi )
217 {
218 assert( v.size() == dimension );
219
220 // Make a set of the vertex indices
221 std::set< unsigned int > facetIndices ( v.begin(), v.end() );
222
223 // Try to insert this set into the neighborMap
224 auto entry = neighborMap.insert( { facetIndices, std::pair<Element_handle, int>( element, fi ) } );
225
226 // If facetIndices was already in neighborMap, connect the neighbors and remove the entry
227 if( !entry.second )
228 {
229 auto facet = entry.first->second;
230 Element_handle neighbor = facet.first;
231 int ni = facet.second;
232
233 element->set_neighbor(fi, neighbor);
234 neighbor->set_neighbor(ni, element);
235
236 neighborMap.erase( facetIndices );
237 }
238 }
239
240 public:
246 template< int d = dimension >
247 std::enable_if_t< d == 2, bool >
248 isElement( const std::vector< unsigned int >& v ) const
249 {
250 assert( v.size() == dimension+1 );
251 return tr_.is_face( vhs_[v[0]], vhs_[v[1]], vhs_[v[2]] );
252 }
253
259 template< int d = dimension >
260 std::enable_if_t< d == 3, bool >
261 isElement( const std::vector< unsigned int >& v ) const
262 {
263 assert( v.size() == dimension+1 );
264 Element_handle cell;
265 return tr_.is_cell( vhs_[v[0]], vhs_[v[1]], vhs_[v[2]], vhs_[v[3]], cell );
266 }
267
274 virtual void insertBoundarySegment ( const std::vector< unsigned int >& vertices )
275 {
276 assert( vertices.size() == dimension );
277
278 std::vector< std::size_t > sorted_vertices;
279 for ( const auto& v : vertices )
280 sorted_vertices.push_back( vhs_[v]->info().id );
281 std::sort(sorted_vertices.begin(), sorted_vertices.end());
282
283 if( boundarySegments_.find( sorted_vertices ) != boundarySegments_.end() )
284 DUNE_THROW( GridError, "A boundary segment was inserted twice." );
285
286 boundarySegments_.insert( std::make_pair( sorted_vertices, countBoundarySegments++ ) );
287 }
288
289 void insertBoundarySegment ( const std::vector< unsigned int >& vertices,
290 const std::shared_ptr< BoundarySegment >& boundarySegment )
291 {
292 DUNE_THROW( NotImplemented, "insertBoundarySegments with Dune::BoundarySegment" );
293 }
294
295 void insertInterfaceBoundarySegment ( const std::vector< unsigned int >& vertices )
296 {
297 assert( vertices.size() == dimension-1 );
298
299 std::vector< std::size_t > sorted_vertices;
300 for ( const auto& v : vertices )
301 sorted_vertices.push_back( vhs_[v]->info().id );
302 std::sort(sorted_vertices.begin(), sorted_vertices.end());
303
304 if( boundarySegments_.find( sorted_vertices ) != boundarySegments_.end() )
305 DUNE_THROW( GridError, "A boundary segment was inserted twice." );
306
307 interfaceBoundarySegments_.insert( std::make_pair( sorted_vertices, countInterfaceBoundarySegments++ ) );
308 }
309
316 void insertVertex ( const WorldVector &pos )
317 {
318 // Insert vertex
319 auto vh = tr_.tds().create_vertex();
320 vh->set_point( makePoint( pos ) );
321
322 // Store insertion index
323 vh->info().id = countVertices;
324 vh->info().idWasSet = true;
325
326 // Increase vertex counter
327 countVertices++;
328
329 // Store the inserted vertex handle for later use
330 vhs_.push_back( vh );
331 }
332
338 void insertInterface ( const std::vector< unsigned int > &vertices, const std::size_t marker = 1 )
339 {
340 assert( vertices.size() == dimension );
341
342 std::vector< std::size_t > sorted_vertices;
343 for( const auto& v : vertices )
344 sorted_vertices.push_back( vhs_[v]->info().id );
345 std::sort(sorted_vertices.begin(), sorted_vertices.end());
346 interfaceSegments_.insert( std::make_pair( sorted_vertices, marker ) );
347 }
348
353 unsigned int insertionIndex ( const typename Codim<0>::Entity &entity ) const
354 {
355 return entity.impl().hostEntity()->info().insertionIndex;
356 }
357
362 unsigned int insertionIndex ( const typename Codim< dimension >::Entity &entity ) const
363 {
364 return entity.impl().hostEntity()->info().id;
365 }
366
371 unsigned int insertionIndex ( const typename Grid::LeafIntersection &intersection ) const
372 {
373 return intersection.impl().boundaryId();
374 }
375
378 {
379 return boundarySegments_;
380 }
381
383 const BoundaryIds& boundaryIds() const
384 {
385 return boundaryIds_;
386 }
387
389 void addBoundaryId( std::size_t boundarySegmentIndex, std::size_t boundaryId )
390 {
391 boundaryIds_.insert( std::make_pair( boundarySegmentIndex, boundaryId ) );
392 }
393
402 std::unique_ptr<Grid> createGrid ()
403 {
404 // Sort elements by x-coordinate of center for partitioning
405 std::sort(elements_.begin(), elements_.end(), [this](const auto& a, const auto& b){
406 const auto& va = std::get<0>(a);
407 const auto& vb = std::get<0>(b);
408
409 double xa = 0.0;
410 double xb = 0.0;
411 for (int i = 0; i < dimensionworld+1; ++i)
412 {
413 xa += vhs_[va[i]]->point().x();
414 xb += vhs_[vb[i]]->point().x();
415 }
416 return xa < xb;
417 });
418
419 for (auto& t : elements_)
420 createElement(std::get<0>(t), std::get<1>(t), std::get<2>(t));
421
422 // Create the infinite cells (neighbors of boundary cells)
423 createInfiniteVertex();
424
425 // Create the infinite cells (neighbors of boundary cells)
426 createInfiniteCells();
427
428 // Remove interfaceSegments_ from boundarySegments_
429 for( const auto& interfaceSeg : interfaceSegments_ )
430 boundarySegments_.erase( interfaceSeg.first );
431
432 // Mark interface vertices as isInterface
433 for( const auto& interfaceSeg : interfaceSegments_ )
434 for( const auto& v : interfaceSeg.first.vt() )
435 vhs_[v]->info().isInterface = true;
436
437 // Check if all inserted elements really exist in the triangulation
438 checkOccurenceOfAllElements();
439
440 // Return pointer to grid
441 return std::make_unique<Grid> (
442 std::move(tr_),
443 std::move(boundarySegments_),
444 std::move(interfaceBoundarySegments_),
445 std::move(boundaryIds_),
446 std::move(interfaceSegments_)
447 );
448 }
449
451 const std::vector< Vertex_handle >& vertexHandles () const
452 {
453 return vhs_;
454 }
455
456 private:
460 void createInfiniteVertex()
461 {
462 if( countElements > 0 )
463 tr_.tds().set_dimension(dimension);
464 else
465 tr_.tds().set_dimension(0);
466
467 Vertex_handle infinite = tr_.tds().create_vertex();
468 infinite->info().id = std::size_t(-1);
469 tr_.set_infinite_vertex(infinite);
470 }
471
476 template< int d = dimension >
477 std::enable_if_t< d == 2, void >
478 createInfiniteCells()
479 {
480 // Iterate over all unique facets
481 for ( const auto& entry : neighborMap )
482 {
483 auto facet = entry.second;
484 Element_handle face = facet.first;
485 int fi = facet.second;
486
487 // Remove real boundary segments from interfaceSegments_
488 std::vector< std::size_t > vertices;
489 vertices.push_back( face->vertex( (fi+2)%3 )->info().id );
490 vertices.push_back( face->vertex( (fi+1)%3 )->info().id );
491 std::sort(vertices.begin(), vertices.end());
492
493 auto it = boundarySegments_.find( vertices );
494 if( it != boundarySegments_.end() )
495 interfaceSegments_.erase( vertices );
496
497
498 // Create infinite face with correct orientation
499 Element_handle iface = tr_.tds().create_face(
500 face->vertex( (fi+2)%3 ),
501 face->vertex( (fi+1)%3 ),
502 tr_.infinite_vertex()
503 );
504
505 tr_.infinite_vertex()->set_face( iface );
506
507 face->set_neighbor(fi, iface);
508 iface->set_neighbor(2, face);
509
510
511 // Map infinite neighbors
512 for( int i = 0; i < 2; ++i )
513 {
514 std::set< std::size_t > vertexIndex ( { iface->vertex(i)->info().id } );
515 auto entry = infiniteNeighborMap.insert( { vertexIndex, std::pair<Element_handle, int>( iface, (i+1)%2 ) } );
516
517 // If vertexIndex was already in map, connect neighbors and remove entry
518 if( !entry.second )
519 {
520 auto pair = entry.first->second;
521 Element_handle neighbor = pair.first;
522 int ni = pair.second;
523
524 iface->set_neighbor((i+1)%2, neighbor);
525 neighbor->set_neighbor(ni, iface);
526
527 infiniteNeighborMap.erase( vertexIndex );
528 }
529 }
530 }
531
532 // Assert that all boundary facets are mapped
533 assert( infiniteNeighborMap.size() == 0 );
534 }
535
540 template< int d = dimension >
541 std::enable_if_t< d == 3, void >
542 createInfiniteCells()
543 {
544 // Iterate over all unique facets
545 for ( const auto& entry : neighborMap )
546 {
547 auto facet = entry.second;
548 Element_handle cell = facet.first;
549 int fi = facet.second;
550
551 // Remove real boundary segments from interfaceSegments_
552 std::vector< std::size_t > vertices;
553 vertices.push_back( cell->vertex( (fi%2==1) ? (fi+2)&3 : (fi+1)&3 )->info().id );
554 vertices.push_back( cell->vertex( (fi%2==1) ? (fi+1)&3 : (fi+2)&3 )->info().id );
555 vertices.push_back( cell->vertex( (fi+3)&3 )->info().id );
556 std::sort(vertices.begin(), vertices.end());
557
558 auto it = boundarySegments_.find( vertices );
559 if( it != boundarySegments_.end() )
560 interfaceSegments_.erase( vertices );
561
562
563 // Create infinite cell with correct orientation
564 Element_handle icell = tr_.tds().create_cell(
565 cell->vertex( (fi%2==1) ? (fi+2)&3 : (fi+1)&3 ),
566 cell->vertex( (fi%2==1) ? (fi+1)&3 : (fi+2)&3 ),
567 cell->vertex((fi+3)&3),
568 tr_.infinite_vertex()
569 );
570
571 tr_.infinite_vertex()->set_cell( icell );
572
573 cell->set_neighbor(fi, icell);
574 icell->set_neighbor(3, cell);
575
576
577 // Map infinite neighbors
578 for( int i = 0; i < 3; ++i )
579 {
580 std::set< std::size_t > edgeIndices ( { icell->vertex(i)->info().id, icell->vertex((i+1)%3)->info().id } );
581 auto entry = infiniteNeighborMap.insert( { edgeIndices, std::pair<Element_handle, int>( icell, (i+2)%3 ) } );
582
583 // If edgeIndices was already in map, connect neighbors and remove entry
584 if( !entry.second )
585 {
586 auto pair = entry.first->second;
587 Element_handle neighbor = pair.first;
588 int ni = pair.second;
589
590 icell->set_neighbor((i+2)%3, neighbor);
591 neighbor->set_neighbor(ni, icell);
592
593 infiniteNeighborMap.erase( edgeIndices );
594 }
595 }
596 }
597
598 // Assert that all boundary facets are mapped
599 assert( infiniteNeighborMap.size() == 0 );
600 }
601
604 void checkOccurenceOfAllElements() const
605 {
606 for ( const auto& v : elementVerticesList )
607 if( !isElement( v ) )
608 DUNE_THROW( InvalidStateException, "Inserted element was not found in CGAL triangulation." );
609 }
610
612 HostGrid tr_;
613 std::vector< Vertex_handle > vhs_;
614 std::vector<Tuple> elements_;
615 BoundarySegments boundarySegments_, interfaceBoundarySegments_;
616 BoundaryIds boundaryIds_;
617 InterfaceSegments interfaceSegments_;
618 std::vector< std::vector< unsigned int > > elementVerticesList;
619 std::map< std::set< unsigned int >, std::pair<Element_handle, int> > neighborMap;
620 std::map< std::set< std::size_t >, std::pair<Element_handle, int> > infiniteNeighborMap;
621 std::size_t countElements = 0, countVertices = 0;
622 std::size_t countBoundarySegments = 0, countInterfaceBoundarySegments = 0;
623 };
624
625} // end namespace Dune
626
627#endif
specialization of the explicit GridFactory for MMesh
Definition: explicitgridfactory.hh:35
std::unordered_map< IdType, std::size_t > InterfaceSegments
type of the interface segment set
Definition: explicitgridfactory.hh:65
const BoundarySegments & boundarySegments() const
returns the boundary segment to index map
Definition: explicitgridfactory.hh:377
Dune::BoundarySegment< dimension, dimensionworld > BoundarySegment
type of a Dune boundary segment
Definition: explicitgridfactory.hh:56
const std::vector< Vertex_handle > & vertexHandles() const
return the vertex handles
Definition: explicitgridfactory.hh:451
static const bool supportsBoundaryIds
are boundary ids supported by this factory?
Definition: explicitgridfactory.hh:83
Grid::ctype ctype
type of (scalar) coordinates
Definition: explicitgridfactory.hh:41
void addBoundaryId(std::size_t boundarySegmentIndex, std::size_t boundaryId)
add a boundary id
Definition: explicitgridfactory.hh:389
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 triangulation 3.
Definition: explicitgridfactory.hh:261
FieldVector< ctype, dimensionworld > WorldVector
type of vector for world coordinates
Definition: explicitgridfactory.hh:51
Grid::IdType IdType
type of an id
Definition: explicitgridfactory.hh:58
void insertVertex(const WorldVector &pos)
Insert a vertex into the macro grid.
Definition: explicitgridfactory.hh:316
void insertElement(const GeometryType &type, const std::vector< unsigned int > &v)
insert an element into the macro grid
Definition: explicitgridfactory.hh:98
virtual void insertBoundarySegment(const std::vector< unsigned int > &vertices)
insert a boundary segment into the macro grid
Definition: explicitgridfactory.hh:274
void insertInterface(const std::vector< unsigned int > &vertices, const std::size_t marker=1)
insert an interface into the macro grid
Definition: explicitgridfactory.hh:338
unsigned int insertionIndex(const typename Grid::LeafIntersection &intersection) const
return insertion index of boundary intersection
Definition: explicitgridfactory.hh:371
static const int dimension
dimension of the grid
Definition: explicitgridfactory.hh:46
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:110
Grid::HostGridType HostGrid
type of the hostgrid
Definition: explicitgridfactory.hh:43
unsigned int insertionIndex(const typename Codim< 0 >::Entity &entity) const
return insertion index of entity
Definition: explicitgridfactory.hh:353
MMeshExplicitGridFactory()
Definition: explicitgridfactory.hh:88
unsigned int insertionIndex(const typename Codim< dimension >::Entity &entity) const
return insertion index of vertex entity
Definition: explicitgridfactory.hh:362
std::unique_ptr< Grid > createGrid()
finalize grid creation and hand over the grid
Definition: explicitgridfactory.hh:402
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 triangulation 2.
Definition: explicitgridfactory.hh:248
static const int dimensionworld
dimension of the world
Definition: explicitgridfactory.hh:48
std::unordered_map< IdType, std::size_t > BoundarySegments
type of the boundary segment id map
Definition: explicitgridfactory.hh:61
FieldMatrix< ctype, dimensionworld, dimensionworld > WorldMatrix
type of matrix from world coordinates to world coordinates
Definition: explicitgridfactory.hh:53
static const bool supportPeriodicity
the factory is not able to create periodic meshes
Definition: explicitgridfactory.hh:85
const BoundaryIds & boundaryIds() const
returns the boundary segment index to boundary id map
Definition: explicitgridfactory.hh:383
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 (Apr 13, 22:42, 2025)