14#ifndef DUMUX_DISCRETIZATION_CCMPFA_FV_ELEMENT_GEOMETRY_HH
15#define DUMUX_DISCRETIZATION_CCMPFA_FV_ELEMENT_GEOMETRY_HH
20#include <dune/common/exceptions.hh>
21#include <dune/common/iteratorrange.hh>
22#include <dune/geometry/type.hh>
31namespace Detail::Mpfa {
33template<
typename Gr
idGeometry,
typename SubControlVolumeFace>
34typename SubControlVolumeFace::Traits::Geometry makeScvfGeometry(
const GridGeometry& gridGeometry,
35 const SubControlVolumeFace& scvf)
37 static constexpr int dim = GridGeometry::GridView::dimension;
39 const auto& facetInfo = scvf.facetInfo();
40 const auto element = gridGeometry.element(facetInfo.elementIndex);
41 const auto elemGeo =
element.geometry();
42 const auto refElement = referenceElement(elemGeo);
43 for (
const auto& is : intersections(gridGeometry.gridView(), element))
45 if (is.indexInInside() == facetInfo.facetIndex)
47 const auto numCorners = is.geometry().corners();
48 const auto isPositions = GridGeometry::MpfaHelper::computeScvfCornersOnIntersection(
49 elemGeo, refElement, facetInfo.facetIndex, numCorners
52 Dune::GeometryTypes::cube(dim-1),
53 GridGeometry::MpfaHelper::getScvfCorners(
54 isPositions, numCorners, facetInfo.facetCornerIndex
59 DUNE_THROW(Dune::InvalidStateException,
"Could not construct scvf geometry");
62template<
typename Gr
idGeometry,
typename SubControlVolumeFace>
63auto getVertexCorner(
const GridGeometry& gridGeometry,
const SubControlVolumeFace& scvf)
65 static constexpr int dim = GridGeometry::GridView::dimension;
67 const auto& facetInfo = scvf.facetInfo();
68 const auto element = gridGeometry.element(facetInfo.elementIndex);
69 const auto elemGeo =
element.geometry();
70 const auto refElement = referenceElement(elemGeo);
71 return elemGeo.global(refElement.position(
72 refElement.subEntity(facetInfo.facetIndex, 1, facetInfo.facetCornerIndex, dim),
77template<
typename Gr
idGeometry,
typename SubControlVolumeFace>
78auto getFacetCorner(
const GridGeometry& gridGeometry,
const SubControlVolumeFace& scvf)
80 const auto& facetInfo = scvf.facetInfo();
81 const auto element = gridGeometry.element(facetInfo.elementIndex);
82 const auto elemGeo =
element.geometry();
83 const auto refElement = referenceElement(elemGeo);
84 return elemGeo.global(refElement.position(facetInfo.facetIndex, 1));
99template<
class GG,
bool enableGr
idGeometryCache>
112 using GridView =
typename GG::GridView;
115 static constexpr int dim = GridView::dimension;
116 static constexpr int dimWorld = GridView::dimensionworld;
120 using Element =
typename GridView::template Codim<0>::Entity;
122 using SubControlVolume =
typename GG::SubControlVolume;
124 using SubControlVolumeFace =
typename GG::SubControlVolumeFace;
126 using GridGeometry = GG;
128 static constexpr std::size_t maxNumElementScvs = 1;
130 static constexpr std::size_t maxNumElementScvfs = dim == 3 ? 24 : 8;
134 : gridGeometryPtr_(&gridGeometry) {}
137 const SubControlVolume& scv(GridIndexType scvIdx)
const
139 return gridGeometry().scv(scvIdx);
143 const SubControlVolumeFace& scvf(GridIndexType scvfIdx)
const
145 return gridGeometry().scvf(scvfIdx);
150 const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx,
unsigned int outsideScvIdx = 0)
const
152 return gridGeometry().flipScvf(scvfIdx, outsideScvIdx);
160 friend inline Dune::IteratorRange< ScvIterator<SubControlVolume, std::array<GridIndexType, 1>, ThisType> >
161 scvs(
const CCMpfaFVElementGeometry& fvGeometry)
163 using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::array<GridIndexType, 1>, ThisType>;
164 return Dune::IteratorRange<ScvIterator>(ScvIterator(fvGeometry.scvIndices_.begin(), fvGeometry),
165 ScvIterator(fvGeometry.scvIndices_.end(), fvGeometry));
173 friend inline Dune::IteratorRange< ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType> >
174 scvfs(
const CCMpfaFVElementGeometry& fvGeometry)
176 const auto& g = fvGeometry.gridGeometry();
177 const auto scvIdx = fvGeometry.scvIndices_[0];
178 using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType>;
179 return Dune::IteratorRange<ScvfIterator>(ScvfIterator(g.scvfIndicesOfScv(scvIdx).begin(), fvGeometry),
180 ScvfIterator(g.scvfIndicesOfScv(scvIdx).end(), fvGeometry));
184 std::size_t numScv()
const
186 return scvIndices_.size();
190 std::size_t numScvf()
const
192 return gridGeometry().scvfIndicesOfScv(scvIndices_[0]).size();
200 CCMpfaFVElementGeometry bind(
const Element& element) &&
202 this->bindElement(element);
203 return std::move(*
this);
206 void bind(
const Element& element) &
208 this->bindElement(element);
216 CCMpfaFVElementGeometry bindElement(
const Element& element) &&
218 this->bindElement(element);
219 return std::move(*
this);
223 void bindElement(
const Element& element) &
226 scvIndices_[0] = gridGeometry().elementMapper().index(element);
231 {
return static_cast<bool>(element_); }
235 {
return *element_; }
238 const GridGeometry& gridGeometry()
const
239 {
return *gridGeometryPtr_; }
242 bool hasBoundaryScvf()
const
243 {
return gridGeometry().hasBoundaryScvf(scvIndices_[0]); }
246 typename Element::Geometry geometry(
const SubControlVolume& scv)
const
247 {
return gridGeometryPtr_->element(scv.dofIndex()).geometry(); }
250 typename SubControlVolumeFace::Traits::Geometry geometry(
const SubControlVolumeFace& scvf)
const
251 {
return Detail::Mpfa::makeScvfGeometry(gridGeometry(), scvf); }
254 typename SubControlVolumeFace::Traits::GlobalPosition vertexCorner(
const SubControlVolumeFace& scvf)
const
255 {
return Detail::Mpfa::getVertexCorner(gridGeometry(), scvf); }
258 typename SubControlVolumeFace::Traits::GlobalPosition facetCorner(
const SubControlVolumeFace& scvf)
const
259 {
return Detail::Mpfa::getFacetCorner(gridGeometry(), scvf); }
263 std::optional<Element> element_;
264 std::array<GridIndexType, 1> scvIndices_;
265 const GridGeometry* gridGeometryPtr_;
276 using ThisType = CCMpfaFVElementGeometry<GG, false>;
277 using GridView =
typename GG::GridView;
279 using MpfaHelper =
typename GG::MpfaHelper;
281 static constexpr int dim = GridView::dimension;
282 static constexpr int dimWorld = GridView::dimensionworld;
283 using CoordScalar =
typename GridView::ctype;
287 using Element =
typename GridView::template Codim<0>::Entity;
289 using SubControlVolume =
typename GG::SubControlVolume;
291 using SubControlVolumeFace =
typename GG::SubControlVolumeFace;
293 using GridGeometry = GG;
295 static constexpr std::size_t maxNumElementScvs = 1;
297 static constexpr std::size_t maxNumElementScvfs = dim == 3 ? 24 : 8;
300 CCMpfaFVElementGeometry(
const GridGeometry& gridGeometry)
301 : gridGeometryPtr_(&gridGeometry) {}
305 const SubControlVolume& scv(GridIndexType scvIdx)
const
307 if (scvIdx == scvIndices_[0])
310 return neighborScvs_[
findLocalIndex(scvIdx, neighborScvIndices_)];
315 const SubControlVolumeFace& scvf(GridIndexType scvfIdx)
const
317 auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
318 if (it != scvfIndices_.end())
319 return scvfs_[std::distance(scvfIndices_.begin(), it)];
321 return neighborScvfs_[
findLocalIndex(scvfIdx, neighborScvfIndices_)];
326 const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx,
unsigned int outsideScvIdx = 0)
const
328 return scvf( gridGeometry().flipScvfIdx(scvfIdx, outsideScvIdx) );
336 friend inline Dune::IteratorRange<typename std::array<SubControlVolume, 1>::const_iterator>
337 scvs(
const ThisType& g)
339 using IteratorType =
typename std::array<SubControlVolume, 1>::const_iterator;
340 return Dune::IteratorRange<IteratorType>(g.scvs_.begin(), g.scvs_.end());
348 friend inline Dune::IteratorRange<typename std::vector<SubControlVolumeFace>::const_iterator>
349 scvfs(
const ThisType& g)
351 using IteratorType =
typename std::vector<SubControlVolumeFace>::const_iterator;
352 return Dune::IteratorRange<IteratorType>(g.scvfs_.begin(), g.scvfs_.end());
356 std::size_t numScv()
const
357 {
return scvs_.size(); }
360 std::size_t numScvf()
const
361 {
return scvfs_.size(); }
368 CCMpfaFVElementGeometry bindElement(
const Element& element) &&
370 this->bindElement_(element);
371 return std::move(*
this);
374 void bindElement(
const Element& element) &
376 this->bindElement_(element);
384 CCMpfaFVElementGeometry bind(
const Element& element) &&
386 this->bind_(element);
387 return std::move(*
this);
390 void bind(
const Element& element) &
392 this->bind_(element);
397 {
return static_cast<bool>(element_); }
401 {
return *element_; }
404 const GridGeometry& gridGeometry()
const
405 {
return *gridGeometryPtr_; }
408 bool hasBoundaryScvf()
const
409 {
return hasBoundaryScvf_; }
412 typename SubControlVolume::Traits::Geometry geometry(
const SubControlVolume& scv)
const
413 {
return gridGeometryPtr_->element(scv.dofIndex()).geometry(); }
416 typename SubControlVolumeFace::Traits::Geometry geometry(
const SubControlVolumeFace& scvf)
const
417 {
return Detail::Mpfa::makeScvfGeometry(gridGeometry(), scvf); }
420 typename SubControlVolumeFace::Traits::GlobalPosition vertexCorner(
const SubControlVolumeFace& scvf)
const
421 {
return Detail::Mpfa::getVertexCorner(gridGeometry(), scvf); }
424 typename SubControlVolumeFace::Traits::GlobalPosition facetCorner(
const SubControlVolumeFace& scvf)
const
425 {
return Detail::Mpfa::getFacetCorner(gridGeometry(), scvf); }
431 void bind_(
const Element& element)
434 bindElement_(element);
437 const auto globalI = gridGeometry().elementMapper().index(element);
438 const auto& assemblyMapI = gridGeometry().connectivityMap()[globalI];
441 const auto numNeighbors = assemblyMapI.size();
442 const auto numNeighborScvfs = numNeighborScvfs_(assemblyMapI);
443 neighborScvs_.reserve(numNeighbors);
444 neighborScvIndices_.reserve(numNeighbors);
445 neighborScvfIndices_.reserve(numNeighborScvfs);
446 neighborScvfs_.reserve(numNeighborScvfs);
450 for (
const auto& dataJ : assemblyMapI)
451 makeNeighborGeometries(gridGeometry().
element(dataJ.globalJ),
454 dataJ.additionalScvfs);
473 void bindElement_(
const Element& element)
477 makeElementGeometries(element);
481 template<
class DataJContainer>
482 std::size_t numNeighborScvfs_(
const DataJContainer& dataJContainer)
484 std::size_t numNeighborScvfs = 0;
485 for (
const auto& dataJ : dataJContainer)
486 numNeighborScvfs += dataJ.scvfsJ.size() + dataJ.additionalScvfs.size();
487 return numNeighborScvfs;
491 void makeElementGeometries(
const Element& element)
494 const auto eIdx = gridGeometry().elementMapper().index(element);
495 scvs_[0] = SubControlVolume(
element.geometry(), eIdx);
496 scvIndices_[0] = eIdx;
499 const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdx);
500 const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx);
506 const auto numLocalScvf = scvFaceIndices.size();
507 scvfIndices_.reserve(numLocalScvf);
508 scvfs_.reserve(numLocalScvf);
512 std::vector<bool> finishedFacets;
514 finishedFacets.resize(
element.subEntities(1),
false);
517 for (
const auto& is : intersections(gridGeometry().gridView(), element))
523 const auto indexInInside = is.indexInInside();
524 if (finishedFacets[indexInInside])
527 finishedFacets[indexInInside] =
true;
531 bool useNeighbor = is.neighbor() && is.outside().level() >
element.level();
532 const auto& e = useNeighbor ? is.outside() :
element;
533 const auto indexInElement = useNeighbor ? is.indexInOutside() : is.indexInInside();
534 const auto eg = e.geometry();
535 const auto refElement = referenceElement(eg);
538 const auto numCorners = is.geometry().corners();
539 const auto isPositions = MpfaHelper::computeScvfCornersOnIntersection(eg,
548 auto vIdxLocal = refElement.subEntity(indexInElement, 1, c, dim);
549 auto vIdxGlobal = gridGeometry().vertexMapper().subIndex(e, vIdxLocal, dim);
552 if (gridGeometry().isGhostVertex(vIdxGlobal))
555 hasBoundaryScvf_ = (hasBoundaryScvf_ || is.boundary());
556 typename SubControlVolumeFace::FacetInfo facetInfo{
557 gridGeometry().elementMapper().index(e),
558 useNeighbor ? is.indexInOutside() : is.indexInInside(),
561 scvfs_.emplace_back(MpfaHelper(),
562 MpfaHelper::getScvfCorners(isPositions, numCorners, c),
564 std::move(facetInfo),
567 scvFaceIndices[scvfCounter],
569 neighborVolVarIndices[scvfCounter],
573 scvfIndices_.emplace_back(scvFaceIndices[scvfCounter]);
580 template<
typename IndexVector>
581 void makeNeighborGeometries(
const Element& element,
582 GridIndexType eIdxGlobal,
583 const IndexVector& scvfIndices,
584 const IndexVector& additionalScvfs)
587 neighborScvs_.emplace_back(
element.geometry(), eIdxGlobal);
588 neighborScvIndices_.push_back(eIdxGlobal);
591 const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdxGlobal);
592 const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdxGlobal);
599 std::vector<bool> finishedFacets;
601 finishedFacets.resize(
element.subEntities(1),
false);
604 for (
const auto& is : intersections(gridGeometry().gridView(), element))
610 auto indexInInside = is.indexInInside();
611 if(finishedFacets[indexInInside])
614 finishedFacets[indexInInside] =
true;
618 bool useNeighbor = is.neighbor() && is.outside().level() >
element.level();
619 const auto& e = useNeighbor ? is.outside() :
element;
620 const auto indexInElement = useNeighbor ? is.indexInOutside() : is.indexInInside();
621 const auto eg = e.geometry();
622 const auto refElement = referenceElement(eg);
625 const auto numCorners = is.geometry().corners();
626 const auto isPositions = MpfaHelper::computeScvfCornersOnIntersection(eg,
635 auto vIdxLocal = refElement.subEntity(indexInElement, 1, c, dim);
636 auto vIdxGlobal = gridGeometry().vertexMapper().subIndex(e, vIdxLocal, dim);
639 if (gridGeometry().isGhostVertex(vIdxGlobal))
643 if (!MpfaHelper::vectorContainsValue(scvfIndices, scvFaceIndices[scvfCounter])
644 && !MpfaHelper::vectorContainsValue(additionalScvfs, scvFaceIndices[scvfCounter]))
652 typename SubControlVolumeFace::FacetInfo facetInfo{
653 gridGeometry().elementMapper().index(e),
654 useNeighbor ? is.indexInOutside() : is.indexInInside(),
657 neighborScvfs_.emplace_back(MpfaHelper(),
658 MpfaHelper::getScvfCorners(isPositions, numCorners, c),
660 std::move(facetInfo),
663 scvFaceIndices[scvfCounter],
665 neighborVolVarIndices[scvfCounter],
669 neighborScvfIndices_.emplace_back(scvFaceIndices[scvfCounter]);
679 const std::vector<GridIndexType>& indices)
const
681 auto it = std::find(indices.begin(), indices.end(), idx);
682 assert(it != indices.end() &&
"Could not find the scv/scvf! Make sure to properly bind this class!");
683 return std::distance(indices.begin(), it);
689 scvfIndices_.clear();
692 neighborScvIndices_.clear();
693 neighborScvfIndices_.clear();
694 neighborScvs_.clear();
695 neighborScvfs_.clear();
697 hasBoundaryScvf_ =
false;
700 const GridGeometry* gridGeometryPtr_;
701 std::optional<Element> element_;
704 std::array<GridIndexType, 1> scvIndices_;
705 std::vector<GridIndexType> scvfIndices_;
706 std::array<SubControlVolume, 1> scvs_;
707 std::vector<SubControlVolumeFace> scvfs_;
709 std::vector<GridIndexType> neighborScvIndices_;
710 std::vector<GridIndexType> neighborScvfIndices_;
711 std::vector<SubControlVolume> neighborScvs_;
712 std::vector<SubControlVolumeFace> neighborScvfs_;
714 bool hasBoundaryScvf_ =
false;
Stencil-local finite volume geometry (scvs and scvfs) for cell-centered mpfa models This builds up th...
Definition discretization/cellcentered/mpfa/fvelementgeometry.hh:100
T getParam(Args &&... args)
A free function to get a parameter from the parameter tree singleton.
Definition parameters.hh:139
auto findLocalIndex(const GridIndexType idx, const std::vector< GridIndexType > &indices)
Definition discretization/cellcentered/tpfa/fvelementgeometry.hh:33
std::size_t numCorners(Shape shape)
Returns the number of corners of a given geometry.
Definition throatproperties.hh:220
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Class providing iterators over sub control volumes and sub control volume faces of an element.
typename GridView::IndexSet::IndexType GridIndex
Definition indextraits.hh:27