14#ifndef DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_HH
15#define DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_HH
39template<
class Gr
idView,
class Traits,
bool enableCache>
43template<
class Gr
idView>
48 DUNE_THROW(Dune::InvalidStateException,
"The ccmpfa discretization method needs at least an overlap of 1 for parallel computations. "
49 <<
" Set the parameter \"Grid.Overlap\" in the input file.");
58template<
class GV,
class Traits>
59class CCMpfaFVGridGeometry<GV, Traits, true>
60:
public BaseGridGeometry<GV, Traits>
62 using ThisType = CCMpfaFVGridGeometry<GV, Traits, true>;
63 using ParentType = BaseGridGeometry<GV, Traits>;
65 static constexpr int dim = GV::dimension;
66 static constexpr int dimWorld = GV::dimensionworld;
68 using Element =
typename GV::template Codim<0>::Entity;
69 using Vertex =
typename GV::template Codim<dim>::Entity;
70 using Intersection =
typename GV::Intersection;
72 using CoordScalar =
typename GV::ctype;
74 using ScvfOutsideGridIndexStorage =
typename Traits::SubControlVolumeFace::Traits::OutsideGridIndexStorage;
78 using FlipScvfIndexSet = std::vector<ScvfOutsideGridIndexStorage>;
80 using GridIVIndexSets =
typename Traits::template GridIvIndexSets<ThisType>;
82 using SecondaryIvIndicatorType = std::function<bool(
const Element&,
const Intersection&,
bool)>;
85 using LocalView =
typename Traits::template LocalView<ThisType, true>;
87 using SubControlVolume =
typename Traits::SubControlVolume;
89 using SubControlVolumeFace =
typename Traits::SubControlVolumeFace;
93 using ConnectivityMap =
typename Traits::template ConnectivityMap<ThisType>;
95 using DofMapper =
typename Traits::ElementMapper;
99 using MpfaHelper =
typename Traits::template MpfaHelper<ThisType>;
102 using DiscretizationMethod = DiscretizationMethods::CCMpfa;
103 static constexpr DiscretizationMethod discMethod{};
106 static constexpr int maxElementStencilSize = Traits::maxElementStencilSize;
109 static constexpr bool hasSingleInteractionVolumeType = !MpfaHelper::considerSecondaryIVs();
113 CCMpfaFVGridGeometry(
const GridView& gridView)
114 : ParentType(gridView)
115 , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching)
116 {
return is.boundary() || isBranching; } )
123 CCMpfaFVGridGeometry(
const GridView& gridView,
const SecondaryIvIndicatorType& indicator)
124 : ParentType(gridView)
125 , secondaryIvIndicator_(indicator)
133 const DofMapper& dofMapper()
const
134 {
return this->elementMapper(); }
137 std::size_t numScv()
const
138 {
return scvs_.size(); }
141 std::size_t numScvf()
const
142 {
return scvfs_.size(); }
145 std::size_t numBoundaryScvf()
const
146 {
return numBoundaryScvf_; }
149 std::size_t numDofs()
const
150 {
return this->gridView().size(0); }
154 template<
bool useSecondary = !hasSingleInteractionVolumeType, std::enable_if_t<useSecondary,
bool> = 0>
155 bool vertexUsesSecondaryInteractionVolume(GridIndexType vIdxGlobal)
const
156 {
return secondaryInteractionVolumeVertices_[vIdxGlobal]; }
160 template<
bool useSecondary = !hasSingleInteractionVolumeType, std::enable_if_t<!useSecondary,
bool> = 0>
161 constexpr bool vertexUsesSecondaryInteractionVolume(GridIndexType vIdxGlobal)
const
166 void update(
const GridView& gridView)
168 ParentType::update(gridView);
173 void update(GridView&& gridView)
175 ParentType::update(std::move(gridView));
180 MpfaHelper mpfaHelper()
const
181 {
return MpfaHelper(); }
184 const SubControlVolume& scv(GridIndexType scvIdx)
const
185 {
return scvs_[scvIdx]; }
188 const SubControlVolumeFace& scvf(GridIndexType scvfIdx)
const
189 {
return scvfs_[scvfIdx]; }
193 const ConnectivityMap& connectivityMap()
const
194 {
return connectivityMap_; }
197 const GridIVIndexSets& gridInteractionVolumeIndexSets()
const
198 {
return ivIndexSets_; }
201 const std::vector<GridIndexType>& scvfIndicesOfScv(GridIndexType scvIdx)
const
202 {
return scvfIndicesOfScv_[scvIdx]; }
205 const FlipScvfIndexSet& flipScvfIndexSet()
const
206 {
return flipScvfIndices_; }
210 const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx,
unsigned int outsideScvfIdx = 0)
const
211 {
return scvfs_[flipScvfIndices_[scvfIdx][outsideScvfIdx]]; }
214 bool hasBoundaryScvf(GridIndexType eIdx)
const
215 {
return hasBoundaryScvf_[eIdx]; }
228 const auto numVert = this->gridView().size(dim);
229 const auto numScvs = numDofs();
230 std::size_t numScvf = MpfaHelper::getGlobalNumScvf(this->gridView());
233 scvs_.resize(numScvs);
234 scvfs_.reserve(numScvf);
235 scvfIndicesOfScv_.resize(numScvs);
236 hasBoundaryScvf_.assign(numScvs,
false);
240 secondaryInteractionVolumeVertices_.assign(numVert,
false);
243 const auto isGhostVertex = MpfaHelper::findGhostVertices(this->gridView(), this->vertexMapper());
246 typename GridIVIndexSets::DualGridIndexSet dualIdSet(this->gridView());
249 GridIndexType scvfIdx = 0;
250 numBoundaryScvf_ = 0;
251 for (
const auto& element : elements(this->gridView()))
253 const auto eIdx = this->elementMapper().index(element);
256 auto elementGeometry =
element.geometry();
259 std::vector<GridIndexType> scvfIndexSet;
260 scvfIndexSet.reserve(MpfaHelper::getNumLocalScvfs(elementGeometry.type()));
264 std::vector<ScvfOutsideGridIndexStorage> outsideIndices;
267 outsideIndices.resize(
element.subEntities(1));
268 for (
const auto& intersection : intersections(this->gridView(), element))
270 if (intersection.neighbor())
272 const auto nIdx = this->elementMapper().index( intersection.outside() );
273 outsideIndices[intersection.indexInInside()].push_back(nIdx);
279 for (
const auto& is : intersections(this->gridView(), element))
281 const auto indexInInside = is.indexInInside();
282 const bool boundary = is.boundary();
283 const bool neighbor = is.neighbor();
286 hasBoundaryScvf_[eIdx] =
true;
289 if (dim < dimWorld && neighbor && outsideIndices[indexInInside].empty())
293 const bool useNeighbor = neighbor && is.outside().level() >
element.level();
294 const auto& e = useNeighbor ? is.outside() :
element;
295 const auto indexInElement = useNeighbor ? is.indexInOutside() : indexInInside;
296 const auto eg = e.geometry();
297 const auto refElement = referenceElement(eg);
300 const auto numCorners = is.geometry().corners();
301 const auto isPositions = MpfaHelper::computeScvfCornersOnIntersection(eg,
307 const bool isBranchingPoint = dim < dimWorld ? outsideIndices[indexInInside].size() > 1 :
false;
308 const bool usesSecondaryIV = secondaryIvIndicator_(element, is, isBranchingPoint);
314 const auto vIdxLocal = refElement.subEntity(indexInElement, 1, c, dim);
315 const auto vIdxGlobal = this->vertexMapper().subIndex(e, vIdxLocal, dim);
318 if (isGhostVertex[vIdxGlobal])
323 secondaryInteractionVolumeVertices_[vIdxGlobal] =
true;
329 const auto& outsideScvIndices = [&] ()
332 return dim == dimWorld ?
333 ScvfOutsideGridIndexStorage({this->elementMapper().index(is.outside())}) :
334 outsideIndices[indexInInside];
336 return ScvfOutsideGridIndexStorage({GridIndexType(numScvs) + numBoundaryScvf_++});
339 scvfIndexSet.push_back(scvfIdx);
340 typename SubControlVolumeFace::FacetInfo facetInfo{
341 this->elementMapper().index(e),
342 useNeighbor ? is.indexInOutside() : is.indexInInside(),
345 scvfs_.emplace_back(MpfaHelper(),
346 MpfaHelper::getScvfCorners(isPositions, numCorners, c),
348 std::move(facetInfo),
358 dualIdSet[vIdxGlobal].insert(scvfs_.back());
366 outsideIndices[indexInInside].clear();
370 scvs_[eIdx] = SubControlVolume(std::move(elementGeometry), eIdx);
373 scvfIndicesOfScv_[eIdx] = scvfIndexSet;
377 flipScvfIndices_.resize(scvfs_.size());
378 for (
const auto& scvf : scvfs_)
383 const auto numOutsideScvs = scvf.numOutsideScvs();
384 const auto vIdxGlobal = scvf.vertexIndex();
385 const auto insideScvIdx = scvf.insideScvIdx();
387 flipScvfIndices_[scvf.index()].resize(numOutsideScvs);
388 for (std::size_t i = 0; i < numOutsideScvs; ++i)
390 const auto outsideScvIdx = scvf.outsideScvIdx(i);
391 for (
auto outsideScvfIndex : scvfIndicesOfScv_[outsideScvIdx])
393 const auto& outsideScvf = this->scvf(outsideScvfIndex);
394 if (outsideScvf.vertexIndex() == vIdxGlobal &&
395 MpfaHelper::vectorContainsValue(outsideScvf.outsideScvIndices(), insideScvIdx))
397 flipScvfIndices_[scvf.index()][i] = outsideScvfIndex;
406 std::cout <<
"Initializing of the grid finite volume geometry took " << timer.elapsed() <<
" seconds." << std::endl;
410 ivIndexSets_.update(*
this, std::move(dualIdSet));
411 std::cout <<
"Initializing of the grid interaction volume index sets took " << timer.elapsed() <<
" seconds." << std::endl;
415 connectivityMap_.update(*
this);
416 std::cout <<
"Initializing of the connectivity map took " << timer.elapsed() <<
" seconds." << std::endl;
420 ConnectivityMap connectivityMap_;
423 std::vector<SubControlVolume> scvs_;
424 std::vector<SubControlVolumeFace> scvfs_;
427 std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_;
428 std::vector<bool> secondaryInteractionVolumeVertices_;
429 GridIndexType numBoundaryScvf_;
430 std::vector<bool> hasBoundaryScvf_;
433 FlipScvfIndexSet flipScvfIndices_;
436 GridIVIndexSets ivIndexSets_;
439 SecondaryIvIndicatorType secondaryIvIndicator_;
449template<
class GV,
class Traits>
453 using ThisType = CCMpfaFVGridGeometry<GV, Traits, false>;
454 using ParentType = BaseGridGeometry<GV, Traits>;
456 static constexpr int dim = GV::dimension;
457 static constexpr int dimWorld = GV::dimensionworld;
459 using Element =
typename GV::template Codim<0>::Entity;
460 using Vertex =
typename GV::template Codim<dim>::Entity;
461 using Intersection =
typename GV::Intersection;
463 using CoordScalar =
typename GV::ctype;
465 using ScvfOutsideGridIndexStorage =
typename Traits::SubControlVolumeFace::Traits::OutsideGridIndexStorage;
469 using FlipScvfIndexSet = std::vector<ScvfOutsideGridIndexStorage>;
471 using GridIVIndexSets =
typename Traits::template GridIvIndexSets<ThisType>;
473 using SecondaryIvIndicatorType = std::function<bool(
const Element&,
const Intersection&,
bool)>;
476 using LocalView =
typename Traits::template LocalView<ThisType, false>;
478 using SubControlVolume =
typename Traits::SubControlVolume;
480 using SubControlVolumeFace =
typename Traits::SubControlVolumeFace;
484 using ConnectivityMap =
typename Traits::template ConnectivityMap<ThisType>;
486 using DofMapper =
typename Traits::ElementMapper;
490 using MpfaHelper =
typename Traits::template MpfaHelper<ThisType>;
493 using DiscretizationMethod = DiscretizationMethods::CCMpfa;
494 static constexpr DiscretizationMethod discMethod{};
497 static constexpr int maxElementStencilSize = Traits::maxElementStencilSize;
500 static constexpr bool hasSingleInteractionVolumeType = !MpfaHelper::considerSecondaryIVs();
504 CCMpfaFVGridGeometry(
const GridView& gridView)
505 : ParentType(gridView)
506 , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching)
507 {
return is.boundary() || isBranching; } )
514 CCMpfaFVGridGeometry(
const GridView& gridView,
const SecondaryIvIndicatorType& indicator)
515 : ParentType(gridView)
516 , secondaryIvIndicator_(indicator)
524 const DofMapper& dofMapper()
const
525 {
return this->elementMapper(); }
528 std::size_t numScv()
const
532 std::size_t numScvf()
const
536 std::size_t numBoundaryScvf()
const
537 {
return numBoundaryScvf_; }
540 std::size_t numDofs()
const
541 {
return this->gridView().size(0); }
545 template<
bool useSecondary = !hasSingleInteractionVolumeType, std::enable_if_t<useSecondary,
bool> = 0>
546 bool vertexUsesSecondaryInteractionVolume(GridIndexType vIdxGlobal)
const
547 {
return secondaryInteractionVolumeVertices_[vIdxGlobal]; }
551 template<
bool useSecondary = !hasSingleInteractionVolumeType, std::enable_if_t<!useSecondary,
bool> = 0>
552 constexpr bool vertexUsesSecondaryInteractionVolume(GridIndexType vIdxGlobal)
const
556 bool isGhostVertex(
const Vertex& v)
const
557 {
return isGhostVertex_[this->vertexMapper().index(v)]; }
560 bool isGhostVertex(GridIndexType vIdxGlobal)
const
561 {
return isGhostVertex_[vIdxGlobal]; }
565 void update(
const GridView& gridView)
567 ParentType::update(gridView);
572 void update(GridView&& gridView)
574 ParentType::update(std::move(gridView));
579 MpfaHelper mpfaHelper()
const
580 {
return MpfaHelper(); }
583 const std::vector<GridIndexType>& scvfIndicesOfScv(GridIndexType scvIdx)
const
584 {
return scvfIndicesOfScv_[scvIdx]; }
587 const std::vector<ScvfOutsideGridIndexStorage>& neighborVolVarIndices(GridIndexType scvIdx)
const
588 {
return neighborVolVarIndices_[scvIdx]; }
592 const GridIndexType flipScvfIdx(GridIndexType scvfIdx,
unsigned int outsideScvfIdx = 0)
const
593 {
return flipScvfIndices_[scvfIdx][outsideScvfIdx]; }
596 const FlipScvfIndexSet& flipScvfIndexSet()
const
597 {
return flipScvfIndices_; }
601 const ConnectivityMap& connectivityMap()
const
602 {
return connectivityMap_; }
605 const GridIVIndexSets& gridInteractionVolumeIndexSets()
const
606 {
return ivIndexSets_; }
617 numScvs_ = numDofs();
618 scvfIndicesOfScv_.resize(numScvs_);
619 neighborVolVarIndices_.resize(numScvs_);
623 const auto numVert = this->gridView().size(dim);
624 secondaryInteractionVolumeVertices_.assign(numVert,
false);
627 isGhostVertex_ = MpfaHelper::findGhostVertices(this->gridView(), this->vertexMapper());
630 typename GridIVIndexSets::DualGridIndexSet dualIdSet(this->gridView());
633 const auto maxNumScvfs = numScvs_*LocalView::maxNumElementScvfs;
634 std::vector<bool> scvfIsOnBoundary;
635 std::vector<GridIndexType> scvfVertexIndex;
636 scvfIsOnBoundary.reserve(maxNumScvfs);
637 scvfVertexIndex.reserve(maxNumScvfs);
641 numBoundaryScvf_ = 0;
642 for (
const auto& element : elements(this->gridView()))
644 const auto eIdx = this->elementMapper().index(element);
647 auto elementGeometry =
element.geometry();
650 const auto numLocalFaces = MpfaHelper::getNumLocalScvfs(elementGeometry.type());
651 std::vector<GridIndexType> scvfsIndexSet;
652 std::vector<ScvfOutsideGridIndexStorage> neighborVolVarIndexSet;
653 scvfsIndexSet.reserve(numLocalFaces);
654 neighborVolVarIndexSet.reserve(numLocalFaces);
658 std::vector<ScvfOutsideGridIndexStorage> outsideIndices;
661 outsideIndices.resize(
element.subEntities(1));
662 for (
const auto& intersection : intersections(this->gridView(), element))
664 if (intersection.neighbor())
666 auto nIdx = this->elementMapper().index( intersection.outside() );
667 outsideIndices[intersection.indexInInside()].push_back(nIdx);
673 for (
const auto& is : intersections(this->gridView(), element))
675 const auto indexInInside = is.indexInInside();
676 const bool boundary = is.boundary();
677 const bool neighbor = is.neighbor();
680 if (dim < dimWorld && neighbor && outsideIndices[indexInInside].empty())
684 const bool useNeighbor = neighbor && is.outside().level() >
element.level();
685 const auto& e = useNeighbor ? is.outside() :
element;
686 const auto indexInElement = useNeighbor ? is.indexInOutside() : indexInInside;
687 const auto eg = e.geometry();
688 const auto refElement = referenceElement(eg);
691 const bool isBranchingPoint = dim < dimWorld ? outsideIndices[indexInInside].size() > 1 :
false;
692 const bool usesSecondaryIV = secondaryIvIndicator_(element, is, isBranchingPoint);
695 for (std::size_t c = 0; c < is.geometry().corners(); ++c)
698 const auto vIdxLocal = refElement.subEntity(indexInElement, 1, c, dim);
699 const auto vIdxGlobal = this->vertexMapper().subIndex(e, vIdxLocal, dim);
702 if (isGhostVertex_[vIdxGlobal])
707 secondaryInteractionVolumeVertices_[vIdxGlobal] =
true;
710 const auto& outsideScvIndices = [&] ()
713 return dim == dimWorld ?
714 ScvfOutsideGridIndexStorage({this->elementMapper().index(is.outside())}) :
715 outsideIndices[indexInInside];
717 return ScvfOutsideGridIndexStorage({GridIndexType(numScvs_) + numBoundaryScvf_++});
721 dualIdSet[vIdxGlobal].insert(numScvf_, eIdx, boundary);
724 scvfsIndexSet.push_back(numScvf_++);
725 scvfIsOnBoundary.push_back(boundary);
726 scvfVertexIndex.push_back(vIdxGlobal);
727 neighborVolVarIndexSet.emplace_back(std::move(outsideScvIndices));
732 outsideIndices[indexInInside].clear();
736 scvfIndicesOfScv_[eIdx] = scvfsIndexSet;
737 neighborVolVarIndices_[eIdx] = neighborVolVarIndexSet;
741 flipScvfIndices_.resize(numScvf_);
742 for (std::size_t scvIdx = 0; scvIdx < numScvs_; ++scvIdx)
744 const auto& scvfIndices = scvfIndicesOfScv_[scvIdx];
745 for (
unsigned int i = 0; i < scvfIndices.size(); ++i)
748 if (scvfIsOnBoundary[ scvfIndices[i] ])
751 const auto scvfIdx = scvfIndices[i];
752 const auto vIdxGlobal = scvfVertexIndex[scvfIdx];
753 const auto numOutsideScvs = neighborVolVarIndices_[scvIdx][i].size();
755 flipScvfIndices_[scvfIdx].resize(numOutsideScvs);
756 for (
unsigned int j = 0; j < numOutsideScvs; ++j)
758 const auto outsideScvIdx = neighborVolVarIndices_[scvIdx][i][j];
759 const auto& outsideScvfIndices = scvfIndicesOfScv_[outsideScvIdx];
760 for (
unsigned int k = 0; k < outsideScvfIndices.size(); ++k)
762 const auto outsideScvfIndex = outsideScvfIndices[k];
763 const auto outsideScvfVertexIndex = scvfVertexIndex[outsideScvfIndex];
764 const auto& outsideScvfNeighborIndices = neighborVolVarIndices_[outsideScvIdx][k];
765 if (outsideScvfVertexIndex == vIdxGlobal &&
766 MpfaHelper::vectorContainsValue(outsideScvfNeighborIndices, scvIdx))
768 flipScvfIndices_[scvfIdx][j] = outsideScvfIndex;
778 std::cout <<
"Initializing of the grid finite volume geometry took " << timer.elapsed() <<
" seconds." << std::endl;
782 ivIndexSets_.update(*
this, std::move(dualIdSet));
783 std::cout <<
"Initializing of the grid interaction volume index sets took " << timer.elapsed() <<
" seconds." << std::endl;
787 connectivityMap_.update(*
this);
788 std::cout <<
"Initializing of the connectivity map took " << timer.elapsed() <<
" seconds." << std::endl;
792 ConnectivityMap connectivityMap_;
795 std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_;
796 std::vector<std::vector<ScvfOutsideGridIndexStorage>> neighborVolVarIndices_;
797 std::vector<bool> secondaryInteractionVolumeVertices_;
798 std::vector<bool> isGhostVertex_;
799 GridIndexType numScvs_;
800 GridIndexType numScvf_;
801 GridIndexType numBoundaryScvf_;
804 FlipScvfIndexSet flipScvfIndices_;
807 GridIVIndexSets ivIndexSets_;
810 SecondaryIvIndicatorType secondaryIvIndicator_;
Base class for grid geometries.
Check the overlap size for different discretization methods.
Base class for all grid geometries.
Definition basegridgeometry.hh:52
The finite volume geometry (scvs and scvfs) for cell-centered mpfa models on a grid view This builds ...
Definition discretization/cellcentered/mpfa/fvgridgeometry.hh:40
Helper classes to compute the integration elements.
T getParam(Args &&... args)
A free function to get a parameter from the parameter tree singleton.
Definition parameters.hh:139
The available discretization methods in Dumux.
std::size_t numCorners(Shape shape)
Returns the number of corners of a given geometry.
Definition throatproperties.hh:220
void checkOverlapSizeCCMpfa(const GridView &gridView)
check the overlap size for parallel computations
Definition discretization/cellcentered/mpfa/fvgridgeometry.hh:44
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition extrusion.hh:166
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
static bool isValid(const GridView &gridView) noexcept
Definition checkoverlapsize.hh:30
typename GridView::IndexSet::IndexType GridIndex
Definition indextraits.hh:27