4#ifndef DUNE_MMESH_GRID_EXPLICITGRIDFACTORY_HH
5#define DUNE_MMESH_GRID_EXPLICITGRIDFACTORY_HH
15#include <dune/geometry/referenceelements.hh>
16#include <dune/grid/common/gridfactory.hh>
17#include <dune/grid/common/boundarysegment.hh>
32 template<
class Gr
id >
34 :
public GridFactoryInterface< Grid >
37 typedef GridFactoryInterface< Grid > Base;
41 typedef typename Grid::ctype
ctype;
53 typedef FieldMatrix< ctype, dimensionworld, dimensionworld >
WorldMatrix;
58 typedef typename Grid::IdType
IdType;
62 typedef std::unordered_map< std::size_t, std::size_t > BoundaryIds;
70 typedef typename Grid::template Codim< codim >::Entity Entity;
74 typedef typename HostGrid::Point Point;
75 typedef typename HostGrid::Vertex_handle Vertex_handle;
76 typedef typename Grid::template HostGridEntity<0> Element_handle;
78 using Tuple = std::tuple<std::vector< unsigned int >, std::size_t, std::size_t>;
80 using Base::insertElement;
99 const std::vector< unsigned int > &v )
111 const std::vector< unsigned int > &v,
112 const size_t domainMarker )
114 assert( type == GeometryTypes::simplex(
dimension) );
119 storeElement( w, countElements, domainMarker );
125 elementVerticesList.push_back( w );
130 void storeElement( std::vector< unsigned int >& v,
const size_t insertionIndex,
const size_t domainMarker )
132 elements_.push_back( std::make_tuple(v,
insertionIndex, domainMarker) );
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 )
144 auto& p0 = vhs_[v[0]]->point();
145 auto& p1 = vhs_[v[1]]->point();
146 auto& p2 = vhs_[v[2]]->point();
149 auto orientation = (p1.y() - p0.y()) * (p2.x() - p1.x()) - (p1.x() - p0.x()) * (p2.y() - p1.y());
151 if( orientation > 0.0 )
152 std::swap(v[0], v[1]);
154 auto&& v0 = vhs_[v[0]];
155 auto&& v1 = vhs_[v[1]];
156 auto&& v2 = vhs_[v[2]];
159 Element_handle face = tr_.tds().create_face(v0, v1, v2);
163 face->info().domainMarker = domainMarker;
171 addFacetToMap( { v[0], v[1] }, face, 2 );
172 addFacetToMap( { v[0], v[2] }, face, 1 );
173 addFacetToMap( { v[1], v[2] }, face, 0 );
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 )
185 auto&& v0 = vhs_[v[0]];
186 auto&& v1 = vhs_[v[1]];
187 auto&& v2 = vhs_[v[2]];
188 auto&& v3 = vhs_[v[3]];
191 Element_handle cell = tr_.tds().create_cell(v0, v1, v2, v3);
195 cell->info().domainMarker = domainMarker;
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 );
216 void addFacetToMap(
const std::vector< unsigned int >& v,
const Element_handle& element,
const int fi )
221 std::set< unsigned int > facetIndices ( v.begin(), v.end() );
224 auto entry = neighborMap.insert( { facetIndices, std::pair<Element_handle, int>( element, fi ) } );
229 auto facet = entry.first->second;
230 Element_handle neighbor = facet.first;
231 int ni = facet.second;
233 element->set_neighbor(fi, neighbor);
234 neighbor->set_neighbor(ni, element);
236 neighborMap.erase( facetIndices );
246 template<
int d = dimension >
247 std::enable_if_t< d == 2, bool >
251 return tr_.is_face( vhs_[v[0]], vhs_[v[1]], vhs_[v[2]] );
259 template<
int d = dimension >
260 std::enable_if_t< d == 3, bool >
265 return tr_.is_cell( vhs_[v[0]], vhs_[v[1]], vhs_[v[2]], vhs_[v[3]], cell );
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());
283 if( boundarySegments_.find( sorted_vertices ) != boundarySegments_.end() )
284 DUNE_THROW( GridError,
"A boundary segment was inserted twice." );
286 boundarySegments_.insert( std::make_pair( sorted_vertices, countBoundarySegments++ ) );
290 const std::shared_ptr< BoundarySegment >& boundarySegment )
292 DUNE_THROW( NotImplemented,
"insertBoundarySegments with Dune::BoundarySegment" );
295 void insertInterfaceBoundarySegment (
const std::vector< unsigned int >& vertices )
297 assert( vertices.size() ==
dimension-1 );
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());
304 if( boundarySegments_.find( sorted_vertices ) != boundarySegments_.end() )
305 DUNE_THROW( GridError,
"A boundary segment was inserted twice." );
307 interfaceBoundarySegments_.insert( std::make_pair( sorted_vertices, countInterfaceBoundarySegments++ ) );
319 auto vh = tr_.tds().create_vertex();
320 vh->set_point( makePoint( pos ) );
323 vh->info().id = countVertices;
324 vh->info().idWasSet =
true;
330 vhs_.push_back( vh );
338 void insertInterface (
const std::vector< unsigned int > &vertices,
const std::size_t marker = 1 )
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 ) );
355 return entity.impl().hostEntity()->info().insertionIndex;
362 unsigned int insertionIndex (
const typename Codim< dimension >::Entity &entity )
const
364 return entity.impl().hostEntity()->info().id;
371 unsigned int insertionIndex (
const typename Grid::LeafIntersection &intersection )
const
373 return intersection.impl().boundaryId();
379 return boundarySegments_;
389 void addBoundaryId( std::size_t boundarySegmentIndex, std::size_t boundaryId )
391 boundaryIds_.insert( std::make_pair( boundarySegmentIndex, boundaryId ) );
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);
411 for (int i = 0; i < dimensionworld+1; ++i)
413 xa += vhs_[va[i]]->point().x();
414 xb += vhs_[vb[i]]->point().x();
419 for (
auto& t : elements_)
420 createElement(std::get<0>(t), std::get<1>(t), std::get<2>(t));
423 createInfiniteVertex();
426 createInfiniteCells();
429 for(
const auto& interfaceSeg : interfaceSegments_ )
430 boundarySegments_.erase( interfaceSeg.first );
433 for(
const auto& interfaceSeg : interfaceSegments_ )
434 for(
const auto& v : interfaceSeg.first.vt() )
435 vhs_[v]->info().isInterface =
true;
438 checkOccurenceOfAllElements();
441 return std::make_unique<Grid> (
443 std::move(boundarySegments_),
444 std::move(interfaceBoundarySegments_),
445 std::move(boundaryIds_),
446 std::move(interfaceSegments_)
460 void createInfiniteVertex()
462 if( countElements > 0 )
463 tr_.tds().set_dimension(dimension);
465 tr_.tds().set_dimension(0);
467 Vertex_handle infinite = tr_.tds().create_vertex();
468 infinite->info().id = std::size_t(-1);
469 tr_.set_infinite_vertex(infinite);
476 template<
int d = dimension >
477 std::enable_if_t< d == 2, void >
478 createInfiniteCells()
481 for (
const auto& entry : neighborMap )
483 auto facet = entry.second;
484 Element_handle face = facet.first;
485 int fi = facet.second;
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());
493 auto it = boundarySegments_.find( vertices );
494 if( it != boundarySegments_.end() )
495 interfaceSegments_.erase( vertices );
499 Element_handle iface = tr_.tds().create_face(
500 face->vertex( (fi+2)%3 ),
501 face->vertex( (fi+1)%3 ),
502 tr_.infinite_vertex()
505 tr_.infinite_vertex()->set_face( iface );
507 face->set_neighbor(fi, iface);
508 iface->set_neighbor(2, face);
512 for(
int i = 0; i < 2; ++i )
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 ) } );
520 auto pair = entry.first->second;
521 Element_handle neighbor = pair.first;
522 int ni = pair.second;
524 iface->set_neighbor((i+1)%2, neighbor);
525 neighbor->set_neighbor(ni, iface);
527 infiniteNeighborMap.erase( vertexIndex );
533 assert( infiniteNeighborMap.size() == 0 );
540 template<
int d = dimension >
541 std::enable_if_t< d == 3, void >
542 createInfiniteCells()
545 for (
const auto& entry : neighborMap )
547 auto facet = entry.second;
548 Element_handle cell = facet.first;
549 int fi = facet.second;
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());
558 auto it = boundarySegments_.find( vertices );
559 if( it != boundarySegments_.end() )
560 interfaceSegments_.erase( vertices );
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()
571 tr_.infinite_vertex()->set_cell( icell );
573 cell->set_neighbor(fi, icell);
574 icell->set_neighbor(3, cell);
578 for(
int i = 0; i < 3; ++i )
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 ) } );
586 auto pair = entry.first->second;
587 Element_handle neighbor = pair.first;
588 int ni = pair.second;
590 icell->set_neighbor((i+2)%3, neighbor);
591 neighbor->set_neighbor(ni, icell);
593 infiniteNeighborMap.erase( edgeIndices );
599 assert( infiniteNeighborMap.size() == 0 );
604 void checkOccurenceOfAllElements()
const
606 for (
const auto& v : elementVerticesList )
607 if( !isElement( v ) )
608 DUNE_THROW( InvalidStateException,
"Inserted element was not found in CGAL triangulation." );
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;
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.