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