Dune Core Modules (2.11.0)

foamgridfactory.hh
Go to the documentation of this file.
1// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set ts=8 sw=4 et sts=4:
3#ifndef DUNE_FOAMGRID_FACTORY_HH
4#define DUNE_FOAMGRID_FACTORY_HH
5
11#include <vector>
12#include <memory>
13#include <unordered_map>
14#include <functional>
15
17#include <dune/common/hash.hh>
18
21
22namespace Dune {
23
26template <int dimgrid, int dimworld, class ct>
28 : public GridFactoryInterface<FoamGrid<dimgrid, dimworld, ct> >
29 {
31 using ctype = ct;
32
33 public:
34
35 using GridPtrType = std::unique_ptr<FoamGrid<dimgrid, dimworld,ctype>>;
36
39 : factoryOwnsGrid_(true)
40 {
42 grid_->entityImps_.resize(1);
43 }
44
55 : factoryOwnsGrid_(false)
56 {
57 grid_ = grid;
58 grid_->entityImps_.resize(1);
59 }
60
62 ~GridFactoryBase() override {
63 if (grid_ && factoryOwnsGrid_)
64 delete grid_;
65 }
66
68 void insertVertex(const FieldVector<ctype,dimworld>& pos) override {
69 std::get<0>(grid_->entityImps_[0]).emplace_back(
70 0, // level
71 pos, // position
72 grid_->getNextFreeId()
73 );
74 vertexArray_.push_back(&*std::get<0>(grid_->entityImps_[0]).rbegin());
75 }
76
79 unsigned int
81 {
82 return entity.impl().target_->leafIndex_;
83 }
84
87 unsigned int
89 {
90 return vertex.impl().target_->leafIndex_;
91 }
92
95 unsigned int
96 insertionIndex(const typename FoamGrid<dimgrid, dimworld, ctype>::LeafIntersection& intersection) const override
97 {
98 return intersection.boundarySegmentIndex();
99 }
100
101 protected:
102
103 // Pointer to the grid being built
105
106 // True if the factory allocated the grid itself, false if the
107 // grid was handed over from the outside
108 bool factoryOwnsGrid_;
109
111 std::vector<FoamGridEntityImp<0, dimgrid, dimworld, ctype>*> vertexArray_;
112
114 unsigned int boundarySegmentCounter_ = 0;
115 };
116
117template <int dimgrid, int dimworld, class ct>
118 class GridFactory<FoamGrid<dimgrid, dimworld, ct> >
119 : public GridFactoryBase<dimgrid, dimworld, ct>
120 {};
121
124template <int dimworld, class ct>
125 class GridFactory<FoamGrid<1, dimworld, ct> >
126 : public GridFactoryBase<1, dimworld, ct>
127 {
129 enum {dimgrid = 1};
130
132 using ctype = ct;
133
135 template<int mydim>
137
138 using GridPtrType = typename GridFactoryBase<1, dimworld, ct>::GridPtrType;
139
140 public:
141
142 GridFactory() {}
143
146 {}
147
151 void insertBoundarySegment(const std::vector<unsigned int>& vertices) override
152 {
153 boundarySegmentIndices_[ vertices[0] ] = this->boundarySegmentCounter_++;
154 }
155
159 void insertBoundarySegment(const std::vector<unsigned int>& vertices,
160 const std::shared_ptr<BoundarySegment<dimgrid, dimworld> >& boundarySegment) override
161 {
162 DUNE_THROW(Dune::NotImplemented, "Parameterized boundary segments are not implemented");
163 }
164
167 bool wasInserted( const typename FoamGrid<dimgrid, dimworld, ctype>::LeafIntersection &intersection ) const override
168 {
169 if ( !intersection.boundary() || intersection.inside().level() != 0 )
170 return false;
171
172 const auto& vertex = intersection.inside().template subEntity<1>(intersection.indexInInside());
173 const auto& it = boundarySegmentIndices_.find( this->insertionIndex(vertex) );
174 return (it != boundarySegmentIndices_.end());
175 }
176
181 void insertElement(const GeometryType& type,
182 const std::vector<unsigned int>& vertices) override
183 {
184 assert(type.isLine());
185 // insert new element
186 std::get<1>(this->grid_->entityImps_[0]).emplace_back(
187 this->vertexArray_[vertices[0]],
188 this->vertexArray_[vertices[1]],
189 0, // level
190 this->grid_->getNextFreeId()
191 );
192 }
193
199 void insertElement(const GeometryType& type,
200 const std::vector<unsigned int>& vertices,
201 std::function<FieldVector<ctype,dimworld>(FieldVector<ctype,dimgrid>)> elementParametrization)
202 override
203 {
204 assert(type.isLine());
205 EntityImp<1> newElement(this->vertexArray_[vertices[0]],
206 this->vertexArray_[vertices[1]],
207 0, // level
208 this->grid_->getNextFreeId());
209
210 newElement.elementParametrization_ = elementParametrization;
211 std::get<dimgrid>(this->grid_->entityImps_[0]).push_back(newElement);
212 }
213
218 GridPtrType createGrid() override
219 {
220 // Prevent a crash when this method is called twice in a row
221 // You never know who may do this...
222 if (this->grid_==nullptr)
223 return nullptr;
224
225 // make facets (vertices) know about the element
226 for (auto& element : std::get<dimgrid>(this->grid_->entityImps_[0]))
227 {
228 element.vertex_[0]->elements_.push_back(&element);
229 element.vertex_[1]->elements_.push_back(&element);
230 }
231
232 // Create the index sets
233 this->grid_->setIndices();
234
235 // ////////////////////////////////////////////////
236 // Set the boundary ids
237 // ////////////////////////////////////////////////
238
239 for (auto& facet : std::get<0>(this->grid_->entityImps_[0]))
240 {
241 if (facet.elements_.size() == 1) // if boundary facet
242 {
243 const auto it = boundarySegmentIndices_.find( facet.vertex_[0]->leafIndex_ );
244 if (it != boundarySegmentIndices_.end())
245 facet.boundarySegmentIndex_ = it->second;
246 else
247 facet.boundarySegmentIndex_ = this->boundarySegmentCounter_++;
248 }
249 }
250
251 // ////////////////////////////////////////////////
252 // Hand over the new grid
253 // ////////////////////////////////////////////////
254
256 tmp->numBoundarySegments_ = this->boundarySegmentCounter_;
257 this->grid_ = nullptr;
258 return GridPtrType(tmp);
259 }
260
261 private:
262 std::unordered_map<unsigned int, unsigned int> boundarySegmentIndices_;
263 };
264
267template <int dimworld, class ct>
268 class GridFactory<FoamGrid<2, dimworld, ct> >
269 : public GridFactoryBase<2, dimworld, ct>
270 {
272 enum {dimgrid = 2};
273
275 using ctype = ct;
276
278 template<int mydim>
280
281 using GridPtrType = typename GridFactoryBase<2, dimworld, ct>::GridPtrType;
282
283 public:
284
285 GridFactory() {}
286
289 {}
290
294 void insertBoundarySegment(const std::vector<unsigned int>& vertices) override
295 {
296 std::array<unsigned int, 2> vertexIndices {{ vertices[0], vertices[1] }};
297
298 // sort the indices
299 if ( vertexIndices[0] > vertexIndices[1] )
300 std::swap( vertexIndices[0], vertexIndices[1] );
301
302 boundarySegmentIndices_[ vertexIndices ] = this->boundarySegmentCounter_++;
303 }
304
308 void insertBoundarySegment(const std::vector<unsigned int>& vertices,
309 const std::shared_ptr<BoundarySegment<dimgrid, dimworld> >& boundarySegment) override
310 {
311 DUNE_THROW(Dune::NotImplemented, "Parameterized boundary segments are not implemented");
312 }
313
316 bool wasInserted( const typename FoamGrid<dimgrid, dimworld, ctype>::LeafIntersection &intersection ) const override
317 {
318 if ( !intersection.boundary() || intersection.inside().level() != 0 )
319 return false;
320
321 // Get the vertices of the intersection
322 const auto refElement = ReferenceElements<ctype, dimgrid>::general(intersection.inside().type());
323
324 const int subIdx0 = refElement.subEntity(intersection.indexInInside(), 1, /*idx*/0, dimgrid);
325 const auto vertex0 = intersection.inside().template subEntity<2>( subIdx0 );
326 const int subIdx1 = refElement.subEntity(intersection.indexInInside(), 1, /*idx*/1, dimgrid);
327 const auto vertex1 = intersection.inside().template subEntity<2>( subIdx1 );
328
329 std::array<unsigned int, 2> vertexIndices {{
330 this->insertionIndex( vertex0 ),
331 this->insertionIndex( vertex1 )
332 }};
333
334 // sort the indices
335 if ( vertexIndices[0] > vertexIndices[1] )
336 std::swap( vertexIndices[0], vertexIndices[1] );
337
338 const auto& it = boundarySegmentIndices_.find( vertexIndices );
339 return (it != boundarySegmentIndices_.end());
340 }
341
346 void insertElement(const GeometryType& type,
347 const std::vector<unsigned int>& vertices) override {
348
349 assert(type.isTriangle());
350
351 EntityImp<dimgrid> newElement(/*level=*/0, this->grid_->getNextFreeId());
352 newElement.vertex_[0] = this->vertexArray_[vertices[0]];
353 newElement.vertex_[1] = this->vertexArray_[vertices[1]];
354 newElement.vertex_[2] = this->vertexArray_[vertices[2]];
355
356 std::get<dimgrid>(this->grid_->entityImps_[0]).push_back(newElement);
357 }
358
364 void insertElement(const GeometryType& type,
365 const std::vector<unsigned int>& vertices,
366 std::function<FieldVector<ctype,dimworld>(FieldVector<ctype,dimgrid>)> elementParametrization)
367 override
368 {
369 assert(type.isTriangle());
370 EntityImp<dimgrid> newElement(/*level=*/0, this->grid_->getNextFreeId());
371 newElement.vertex_[0] = this->vertexArray_[vertices[0]];
372 newElement.vertex_[1] = this->vertexArray_[vertices[1]];
373 newElement.vertex_[2] = this->vertexArray_[vertices[2]];
374 newElement.elementParametrization_ = elementParametrization;
375 std::get<dimgrid>(this->grid_->entityImps_[0]).push_back(newElement);
376 }
377
381 GridPtrType createGrid() override
382 {
383 // Prevent a crash when this method is called twice in a row
384 // You never know who may do this...
385 if (this->grid_==nullptr)
386 return nullptr;
387
388 // ////////////////////////////////////////////////////
389 // Create the edges
390 // ////////////////////////////////////////////////////
391
392 // For fast retrieval: a map from pairs of vertices to the edge that connects them
393 std::unordered_map<std::pair<const EntityImp<0>*, const EntityImp<0>*>, EntityImp<1>*,
394 HashPair<const EntityImp<0>*>> edgeMap;
395 for (auto& element : std::get<dimgrid>(this->grid_->entityImps_[0]))
396 {
397 const auto refElement = ReferenceElements<ctype, dimgrid>::general(element.type());
398
399 // Loop over all edges of this element
400 for (std::size_t i=0; i<element.facet_.size(); ++i)
401 {
402 // get pointer to the edge (insert edge if it's not in the entity list yet)
403 auto edge = [&](){
404 // Get two vertices of the potential edge
405 auto v0 = element.vertex_[refElement.subEntity(i, 1, 0, 2)];
406 auto v1 = element.vertex_[refElement.subEntity(i, 1, 1, 2)];
407 // sort pointers
408 if ( v0 > v1 )
409 std::swap( v0, v1 );
410
411 // see if the edge was already inserted
412 // the pointer pair hash is symmetric so we don't have to check for pair(v1,v0)
413 auto e = edgeMap.find(std::make_pair(v0, v1));
414 if (e != edgeMap.end())
415 return e->second;
416
417 // edge was not inserted yet: insert the edge now
418 std::get<1>(this->grid_->entityImps_[0]).emplace_back(v0, v1, /*level=*/0, this->grid_->getNextFreeId());
419 // insert it into the map of inserted edges
420 auto newEdge = &*std::get<1>(this->grid_->entityImps_[0]).rbegin();
421 edgeMap.insert(std::make_pair(std::make_pair(v0, v1), newEdge));
422 return newEdge;
423 }();
424
425 // make element know about the edge
426 element.facet_[i] = edge;
427
428 // make edge know about the element
429 edge->elements_.push_back(&element);
430 }
431 }
432
433 // Create the index sets
434 this->grid_->setIndices();
435
436
437 // ////////////////////////////////////////////////
438 // Set the boundary ids
439 // ////////////////////////////////////////////////
440
441 for (auto& facet : std::get<1>(this->grid_->entityImps_[0]))
442 {
443 if (facet.elements_.size() == 1) // if boundary facet
444 {
445 std::array<unsigned int, 2> vertexIndices {{ facet.vertex_[0]->leafIndex_, facet.vertex_[1]->leafIndex_ }};
446 // sort the indices
447 if ( vertexIndices[0] > vertexIndices[1] )
448 std::swap( vertexIndices[0], vertexIndices[1] );
449
450 const auto it = boundarySegmentIndices_.find( vertexIndices );
451 if (it != boundarySegmentIndices_.end())
452 facet.boundarySegmentIndex_ = it->second;
453 else
454 facet.boundarySegmentIndex_ = this->boundarySegmentCounter_++;
455 }
456 }
457
458 // ////////////////////////////////////////////////
459 // Hand over the new grid
460 // ////////////////////////////////////////////////
461
463 tmp->numBoundarySegments_ = this->boundarySegmentCounter_;
464 this->grid_ = nullptr;
465 return GridPtrType(tmp);
466 }
467
468 private:
469 template<class T, class U = T>
470 struct HashPair {
471 std::size_t operator() (const std::pair<T, U>& a) const {
472 std::size_t seed = 0;
473 hash_combine(seed, a.first);
474 hash_combine(seed, a.second);
475 return seed;
476 }
477 };
478
479 struct HashUIntArray {
480 std::size_t operator() (const std::array<unsigned int, 2>& a) const {
481 return hash_range(a.begin(), a.end());
482 }
483 };
484
485 std::unordered_map<std::array<unsigned int, 2>, unsigned int, HashUIntArray> boundarySegmentIndices_;
486 };
487
488} // end namespace Dune
489
490#endif
The actual entity implementation.
Definition: foamgridvertex.hh:47
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:114
constexpr bool isTriangle() const
Return true if entity is a triangle.
Definition: type.hh:289
constexpr bool isLine() const
Return true if entity is a line segment.
Definition: type.hh:284
Specialization of the generic GridFactory for FoamGrid<dimgrid, dimworld>
Definition: foamgridfactory.hh:29
~GridFactoryBase() override
Destructor.
Definition: foamgridfactory.hh:62
void insertVertex(const FieldVector< ctype, dimworld > &pos) override
Insert a vertex into the coarse grid.
Definition: foamgridfactory.hh:68
unsigned int insertionIndex(const typename FoamGrid< dimgrid, dimworld, ctype >::LeafIntersection &intersection) const override
Obtain a boundary's insertion index.
Definition: foamgridfactory.hh:96
GridFactoryBase(FoamGrid< dimgrid, dimworld, ctype > *grid)
Constructor for a given grid object.
Definition: foamgridfactory.hh:54
std::vector< FoamGridEntityImp< 0, dimgrid, dimworld, ctype > * > vertexArray_
Array containing all vertices.
Definition: foamgridfactory.hh:111
unsigned int boundarySegmentCounter_
Counter that creates the boundary segment indices.
Definition: foamgridfactory.hh:114
unsigned int insertionIndex(const typename FoamGrid< dimgrid, dimworld, ctype >::Traits::template Codim< dimgrid >::Entity &vertex) const override
Obtain a vertex' insertion index.
Definition: foamgridfactory.hh:88
GridFactoryBase()
Default constructor.
Definition: foamgridfactory.hh:38
unsigned int insertionIndex(const typename FoamGrid< dimgrid, dimworld, ctype >::Traits::template Codim< 0 >::Entity &entity) const override
Obtain an element's insertion index.
Definition: foamgridfactory.hh:80
Provide a generic factory class for unstructured grids.
Definition: gridfactory.hh:70
virtual unsigned int insertionIndex(const typename Codim< 0 >::Entity &entity) const
obtain an element's insertion index
Definition: gridfactory.hh:181
GridPtrType createGrid() override
Finalize grid creation and hand over the grid.
Definition: foamgridfactory.hh:218
void insertBoundarySegment(const std::vector< unsigned int > &vertices, const std::shared_ptr< BoundarySegment< dimgrid, dimworld > > &boundarySegment) override
Insert a boundary segment and the boundary segment geometry This influences the ordering of the bound...
Definition: foamgridfactory.hh:159
bool wasInserted(const typename FoamGrid< dimgrid, dimworld, ctype >::LeafIntersection &intersection) const override
Return true if leaf intersection was inserted as boundary segment.
Definition: foamgridfactory.hh:167
void insertBoundarySegment(const std::vector< unsigned int > &vertices) override
Insert a boundary segment. This is only needed if you want to control the numbering of the boundary s...
Definition: foamgridfactory.hh:151
void insertElement(const GeometryType &type, const std::vector< unsigned int > &vertices) override
Insert an element into the coarse grid.
Definition: foamgridfactory.hh:181
void insertElement(const GeometryType &type, const std::vector< unsigned int > &vertices, std::function< FieldVector< ctype, dimworld >(FieldVector< ctype, dimgrid >)> elementParametrization) override
Insert a parametrized element into the coarse grid.
Definition: foamgridfactory.hh:199
void insertBoundarySegment(const std::vector< unsigned int > &vertices) override
Insert a boundary segment. This is only needed if you want to control the numbering of the boundary s...
Definition: foamgridfactory.hh:294
void insertBoundarySegment(const std::vector< unsigned int > &vertices, const std::shared_ptr< BoundarySegment< dimgrid, dimworld > > &boundarySegment) override
Insert a boundary segment (== a line) and the boundary segment geometry This influences the ordering ...
Definition: foamgridfactory.hh:308
bool wasInserted(const typename FoamGrid< dimgrid, dimworld, ctype >::LeafIntersection &intersection) const override
Return true if leaf intersection was inserted as boundary segment.
Definition: foamgridfactory.hh:316
GridPtrType createGrid() override
Finalize grid creation and hand over the grid The receiver takes responsibility of the memory allocat...
Definition: foamgridfactory.hh:381
void insertElement(const GeometryType &type, const std::vector< unsigned int > &vertices) override
Insert an element into the coarse grid.
Definition: foamgridfactory.hh:346
void insertElement(const GeometryType &type, const std::vector< unsigned int > &vertices, std::function< FieldVector< ctype, dimworld >(FieldVector< ctype, dimgrid >)> elementParametrization) override
Insert a parametrized element into the coarse grid.
Definition: foamgridfactory.hh:364
Provide a generic factory class for unstructured grids.
Definition: gridfactory.hh:275
GridFactory()
Default constructor.
Definition: gridfactory.hh:291
Default exception for dummy implementations.
Definition: exceptions.hh:357
Provide a generic factory class for unstructured grids.
The FoamGrid class.
Implements a vector constructed from a given type representing a field and a compile-time given size.
#define DUNE_THROW(E,...)
Definition: exceptions.hh:314
constexpr GeometryType vertex
GeometryType representing a vertex.
Definition: type.hh:492
Support for calculating hash values of objects.
Dune namespace
Definition: alignedallocator.hh:13
std::size_t hash_range(It first, It last)
Hashes all elements in the range [first,last) and returns the combined hash.
Definition: hash.hh:322
void hash_combine(std::size_t &seed, const T &arg)
Calculates the hash value of arg and combines it in-place with seed.
Definition: hash.hh:307
Base class for classes implementing geometries of boundary segments.
Definition: boundarysegment.hh:94
Static tag representing a codimension.
Definition: dimension.hh:24
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:156
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Feb 14, 23:39, 2026)