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/boundarysegment.hh>
17#include <dune/grid/common/gridfactory.hh>
34 typedef GridFactoryInterface<Grid> Base;
38 typedef typename Grid::ctype
ctype;
50 typedef FieldMatrix<ctype, dimensionworld, dimensionworld>
WorldMatrix;
55 typedef typename Grid::IdType
IdType;
59 typedef std::unordered_map<std::size_t, std::size_t> BoundaryIds;
66 typedef typename Grid::template Codim<codim>::Entity Entity;
70 typedef typename HostGrid::Point Point;
71 typedef typename HostGrid::Vertex_handle Vertex_handle;
72 typedef typename Grid::template HostGridEntity<0> Element_handle;
74 using Tuple = std::tuple<std::vector<unsigned int>, std::size_t, std::size_t>;
76 using Base::insertElement;
93 const std::vector<unsigned int>& v) {
104 const std::vector<unsigned int>& v,
105 const size_t domainMarker) {
106 assert(type == GeometryTypes::simplex(
dimension));
111 storeElement(w, countElements, domainMarker);
117 elementVerticesList.push_back(w);
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));
132 template <
int d = dimension>
133 std::enable_if_t<d == 2, void> createElement(std::vector<unsigned int>& v,
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();
141 auto orientation = (p1.y() - p0.y()) * (p2.x() - p1.x()) -
142 (p1.x() - p0.x()) * (p2.y() - p1.y());
144 if (orientation > 0.0) std::swap(v[0], v[1]);
146 auto&& v0 = vhs_[v[0]];
147 auto&& v1 = vhs_[v[1]];
148 auto&& v2 = vhs_[v[2]];
151 Element_handle face = tr_.tds().create_face(v0, v1, v2);
155 face->info().domainMarker = domainMarker;
163 addFacetToMap({v[0], v[1]}, face, 2);
164 addFacetToMap({v[0], v[2]}, face, 1);
165 addFacetToMap({v[1], v[2]}, face, 0);
173 template <
int d = dimension>
174 std::enable_if_t<d == 3, void> createElement(
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]];
183 Element_handle cell = tr_.tds().create_cell(v0, v1, v2, v3);
187 cell->info().domainMarker = domainMarker;
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);
210 void addFacetToMap(
const std::vector<unsigned int>& v,
211 const Element_handle& element,
const int fi) {
215 std::set<unsigned int> facetIndices(v.begin(), v.end());
218 auto entry = neighborMap.insert(
219 {facetIndices, std::pair<Element_handle, int>(element, fi)});
224 auto facet = entry.first->second;
225 Element_handle neighbor = facet.first;
226 int ni = facet.second;
228 element->set_neighbor(fi, neighbor);
229 neighbor->set_neighbor(ni, element);
231 neighborMap.erase(facetIndices);
241 template <
int d = dimension>
243 const std::vector<unsigned int>& v)
const {
245 return tr_.is_face(vhs_[v[0]], vhs_[v[1]], vhs_[v[2]]);
253 template <
int d = dimension>
255 const std::vector<unsigned int>& v)
const {
258 return tr_.is_cell(vhs_[v[0]], vhs_[v[1]], vhs_[v[2]], vhs_[v[3]], cell);
268 const std::vector<unsigned int>& vertices) {
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());
276 if (boundarySegments_.find(sorted_vertices) != boundarySegments_.end())
277 DUNE_THROW(GridError,
"A boundary segment was inserted twice.");
279 boundarySegments_.insert(
280 std::make_pair(sorted_vertices, countBoundarySegments++));
284 const std::vector<unsigned int>& vertices,
285 const std::shared_ptr<BoundarySegment>& boundarySegment) {
286 DUNE_THROW(NotImplemented,
287 "insertBoundarySegments with Dune::BoundarySegment");
290 void insertInterfaceBoundarySegment(
291 const std::vector<unsigned int>& vertices) {
292 assert(vertices.size() ==
dimension - 1);
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());
299 if (boundarySegments_.find(sorted_vertices) != boundarySegments_.end())
300 DUNE_THROW(GridError,
"A boundary segment was inserted twice.");
302 interfaceBoundarySegments_.insert(
303 std::make_pair(sorted_vertices, countInterfaceBoundarySegments++));
314 auto vh = tr_.tds().create_vertex();
315 vh->set_point(makePoint(pos));
318 vh->info().id = countVertices;
319 vh->info().idWasSet =
true;
334 const std::size_t marker = 1) {
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));
349 return entity.impl().hostEntity()->info().insertionIndex;
357 const typename Codim<dimension>::Entity& entity)
const {
358 return entity.impl().hostEntity()->info().id;
366 const typename Grid::LeafIntersection& intersection)
const {
367 return intersection.impl().boundaryId();
377 void addBoundaryId(std::size_t boundarySegmentIndex, std::size_t boundaryId) {
378 boundaryIds_.insert(std::make_pair(boundarySegmentIndex, boundaryId));
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);
398 for (int i = 0; i < dimensionworld + 1; ++i) {
399 xa += vhs_[va[i]]->point().x();
400 xb += vhs_[vb[i]]->point().x();
405 for (
auto& t : elements_)
406 createElement(std::get<0>(t), std::get<1>(t), std::get<2>(t));
409 createInfiniteVertex();
412 createInfiniteCells();
415 for (
const auto& interfaceSeg : interfaceSegments_)
416 boundarySegments_.erase(interfaceSeg.first);
419 for (
const auto& interfaceSeg : interfaceSegments_)
420 for (
const auto& v : interfaceSeg.first.vt())
421 vhs_[v]->info().isInterface =
true;
424 checkOccurenceOfAllElements();
427 return std::make_unique<Grid>(std::move(tr_), std::move(boundarySegments_),
428 std::move(interfaceBoundarySegments_),
429 std::move(boundaryIds_),
430 std::move(interfaceSegments_));
440 void createInfiniteVertex() {
441 if (countElements > 0)
442 tr_.tds().set_dimension(dimension);
444 tr_.tds().set_dimension(0);
446 Vertex_handle infinite = tr_.tds().create_vertex();
447 infinite->info().id = std::size_t(-1);
448 tr_.set_infinite_vertex(infinite);
455 template <
int d = dimension>
456 std::enable_if_t<d == 2, void> createInfiniteCells() {
458 for (
const auto& entry : neighborMap) {
459 auto facet = entry.second;
460 Element_handle face = facet.first;
461 int fi = facet.second;
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());
469 auto it = boundarySegments_.find(vertices);
470 if (it != boundarySegments_.end()) interfaceSegments_.erase(vertices);
473 Element_handle iface = tr_.tds().create_face(face->vertex((fi + 2) % 3),
474 face->vertex((fi + 1) % 3),
475 tr_.infinite_vertex());
477 tr_.infinite_vertex()->set_face(iface);
479 face->set_neighbor(fi, iface);
480 iface->set_neighbor(2, face);
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)});
490 auto pair = entry.first->second;
491 Element_handle neighbor = pair.first;
492 int ni = pair.second;
494 iface->set_neighbor((i + 1) % 2, neighbor);
495 neighbor->set_neighbor(ni, iface);
497 infiniteNeighborMap.erase(vertexIndex);
503 assert(infiniteNeighborMap.size() == 0);
510 template <
int d = dimension>
511 std::enable_if_t<d == 3, void> createInfiniteCells() {
513 for (
const auto& entry : neighborMap) {
514 auto facet = entry.second;
515 Element_handle cell = facet.first;
516 int fi = facet.second;
519 std::vector<std::size_t> vertices;
521 cell->vertex((fi % 2 == 1) ? (fi + 2) & 3 : (fi + 1) & 3)->info().id);
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());
527 auto it = boundarySegments_.find(vertices);
528 if (it != boundarySegments_.end()) interfaceSegments_.erase(vertices);
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());
536 tr_.infinite_vertex()->set_cell(icell);
538 cell->set_neighbor(fi, icell);
539 icell->set_neighbor(3, cell);
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)});
551 auto pair = entry.first->second;
552 Element_handle neighbor = pair.first;
553 int ni = pair.second;
555 icell->set_neighbor((i + 2) % 3, neighbor);
556 neighbor->set_neighbor(ni, icell);
558 infiniteNeighborMap.erase(edgeIndices);
564 assert(infiniteNeighborMap.size() == 0);
569 void checkOccurenceOfAllElements()
const {
570 for (
const auto& v : elementVerticesList)
572 DUNE_THROW(InvalidStateException,
573 "Inserted element was not found in CGAL triangulation.");
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> >
587 std::size_t countElements = 0, countVertices = 0;
588 std::size_t countBoundarySegments = 0, countInterfaceBoundarySegments = 0;
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.