version 3.11-dev
discretization/pq1bubble/fvgridgeometry.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
14#ifndef DUMUX_DISCRETIZATION_PQ1BUBBLE_GRID_GEOMETRY_HH
15#define DUMUX_DISCRETIZATION_PQ1BUBBLE_GRID_GEOMETRY_HH
16
17#include <utility>
18#include <unordered_map>
19#include <type_traits>
20
21#include <dune/grid/common/mcmgmapper.hh>
22
24
27
30
38
40
41namespace Dumux {
42
43namespace Detail {
44template<class T>
46 = typename T::EnableHybridCVFE;
47
48template<class T>
49static constexpr bool enablesHybridCVFE
50 = Dune::Std::detected_or_t<std::false_type, EnableHybridCVFE, T>{};
51
52template<class GV, class T>
53using PQ1BubbleGeometryHelper_t = Dune::Std::detected_or_t<
54 std::conditional_t<enablesHybridCVFE<T>,
57 >,
59 T
60>;
61} // end namespace Detail
62
63template <class GridView>
65{
66 using DofMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
67
72 static Dune::MCMGLayout layout()
73 {
74 return [](Dune::GeometryType gt, int dimgrid) {
75 return (gt.dim() == dimgrid) || (gt.dim() == 0);
76 };
77 }
78};
79
86template<class GridView, class MapperTraits = PQ1BubbleMapperTraits<GridView>>
88: public MapperTraits
89{
92
93 template<class GridGeometry, bool enableCache>
95
96 static constexpr std::size_t maxNumElementDofs = (1<<GridView::dimension) + 1;
97};
98
105template<class BaseTraits>
107: public BaseTraits
108{ using EnableHybridCVFE = std::true_type; };
109
116template<class Scalar,
117 class GV,
118 bool enableCaching = true,
121: public BaseGridGeometry<GV, Traits>
122{
125 using GridIndexType = typename IndexTraits<GV>::GridIndex;
126 using LocalIndexType = typename IndexTraits<GV>::LocalIndex;
127
128 using Element = typename GV::template Codim<0>::Entity;
129 using CoordScalar = typename GV::ctype;
130 static const int dim = GV::dimension;
131 static const int dimWorld = GV::dimensionworld;
132
133 static_assert(dim > 1, "Only implemented for dim > 1");
134
135public:
139
140 static constexpr bool enableHybridCVFE = Detail::enablesHybridCVFE<Traits>;
141
142 static constexpr std::size_t maxNumElementDofs = Traits::maxNumElementDofs;
143
147 using LocalView = typename Traits::template LocalView<ThisType, true>;
149 using SubControlVolume = typename Traits::SubControlVolume;
151 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
155 using DofMapper = typename Traits::DofMapper;
159 using GridView = GV;
162
164 PQ1BubbleFVGridGeometry(std::shared_ptr<BasicGridGeometry> gg)
165 : ParentType(std::move(gg))
166 , dofMapper_(this->gridView(), Traits::layout())
167 , cache_(*this)
168 , periodicGridTraits_(this->gridView().grid())
169 {
170 update_();
171 }
172
176 {}
177
179 const DofMapper& dofMapper() const
180 { return dofMapper_; }
181
183 std::size_t numScv() const
184 { return numScv_; }
185
187 std::size_t numScvf() const
188 { return numScvf_; }
189
191 std::size_t numBoundaryScvf() const
192 { return numBoundaryScvf_; }
193
195 std::size_t numDofs() const
196 { return this->dofMapper().size(); }
197
200 {
202 update_();
203 }
204
207 {
208 ParentType::update(std::move(gridView));
209 update_();
210 }
211
213 const FeCache& feCache() const
214 { return feCache_; }
215
217 bool dofOnBoundary(GridIndexType dofIdx) const
218 { return boundaryDofIndices_[dofIdx]; }
219
221 bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
222 { return periodicDofMap_.count(dofIdx); }
223
225 GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
226 { return periodicDofMap_.at(dofIdx); }
227
229 const std::unordered_map<GridIndexType, GridIndexType>& periodicDofMap() const
230 { return periodicDofMap_; }
231
234 { return { gg.cache_ }; }
235
236private:
237 class PQ1BubbleGridGeometryCache
238 {
239 friend class PQ1BubbleFVGridGeometry;
240 public:
243
244 explicit PQ1BubbleGridGeometryCache(const PQ1BubbleFVGridGeometry& gg)
245 : gridGeometry_(&gg)
246 {}
247
248 const PQ1BubbleFVGridGeometry& gridGeometry() const
249 { return *gridGeometry_; }
250
252 const std::vector<SubControlVolume>& scvs(GridIndexType eIdx) const
253 { return scvs_[eIdx]; }
254
256 const std::vector<SubControlVolumeFace>& scvfs(GridIndexType eIdx) const
257 { return scvfs_[eIdx]; }
258
260 bool hasBoundaryScvf(GridIndexType eIdx) const
261 { return hasBoundaryScvf_[eIdx]; }
262
264 const std::vector<std::array<LocalIndexType, 2>>& scvfBoundaryGeometryKeys(GridIndexType eIdx) const
265 { return scvfBoundaryGeometryKeys_.at(eIdx); }
266
267 private:
268 void clear_()
269 {
270 scvs_.clear();
271 scvfs_.clear();
272 hasBoundaryScvf_.clear();
273 scvfBoundaryGeometryKeys_.clear();
274 }
275
276 std::vector<std::vector<SubControlVolume>> scvs_;
277 std::vector<std::vector<SubControlVolumeFace>> scvfs_;
278 std::vector<bool> hasBoundaryScvf_;
279 std::unordered_map<GridIndexType, std::vector<std::array<LocalIndexType, 2>>> scvfBoundaryGeometryKeys_;
280
281 const PQ1BubbleFVGridGeometry* gridGeometry_;
282 };
283
284public:
287 using Cache = PQ1BubbleGridGeometryCache;
288
289private:
290 using GeometryHelper = typename Cache::GeometryHelper;
291
292 void update_()
293 {
294 cache_.clear_();
295 dofMapper_.update(this->gridView());
296
297 auto numElements = this->gridView().size(0);
298 cache_.scvs_.resize(numElements);
299 cache_.scvfs_.resize(numElements);
300 cache_.hasBoundaryScvf_.resize(numElements, false);
301
302 boundaryDofIndices_.assign(numDofs(), false);
303
304 numScv_ = 0;
305 numScvf_ = 0;
306 numBoundaryScvf_ = 0;
307
308 // Build the scvs and scv faces
309 for (const auto& element : elements(this->gridView()))
310 {
311 auto eIdx = this->elementMapper().index(element);
312
313 // get the element geometry
314 auto elementGeometry = element.geometry();
315 const auto refElement = referenceElement(elementGeometry);
316
317 // instantiate the geometry helper
318 GeometryHelper geometryHelper(elementGeometry);
319
320 numScv_ += geometryHelper.numScv();
321 // construct the sub control volumes
322 cache_.scvs_[eIdx].resize(geometryHelper.numScv());
323
324 // Scvs related to control volumes
325 for (LocalIndexType scvLocalIdx = 0; scvLocalIdx < geometryHelper.numScv(); ++scvLocalIdx)
326 {
327 auto corners = geometryHelper.getScvCorners(scvLocalIdx);
328 cache_.scvs_[eIdx][scvLocalIdx] = SubControlVolume(
329 geometryHelper.scvVolume(scvLocalIdx, corners),
330 geometryHelper.dofPosition(scvLocalIdx),
331 Dumux::center(corners),
332 scvLocalIdx,
333 eIdx,
334 GeometryHelper::dofIndex(this->dofMapper(), element, scvLocalIdx),
335 geometryHelper.isOverlappingScv(scvLocalIdx)
336 );
337 }
338
339 // construct the sub control volume faces
340 const auto numInteriorScvfs = GeometryHelper::numInteriorScvf(elementGeometry.type());
341 numScvf_ += numInteriorScvfs;
342 cache_.scvfs_[eIdx].resize(numInteriorScvfs);
343 LocalIndexType scvfLocalIdx = 0;
344 for (; scvfLocalIdx < numInteriorScvfs; ++scvfLocalIdx)
345 {
346 const auto scvPair = geometryHelper.getScvPairForScvf(scvfLocalIdx);
347 const auto corners = geometryHelper.getScvfCorners(scvfLocalIdx);
348 const auto area = Dumux::convexPolytopeVolume<dim-1>(
349 geometryHelper.getInteriorScvfGeometryType(scvfLocalIdx),
350 [&](unsigned int i){ return corners[i]; }
351 );
352
353 cache_.scvfs_[eIdx][scvfLocalIdx] = SubControlVolumeFace(
354 Dumux::center(corners),
355 area,
356 geometryHelper.normal(corners, scvPair),
357 std::move(scvPair),
358 scvfLocalIdx,
359 geometryHelper.isOverlappingScvf(scvfLocalIdx)
360 );
361 }
362
363 // construct the sub control volume faces on the domain boundary
364 for (const auto& intersection : intersections(this->gridView(), element))
365 {
366 if (intersection.boundary() && !intersection.neighbor())
367 {
368 cache_.hasBoundaryScvf_[eIdx] = true;
369
370 const auto localFacetIndex = intersection.indexInInside();
371 const auto numBoundaryScvf = GeometryHelper::numBoundaryScvf(elementGeometry.type(), localFacetIndex);
372 numScvf_ += numBoundaryScvf;
373 numBoundaryScvf_ += numBoundaryScvf;
374
375 for (unsigned int isScvfLocalIdx = 0; isScvfLocalIdx < numBoundaryScvf; ++isScvfLocalIdx)
376 {
377 // find the scvs this scvf is belonging to
378 const auto scvPair = geometryHelper.getScvPairForBoundaryScvf(localFacetIndex, isScvfLocalIdx);
379 const auto corners = geometryHelper.getBoundaryScvfCorners(localFacetIndex, isScvfLocalIdx);
380 const auto area = Dumux::convexPolytopeVolume<dim-1>(
381 geometryHelper.getBoundaryScvfGeometryType(isScvfLocalIdx),
382 [&](unsigned int i){ return corners[i]; }
383 );
384 cache_.scvfs_[eIdx].emplace_back(
385 Dumux::center(corners),
386 area,
387 intersection.centerUnitOuterNormal(),
388 std::move(scvPair),
389 scvfLocalIdx,
390 typename SubControlVolumeFace::Traits::BoundaryFlag{ intersection },
391 geometryHelper.isOverlappingBoundaryScvf(localFacetIndex)
392 );
393
394 // store look-up map to construct boundary scvf geometries
395 cache_.scvfBoundaryGeometryKeys_[eIdx].emplace_back(std::array<LocalIndexType, 2>{{
396 static_cast<LocalIndexType>(localFacetIndex),
397 static_cast<LocalIndexType>(isScvfLocalIdx)
398 }});
399
400 // increment local counter
401 scvfLocalIdx++;
402 }
403
404 const auto numDofsIntersection = GeometryHelper::numLocalDofsIntersection(elementGeometry.type(), localFacetIndex);
405 // TODO also move this to helper class
406 // add all dofs on the intersection to the set of boundary dofs
407 for (int ilocalDofIdx = 0; ilocalDofIdx < numDofsIntersection; ++ilocalDofIdx)
408 {
409 auto localDofIdx = GeometryHelper::localDofIndexIntersection(elementGeometry.type(), localFacetIndex, ilocalDofIdx);
410 const auto vIdxGlobal = GeometryHelper::dofIndex(this->dofMapper(), element, localDofIdx);
411 boundaryDofIndices_[vIdxGlobal] = true;
412 }
413 }
414
415 // inform the grid geometry if we have periodic boundaries
416 else if (periodicGridTraits_.isPeriodic(intersection))
417 {
418 this->setPeriodic();
419
420 // find the mapped periodic vertex of all vertices on periodic boundaries
421 const auto fIdx = intersection.indexInInside();
422 const auto numFaceVerts = refElement.size(fIdx, 1, dim);
423 const auto eps = 1e-7*(elementGeometry.corner(1) - elementGeometry.corner(0)).two_norm();
424 for (int localVIdx = 0; localVIdx < numFaceVerts; ++localVIdx)
425 {
426 const auto vIdx = refElement.subEntity(fIdx, 1, localVIdx, dim);
427 const auto vIdxGlobal = this->dofMapper().subIndex(element, vIdx, dim);
428 const auto vPos = elementGeometry.corner(vIdx);
429
430 const auto& outside = intersection.outside();
431 const auto outsideGeometry = outside.geometry();
432 for (const auto& isOutside : intersections(this->gridView(), outside))
433 {
434 // only check periodic vertices of the periodic neighbor
435 if (periodicGridTraits_.isPeriodic(isOutside))
436 {
437 const auto fIdxOutside = isOutside.indexInInside();
438 const auto numFaceVertsOutside = refElement.size(fIdxOutside, 1, dim);
439 for (int localVIdxOutside = 0; localVIdxOutside < numFaceVertsOutside; ++localVIdxOutside)
440 {
441 const auto vIdxOutside = refElement.subEntity(fIdxOutside, 1, localVIdxOutside, dim);
442 const auto vPosOutside = outsideGeometry.corner(vIdxOutside);
443 const auto shift = std::abs((this->bBoxMax()-this->bBoxMin())*intersection.centerUnitOuterNormal());
444 if (std::abs((vPosOutside-vPos).two_norm() - shift) < eps)
445 periodicDofMap_[vIdxGlobal] = this->dofMapper().subIndex(outside, vIdxOutside, dim);
446 }
447 }
448 }
449 }
450 }
451 }
452 }
453
454 // error check: periodic boundaries currently don't work for pq1bubble in parallel
455 if (this->isPeriodic() && this->gridView().comm().size() > 1)
456 DUNE_THROW(Dune::NotImplemented, "Periodic boundaries for pq1bubble method for parallel simulations!");
457 }
458
459 DofMapper dofMapper_;
460
461 const FeCache feCache_;
462
463 std::size_t numScv_;
464 std::size_t numScvf_;
465 std::size_t numBoundaryScvf_;
466
467 // vertices on the boundary
468 std::vector<bool> boundaryDofIndices_;
469
470 // a map for periodic boundary vertices
471 std::unordered_map<GridIndexType, GridIndexType> periodicDofMap_;
472
473 Cache cache_;
474
476};
477
478} // end namespace Dumux
479
480#endif
Base class for grid geometries.
Compute the center point of a convex polytope geometry or a random-access container of corner points.
Base class for all grid geometries.
Definition: basegridgeometry.hh:52
const ElementMapper & elementMapper() const
Returns the mapper for elements to indices for constant grids.
Definition: basegridgeometry.hh:112
void setPeriodic(bool value=true)
Set the periodicity of the grid geometry.
Definition: basegridgeometry.hh:169
const GlobalCoordinate & bBoxMax() const
The coordinate of the corner of the GridView's bounding box with the largest values.
Definition: basegridgeometry.hh:156
Element element(GridIndexType eIdx) const
Get an element from a global element index.
Definition: basegridgeometry.hh:142
const GridView & gridView() const
Return the gridView this grid geometry object lives on.
Definition: basegridgeometry.hh:100
void update(const GridView &gridView)
Update all fvElementGeometries (call this after grid adaption)
Definition: basegridgeometry.hh:88
const GlobalCoordinate & bBoxMin() const
The coordinate of the corner of the GridView's bounding box with the smallest values.
Definition: basegridgeometry.hh:149
bool isPeriodic() const
Returns if the grid geometry is periodic (at all)
Definition: basegridgeometry.hh:162
Definition: discretization/pq1bubble/geometryhelper.hh:503
Definition: pq1bubblefecache.hh:29
Base class for the finite volume geometry vector for pq1bubble models This builds up the sub control ...
Definition: discretization/pq1bubble/fvelementgeometry.hh:42
Base class for the finite volume geometry vector for pq1bubble schemes This builds up the sub control...
Definition: discretization/pq1bubble/fvgridgeometry.hh:122
void update(const GridView &gridView)
update all geometries (call this after grid adaption)
Definition: discretization/pq1bubble/fvgridgeometry.hh:199
friend LocalView localView(const PQ1BubbleFVGridGeometry &gg)
local view of this object (constructed with the internal cache)
Definition: discretization/pq1bubble/fvgridgeometry.hh:233
PQ1BubbleGridGeometryCache Cache
Definition: discretization/pq1bubble/fvgridgeometry.hh:287
PQ1BubbleFVGridGeometry(std::shared_ptr< BasicGridGeometry > gg)
Constructor with basic grid geometry used to share state with another grid geometry on the same grid ...
Definition: discretization/pq1bubble/fvgridgeometry.hh:164
static constexpr DiscretizationMethod discMethod
Definition: discretization/pq1bubble/fvgridgeometry.hh:138
std::size_t numBoundaryScvf() const
The total number of boundary sub control volume faces.
Definition: discretization/pq1bubble/fvgridgeometry.hh:191
PQ1BubbleFVGridGeometry(const GridView &gridView)
Constructor.
Definition: discretization/pq1bubble/fvgridgeometry.hh:174
BasicGridGeometry_t< GV, Traits > BasicGridGeometry
export basic grid geometry type for the alternative constructor
Definition: discretization/pq1bubble/fvgridgeometry.hh:145
std::size_t numScv() const
The total number of sub control volumes.
Definition: discretization/pq1bubble/fvgridgeometry.hh:183
std::size_t numScvf() const
The total number of sub control volume faces.
Definition: discretization/pq1bubble/fvgridgeometry.hh:187
static constexpr std::size_t maxNumElementDofs
Definition: discretization/pq1bubble/fvgridgeometry.hh:142
const FeCache & feCache() const
The finite element cache for creating local FE bases.
Definition: discretization/pq1bubble/fvgridgeometry.hh:213
GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
The index of the vertex / d.o.f. on the other side of the periodic boundary.
Definition: discretization/pq1bubble/fvgridgeometry.hh:225
Extrusion_t< Traits > Extrusion
export the type of extrusion
Definition: discretization/pq1bubble/fvgridgeometry.hh:153
static constexpr bool enableHybridCVFE
Definition: discretization/pq1bubble/fvgridgeometry.hh:140
typename Traits::SubControlVolumeFace SubControlVolumeFace
export the type of sub control volume
Definition: discretization/pq1bubble/fvgridgeometry.hh:151
std::size_t numDofs() const
The total number of degrees of freedom.
Definition: discretization/pq1bubble/fvgridgeometry.hh:195
bool dofOnBoundary(GridIndexType dofIdx) const
If a vertex / d.o.f. is on the boundary.
Definition: discretization/pq1bubble/fvgridgeometry.hh:217
typename Traits::DofMapper DofMapper
export dof mapper type
Definition: discretization/pq1bubble/fvgridgeometry.hh:155
const DofMapper & dofMapper() const
The dofMapper.
Definition: discretization/pq1bubble/fvgridgeometry.hh:179
const std::unordered_map< GridIndexType, GridIndexType > & periodicDofMap() const
Returns the map between dofs across periodic boundaries.
Definition: discretization/pq1bubble/fvgridgeometry.hh:229
GV GridView
export the grid view type
Definition: discretization/pq1bubble/fvgridgeometry.hh:159
bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
If a vertex / d.o.f. is on a periodic boundary.
Definition: discretization/pq1bubble/fvgridgeometry.hh:221
typename Traits::template LocalView< ThisType, true > LocalView
export the type of the fv element geometry (the local view type)
Definition: discretization/pq1bubble/fvgridgeometry.hh:147
typename Traits::SubControlVolume SubControlVolume
export the type of sub control volume
Definition: discretization/pq1bubble/fvgridgeometry.hh:149
typename PeriodicGridTraits< typename GV::Grid >::SupportsPeriodicity SupportsPeriodicity
export whether the grid(geometry) supports periodicity
Definition: discretization/pq1bubble/fvgridgeometry.hh:161
void update(GridView &&gridView)
update all geometries (call this after grid adaption)
Definition: discretization/pq1bubble/fvgridgeometry.hh:206
Dumux::PQ1BubbleFECache< CoordScalar, Scalar, dim > FeCache
export the finite element cache type
Definition: discretization/pq1bubble/fvgridgeometry.hh:157
A class to create sub control volume and sub control volume face geometries per element.
Definition: discretization/pq1bubble/geometryhelper.hh:167
Class for a sub control volume face in the cvfe method, i.e a part of the boundary of a sub control v...
Definition: discretization/pq1bubble/subcontrolvolumeface.hh:58
the sub control volume for the pq1bubble scheme
Definition: discretization/pq1bubble/subcontrolvolume.hh:55
Defines the default element and vertex mapper types.
Base class for the local finite volume geometry for the pq1bubble method This builds up the sub contr...
Helper class constructing the dual grid finite volume geometries for the cvfe discretizazion method.
the sub control volume for the cvfe scheme
Base class for a sub control volume face.
Helper classes to compute the integration elements.
Dune::Std::detected_or_t< Dumux::BasicGridGeometry< GV, typename T::ElementMapper, typename T::VertexMapper >, Detail::SpecifiesBaseGridGeometry, T > BasicGridGeometry_t
Type of the basic grid geometry implementation used as backend.
Definition: basegridgeometry.hh:42
auto convexPolytopeVolume(Dune::GeometryType type, const CornerF &c)
Compute the volume of several common geometry types.
Definition: volume.hh:41
Corners::value_type center(const Corners &corners)
The center of a given list of corners.
Definition: center.hh:24
Defines the index types used for grid and local indices.
The available discretization methods in Dumux.
typename T::EnableHybridCVFE EnableHybridCVFE
Definition: discretization/pq1bubble/fvgridgeometry.hh:46
static constexpr bool enablesHybridCVFE
Definition: discretization/pq1bubble/fvgridgeometry.hh:50
typename T::GeometryHelper SpecifiesGeometryHelper
Definition: basegridgeometry.hh:30
Dune::Std::detected_or_t< std::conditional_t< enablesHybridCVFE< T >, Dumux::HybridPQ1BubbleGeometryHelper< GV, typename T::SubControlVolume, typename T::SubControlVolumeFace >, Dumux::PQ1BubbleGeometryHelper< GV, typename T::SubControlVolume, typename T::SubControlVolumeFace > >, SpecifiesGeometryHelper, T > PQ1BubbleGeometryHelper_t
Definition: discretization/pq1bubble/fvgridgeometry.hh:60
CVFE< CVFEMethods::PQ1Bubble > PQ1Bubble
Definition: method.hh:108
Definition: adapt.hh:17
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:166
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition: localdof.hh:79
Grid properties related to periodicity.
A finite element cache for P1/Q1 function with bubble.
Definition: defaultmappertraits.hh:23
Definition: method.hh:46
The default traits for the hybrid pq1bubble finite volume grid geometry Defines the scv and scvf type...
Definition: discretization/pq1bubble/fvgridgeometry.hh:108
std::true_type EnableHybridCVFE
Definition: discretization/pq1bubble/fvgridgeometry.hh:108
Structure to define the index types used for grid and local indices.
Definition: indextraits.hh:26
The default traits for the pq1bubble finite volume grid geometry Defines the scv and scvf types and t...
Definition: discretization/pq1bubble/fvgridgeometry.hh:89
static constexpr std::size_t maxNumElementDofs
Definition: discretization/pq1bubble/fvgridgeometry.hh:96
Definition: discretization/pq1bubble/fvgridgeometry.hh:65
Dune::MultipleCodimMultipleGeomTypeMapper< GridView > DofMapper
Definition: discretization/pq1bubble/fvgridgeometry.hh:66
static Dune::MCMGLayout layout()
layout for elements and vertices
Definition: discretization/pq1bubble/fvgridgeometry.hh:72
Definition: periodicgridtraits.hh:24
bool isPeriodic(const typename Grid::LeafIntersection &intersection) const
Definition: periodicgridtraits.hh:28
Compute the volume of several common geometry types.