12#ifndef DUMUX_DISCRETIZATION_FACECENTERED_STAGGERED_FV_ELEMENT_GEOMETRY_HH 
   13#define DUMUX_DISCRETIZATION_FACECENTERED_STAGGERED_FV_ELEMENT_GEOMETRY_HH 
   18#include <dune/common/rangeutilities.hh> 
   19#include <dune/common/reservedvector.hh> 
   20#include <dune/common/iteratorrange.hh> 
   21#include <dune/common/exceptions.hh> 
   32namespace Detail::FCStaggered {
 
   34template<
class FVElementGeometry, 
class SubControlVolume>
 
   35typename SubControlVolume::Traits::Geometry scvGeometry(
const FVElementGeometry& fvGeometry,
 
   36                                                        const SubControlVolume& scv)
 
   38    typename SubControlVolume::Traits::CornerStorage corners{};
 
   40    const auto elementGeometry = (scv.elementIndex() != fvGeometry.elementIndex()) ?
 
   41        fvGeometry.element().geometry() :
 
   42        fvGeometry.gridGeometry().element(scv.elementIndex()).geometry();
 
   44    const auto center = elementGeometry.center();
 
   45    const auto dofAxis = scv.dofAxis();
 
   46    for (
int i = 0; i < corners.size(); ++i)
 
   48        auto& corner = corners[i];
 
   51        corner = elementGeometry.corner(i);
 
   55        if ((corner[dofAxis] - center[dofAxis]) * scv.directionSign() < 0.0)
 
   56            corner[dofAxis] = 
center[dofAxis];
 
   59    return {corners.front(), corners.back()};
 
   62template<
class FVElementGeometry, 
class SubControlVolumeFace>
 
   63typename SubControlVolumeFace::Traits::Geometry scvfGeometry(
const FVElementGeometry& fvGeometry,
 
   64                                                             const SubControlVolumeFace& scvf)
 
   66    const auto normalAxis = scvf.normalAxis();
 
   67    const auto center = scvf.center();
 
   68    const auto shift = scvf.ipGlobal() - 
center;
 
   70    const auto insideElementIndex = (fvGeometry.scv(scvf.insideScvIdx())).elementIndex();
 
   71    const auto elementGeometry = (insideElementIndex != fvGeometry.elementIndex()) ?
 
   72        fvGeometry.element().geometry() :
 
   73        fvGeometry.gridGeometry().element(insideElementIndex).geometry();
 
   75    auto corners = std::array{
 
   76        elementGeometry.corner(0),
 
   77        elementGeometry.corner(elementGeometry.corners() - 1)
 
   81    for (
int i = 0; i < corners.size(); ++i)
 
   83        auto& corner = corners[i];
 
   84        corner[normalAxis] = 
center[normalAxis];
 
   85        if (scvf.isLateral() && (corner - center)*shift < 0.0)
 
   86            corner[dofAxis] = elementGeometry.center()[dofAxis];
 
   89    auto inPlaneAxes = std::move(std::bitset<SubControlVolumeFace::Traits::dimWorld>{}.set());
 
   90    inPlaneAxes.set(normalAxis, 
false);
 
   92    return {corners[0], corners[1], inPlaneAxes};
 
   96template<
class FVElementGeometry, 
class SubControlVolume>
 
   97const SubControlVolume& outsidePeriodicScv(
const FVElementGeometry& fvGeometry,
 
   98                                           const SubControlVolume& selfScv)
 
  100    assert(fvGeometry.gridGeometry().dofOnPeriodicBoundary(selfScv.dofIndex()));
 
  102    auto localOppositeIndex = FVElementGeometry::GridGeometry::GeometryHelper::localOppositeIdx(selfScv.localDofIndex());
 
  103    const auto& normalScvf =  std::next(scvfs(fvGeometry, selfScv).begin());
 
  106    const auto& orthogonalScvf = fvGeometry.lateralOrthogonalScvf(*normalScvf);
 
  107    const auto orthogonalOutsideScv = fvGeometry.scv(orthogonalScvf.outsideScvIdx());
 
  109    auto outsidePeriodicFVGeometry = 
localView(fvGeometry.gridGeometry());
 
  110    const auto& periodicElement = fvGeometry.gridGeometry().element(orthogonalOutsideScv.elementIndex());
 
  111    outsidePeriodicFVGeometry.bindElement(periodicElement);
 
  113    for (
const auto& outerPeriodicScv : scvs(outsidePeriodicFVGeometry))
 
  114        if (outerPeriodicScv.localDofIndex() == localOppositeIndex)
 
  115            return outerPeriodicScv;
 
  117    DUNE_THROW(Dune::InvalidStateException, 
"No outside periodic scv found");
 
  123template<
class GG, 
bool cachingEnabled>
 
  135    using GridView = 
typename GG::GridView;
 
  137    static constexpr auto numScvsPerElement = GG::StaticInformation::numScvsPerElement;
 
  141    using SubControlVolume = 
typename GG::SubControlVolume;
 
  142    using SubControlVolumeFace = 
typename GG::SubControlVolumeFace;
 
  143    using Element = 
typename GridView::template Codim<0>::Entity;
 
  144    using GridGeometry = GG;
 
  147    static constexpr std::size_t maxNumElementScvs = numScvsPerElement;
 
  150    : gridGeometry_(&gridGeometry)
 
  154    const SubControlVolume& scv(GridIndexType scvIdx)
 const 
  155    { 
return gridGeometry().scv(scvIdx); }
 
  158    const SubControlVolumeFace& scvf(GridIndexType scvfIdx)
 const 
  159    { 
return gridGeometry().scvf(scvfIdx); }
 
  162    const SubControlVolumeFace& lateralOrthogonalScvf(
const SubControlVolumeFace& scvf)
 const 
  164        assert(scvf.isLateral());
 
  165        const auto otherGlobalIdx = scvfIndices_()[GridGeometry::GeometryHelper::lateralOrthogonalScvfLocalIndex(scvf.localIndex())];
 
  166        return gridGeometry().scvf(otherGlobalIdx);
 
  171    const SubControlVolumeFace& frontalScvfOnBoundary(
const SubControlVolume& scv)
 const 
  173        assert(scv.boundary());
 
  176        auto scvfIter = scvfs(*
this, scv).begin();
 
  177        const auto end = scvfs(*
this, scv).end();
 
  178        while (!(scvfIter->isFrontal() && scvfIter->boundary()) && (scvfIter != end))
 
  181        assert(scvfIter->isFrontal());
 
  182        assert(scvfIter->boundary());
 
  192    scvs(
const FaceCenteredStaggeredFVElementGeometry& fvGeometry)
 
  193    { 
return fvGeometry.gridGeometry().scvs(fvGeometry); }
 
  201    scvfs(
const FaceCenteredStaggeredFVElementGeometry& fvGeometry)
 
  203        using IndexContainerType = std::decay_t<
decltype(fvGeometry.scvfIndices_())>;
 
  204        using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, IndexContainerType, ThisType>;
 
  205        return Dune::IteratorRange<ScvfIterator>(ScvfIterator(fvGeometry.scvfIndices_().begin(), fvGeometry),
 
  206                                                 ScvfIterator(fvGeometry.scvfIndices_().end(), fvGeometry));
 
  215    scvfs(
const FaceCenteredStaggeredFVElementGeometry& fvGeometry, 
const SubControlVolume& scv)
 
  217        using IndexContainerType = std::decay_t<
decltype(fvGeometry.scvfIndices_())>;
 
  218        using ScvfIterator = Dumux::SkippingScvfIterator<SubControlVolumeFace, IndexContainerType, ThisType>;
 
  219        auto begin = ScvfIterator::makeBegin(fvGeometry.scvfIndices_(), fvGeometry, scv.index());
 
  220        auto end = ScvfIterator::makeEnd(fvGeometry.scvfIndices_(), fvGeometry, scv.index());
 
  221        return Dune::IteratorRange<ScvfIterator>(begin, end);
 
  225    std::size_t numScv()
 const 
  226    { 
return numScvsPerElement; }
 
  229    std::size_t numScvf()
 const 
  230    { 
return scvfIndices_().size(); }
 
  233    bool hasBoundaryScvf()
 const 
  234    { 
return gridGeometry().hasBoundaryScvf(eIdx_); }
 
  241    FaceCenteredStaggeredFVElementGeometry bind(
const Element& element) &&
 
  244        return std::move(*
this);
 
  248    void bind(
const Element& element) &
 
  249    { this->bindElement(element); }
 
  256    FaceCenteredStaggeredFVElementGeometry bindElement(
const Element& element) &&
 
  258        this->bindElement(element);
 
  259        return std::move(*
this);
 
  263    void bindElement(
const Element& element) &
 
  266        eIdx_ = gridGeometry().elementMapper().index(element);
 
  270    const GridGeometry& gridGeometry()
 const 
  272        assert(gridGeometry_);
 
  273        return *gridGeometry_;
 
  276    std::size_t elementIndex()
 const 
  281    { 
return *elementPtr_; }
 
  284    bool scvfIntegrationPointInConcaveCorner(
const SubControlVolumeFace& scvf)
 const 
  285    { 
return GG::GeometryHelper::scvfIntegrationPointInConcaveCorner(*
this, scvf); }
 
  288    const SubControlVolumeFace& outsideScvfWithSameIntegrationPoint(
const SubControlVolumeFace& scvf)
 const 
  290        const auto& lateralOrthogonalScvf = this->lateralOrthogonalScvf(scvf);
 
  291        assert(!lateralOrthogonalScvf.boundary());
 
  293        const auto otherLocalIdx = GG::GeometryHelper::localIndexOutsideScvfWithSameIntegrationPoint(scvf, scv(scvf.insideScvIdx()));
 
  295        auto outsideFVGeometry = 
localView(gridGeometry());
 
  296        const auto outsideElementIdx = scv(lateralOrthogonalScvf.outsideScvIdx()).elementIndex();
 
  297        outsideFVGeometry.bindElement(gridGeometry().
element(outsideElementIdx));
 
  299        for (
const auto& otherScvf : scvfs(outsideFVGeometry))
 
  300            if (otherScvf.localIndex() == otherLocalIdx)
 
  303        DUNE_THROW(Dune::InvalidStateException, 
"No outside scvf found");
 
  307    const SubControlVolume& outsidePeriodicScv(
const SubControlVolume& selfScv)
 const 
  309        return Detail::FCStaggered::outsidePeriodicScv(*
this, selfScv);
 
  313    typename SubControlVolume::Traits::Geometry geometry(
const SubControlVolume& scv)
 const 
  315        return Detail::FCStaggered::scvGeometry(*
this, scv);
 
  319    typename SubControlVolumeFace::Traits::Geometry geometry(
const SubControlVolumeFace& scvf)
 const 
  321        return Detail::FCStaggered::scvfGeometry(*
this, scvf);
 
  326    const auto& scvfIndices_()
 const 
  328        return gridGeometry().scvfIndicesOfElement(eIdx_);
 
  331    const Element* elementPtr_;
 
  333    const GridGeometry* gridGeometry_;
 
  344    using ThisType = FaceCenteredStaggeredFVElementGeometry<GG, 
false>;
 
  346    using GridView = 
typename GG::GridView;
 
  351    using StaticInfo = 
typename GG::StaticInformation;
 
  352    static constexpr auto dim = StaticInfo::dim;
 
  353    static constexpr auto numScvsPerElement = StaticInfo::numScvsPerElement;
 
  354    static constexpr auto numLateralScvfsPerScv = StaticInfo::numLateralScvfsPerScv;
 
  355    static constexpr auto numLateralScvfsPerElement = StaticInfo::numLateralScvfsPerElement;
 
  356    static constexpr auto minNumScvfsPerElement = StaticInfo::minNumScvfsPerElement;
 
  357    static constexpr auto maxNumScvfsPerElement = StaticInfo::maxNumScvfsPerElement;
 
  363    using SubControlVolume = 
typename GG::SubControlVolume;
 
  364    using SubControlVolumeFace = 
typename GG::SubControlVolumeFace;
 
  365    using Element = 
typename GridView::template Codim<0>::Entity;
 
  366    using GridGeometry = GG;
 
  369    static constexpr std::size_t maxNumElementScvs = numScvsPerElement;
 
  371    FaceCenteredStaggeredFVElementGeometry(
const GridGeometry& gridGeometry)
 
  372    : gridGeometry_(&gridGeometry)
 
  373    , geometryHelper_(gridGeometry.gridView())
 
  377    const SubControlVolumeFace& scvf(
const GridIndexType scvfIdx)
 const 
  378    { 
return scvfs_[findLocalIndex_(scvfIdx, scvfIndices_())]; }
 
  386    scvfs(
const FaceCenteredStaggeredFVElementGeometry& fvGeometry)
 
  388        using Iter = 
typename decltype(fvGeometry.scvfs_)::const_iterator;
 
  389        return Dune::IteratorRange<Iter>(fvGeometry.scvfs_.begin(), fvGeometry.scvfs_.end());
 
  398    scvfs(
const FaceCenteredStaggeredFVElementGeometry& fvGeometry, 
const SubControlVolume& scv)
 
  400        using IndexContainerType = std::decay_t<
decltype(fvGeometry.scvfIndices_())>;
 
  401        using ScvfIterator = Dumux::SkippingScvfIterator<SubControlVolumeFace, IndexContainerType, ThisType>;
 
  402        auto begin = ScvfIterator::makeBegin(fvGeometry.scvfIndices_(), fvGeometry, scv.index());
 
  403        auto end = ScvfIterator::makeEnd(fvGeometry.scvfIndices_(), fvGeometry, scv.index());
 
  404        return Dune::IteratorRange<ScvfIterator>(begin, end);
 
  408    const SubControlVolume& scv(
const GridIndexType scvIdx)
 const 
  410        if (scvIdx >= scvIndicesOfElement_.front() && scvIdx <= scvIndicesOfElement_.back())
 
  411            return scvs_[findLocalIndex_(scvIdx, scvIndicesOfElement_)];
 
  413            return neighborScvs_[findLocalIndex_(scvIdx, neighborScvIndices_)];
 
  422    scvs(
const FaceCenteredStaggeredFVElementGeometry& g)
 
  424        using IteratorType = 
typename std::array<SubControlVolume, 1>::const_iterator;
 
  425        return Dune::IteratorRange<IteratorType>(g.scvs_.begin(), g.scvs_.end());
 
  429    const SubControlVolumeFace& lateralOrthogonalScvf(
const SubControlVolumeFace& scvf)
 const 
  431        assert(scvf.isLateral());
 
  432        const auto otherLocalIdx = GridGeometry::GeometryHelper::lateralOrthogonalScvfLocalIndex(scvf.localIndex());
 
  433        return scvfs_[otherLocalIdx];
 
  437    const SubControlVolumeFace& frontalScvfOnBoundary(
const SubControlVolume& scv)
 const 
  439        assert(scv.boundary());
 
  442        auto scvfIter = scvfs(*
this, scv).begin();
 
  443        const auto end = scvfs(*
this, scv).end();
 
  444        while (!(scvfIter->isFrontal() && scvfIter->boundary()) && (scvfIter != end))
 
  447        assert(scvfIter->isFrontal());
 
  448        assert(scvfIter->boundary());
 
  453    bool hasBoundaryScvf()
 const 
  454    { 
return gridGeometry().hasBoundaryScvf(eIdx_); }
 
  457    std::size_t numScv()
 const 
  458    { 
return numScvsPerElement; }
 
  461    std::size_t numScvf()
 const 
  462    { 
return scvfIndices_().size(); }
 
  469    FaceCenteredStaggeredFVElementGeometry bind(
const Element& element) &&
 
  471        this->bind_(element);
 
  472        return std::move(*
this);
 
  475    void bind(
const Element& element) &
 
  476    { this->bind_(element); }
 
  483    FaceCenteredStaggeredFVElementGeometry bindElement(
const Element& element) &&
 
  485        typename GG::LocalIntersectionMapper localIsMapper;
 
  486        localIsMapper.update(gridGeometry().gridView(), element);
 
  487        this->bindElement_(element, localIsMapper);
 
  488        return std::move(*
this);
 
  491    void bindElement(
const Element& element) &
 
  493        typename GG::LocalIntersectionMapper localIsMapper;
 
  494        localIsMapper.update(gridGeometry().gridView(), element);
 
  495        this->bindElement_(element, localIsMapper);
 
  498    GridIndexType elementIndex()
 const 
  503    { 
return *elementPtr_; }
 
  506    const GridGeometry& gridGeometry()
 const 
  508        assert(gridGeometry_);
 
  509        return *gridGeometry_;
 
  513    bool scvfIntegrationPointInConcaveCorner(
const SubControlVolumeFace& scvf)
 const 
  514    { 
return GG::GeometryHelper::scvfIntegrationPointInConcaveCorner(*
this, scvf); }
 
  518    SubControlVolumeFace outsideScvfWithSameIntegrationPoint(
const SubControlVolumeFace& scvf)
 const 
  520        const SubControlVolumeFace& lateralOrthogonalScvf = this->lateralOrthogonalScvf(scvf);
 
  521        assert(!lateralOrthogonalScvf.boundary());
 
  523        const auto otherLocalIdx = GG::GeometryHelper::localIndexOutsideScvfWithSameIntegrationPoint(scvf, scv(scvf.insideScvIdx()));
 
  525        auto outsideFVGeometry = 
localView(gridGeometry());
 
  526        const auto outsideElementIdx = scv(lateralOrthogonalScvf.outsideScvIdx()).elementIndex();
 
  527        outsideFVGeometry.bindElement(gridGeometry().
element(outsideElementIdx));
 
  529        for (
const auto& otherScvf : scvfs(outsideFVGeometry))
 
  530            if (otherScvf.localIndex() == otherLocalIdx)
 
  533        DUNE_THROW(Dune::InvalidStateException, 
"No outside scvf found");
 
  537    SubControlVolume outsidePeriodicScv(
const SubControlVolume& selfScv)
 const 
  539        return Detail::FCStaggered::outsidePeriodicScv(*
this, selfScv);
 
  543    typename SubControlVolume::Traits::Geometry geometry(
const SubControlVolume& scv)
 const 
  545        return Detail::FCStaggered::scvGeometry(*
this, scv);
 
  549    typename SubControlVolumeFace::Traits::Geometry geometry(
const SubControlVolumeFace& scvf)
 const 
  551        return Detail::FCStaggered::scvfGeometry(*
this, scvf);
 
  557    void bind_(
const Element& element)
 
  559        typename GG::LocalIntersectionMapper localIsMapper;
 
  560        localIsMapper.update(gridGeometry().gridView(), element);
 
  562        bindElement_(element, localIsMapper);
 
  563        neighborScvIndices_.clear();
 
  564        neighborScvs_.clear();
 
  566        for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
 
  568            if (intersection.neighbor())
 
  570                const auto localScvIdx = localIsMapper.realToRefIdx(intersection.indexInInside());
 
  571                const auto localOppositeScvIdx = geometryHelper_.localOppositeIdx(localScvIdx);
 
  572                const auto& neighborElement = intersection.outside();
 
  573                const auto neighborElementIdx = gridGeometry().elementMapper().index(neighborElement);
 
  574                const auto& neighborElementGeometry = neighborElement.geometry();
 
  577                std::array<GridIndexType, numScvsPerElement> globalScvIndicesOfNeighborElement;
 
  578                std::iota(globalScvIndicesOfNeighborElement.begin(), globalScvIndicesOfNeighborElement.end(), neighborElementIdx*numScvsPerElement);
 
  580                typename GG::LocalIntersectionMapper localNeighborIsMapper;
 
  581                localNeighborIsMapper.update(gridGeometry().gridView(), neighborElement);
 
  583                for (
const auto& neighborIntersection : intersections(gridGeometry().gridView(), neighborElement))
 
  585                    const auto localNeighborScvIdx = localNeighborIsMapper.realToRefIdx(neighborIntersection.indexInInside());
 
  586                    if (localNeighborScvIdx != localScvIdx && localNeighborScvIdx != localOppositeScvIdx)
 
  589                        const auto dofIndex = gridGeometry().intersectionMapper().globalIntersectionIndex(neighborElement, neighborIntersection.indexInInside());
 
  590                        neighborScvs_.push_back(SubControlVolume(
 
  591                            neighborElementGeometry,
 
  592                            neighborIntersection.geometry(),
 
  593                            globalScvIndicesOfNeighborElement[localNeighborScvIdx],
 
  598                            onDomainBoundary_(neighborIntersection)
 
  601                        neighborScvIndices_.push_back(globalScvIndicesOfNeighborElement[localNeighborScvIdx]);
 
  609    void bindElement_(
const Element& element, 
const typename GG::LocalIntersectionMapper& localIsMapper)
 
  612        eIdx_ = gridGeometry().elementMapper().index(element);
 
  613        std::iota(scvIndicesOfElement_.begin(), scvIndicesOfElement_.end(), eIdx_*numScvsPerElement);
 
  615        scvfs_.resize(minNumScvfsPerElement);
 
  617        const auto& elementGeometry = 
element.geometry();
 
  619        for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
 
  621            const auto localScvIdx = localIsMapper.realToRefIdx(intersection.indexInInside());
 
  622            auto localScvfIdx = localScvIdx*(1 + numLateralScvfsPerScv);
 
  623            const auto& intersectionGeometry = intersection.geometry();
 
  624            const auto dofIndex = gridGeometry().intersectionMapper().globalIntersectionIndex(element, intersection.indexInInside());
 
  626            scvs_[localScvIdx] = SubControlVolume(
 
  628                intersectionGeometry,
 
  629                scvIndicesOfElement_[localScvIdx],
 
  634                onDomainBoundary_(intersection)
 
  638            const auto localOppositeScvIdx = geometryHelper_.localOppositeIdx(localScvIdx);
 
  639            scvfs_[localScvfIdx] = SubControlVolumeFace(
 
  641                intersectionGeometry,
 
  642                std::array{scvIndicesOfElement_[localScvIdx], scvIndicesOfElement_[localOppositeScvIdx]},
 
  644                scvfIndices_()[localScvfIdx],
 
  645                intersection.centerUnitOuterNormal(),
 
  646                SubControlVolumeFace::FaceType::frontal,
 
  647                SubControlVolumeFace::BoundaryType::interior
 
  652            for (
const auto lateralFacetIndex : Dune::transformedRangeView(geometryHelper_.localLaterFaceIndices(localScvIdx),
 
  653                                                                           [&](
auto&& idx) { return localIsMapper.refToRealIdx(idx) ;})
 
  656                const auto& lateralIntersection = geometryHelper_.intersection(lateralFacetIndex, element);
 
  657                const auto& lateralFacet =  geometryHelper_.facet(lateralFacetIndex, element);
 
  658                const auto& lateralFacetGeometry = lateralFacet.geometry();
 
  661                const auto globalScvIndicesForLateralFace = [&]
 
  663                    const auto globalOutsideScvIdx = [&]
 
  665                        if (lateralIntersection.neighbor())
 
  667                            const auto parallelElemIdx = gridGeometry().elementMapper().index(lateralIntersection.outside());
 
  669                            std::array<GridIndexType, numScvsPerElement> globalScvIndicesOfNeighborElement;
 
  670                            std::iota(globalScvIndicesOfNeighborElement.begin(), globalScvIndicesOfNeighborElement.end(), parallelElemIdx*numScvsPerElement);
 
  671                            return globalScvIndicesOfNeighborElement[localScvIdx];
 
  674                            return gridGeometry().outsideVolVarIndex(scvfIndices_()[localScvfIdx]);
 
  677                    return std::array{scvIndicesOfElement_[localScvIdx], globalOutsideScvIdx};
 
  680                const auto boundaryType = [&]
 
  682                    if (onProcessorBoundary_(lateralIntersection))
 
  683                        return SubControlVolumeFace::BoundaryType::processorBoundary;
 
  684                    else if (onDomainBoundary_(lateralIntersection))
 
  685                        return SubControlVolumeFace::BoundaryType::physicalBoundary;
 
  687                        return SubControlVolumeFace::BoundaryType::interior;
 
  690                scvfs_[localScvfIdx] = SubControlVolumeFace(
 
  692                    intersectionGeometry,
 
  693                    lateralFacetGeometry,
 
  694                    globalScvIndicesForLateralFace, 
 
  696                    scvfIndices_()[localScvfIdx],
 
  697                    lateralIntersection.centerUnitOuterNormal(),
 
  698                    SubControlVolumeFace::FaceType::lateral,
 
  706        auto localScvfIdx = minNumScvfsPerElement;
 
  707        for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
 
  710            if (onDomainBoundary_(intersection))
 
  712                const auto localScvIdx = localIsMapper.realToRefIdx(intersection.indexInInside());
 
  714                scvfs_.push_back(SubControlVolumeFace(
 
  716                    intersection.geometry(),
 
  717                    std::array{scvIndicesOfElement_[localScvIdx], scvIndicesOfElement_[localScvIdx]},
 
  719                    scvfIndices_()[localScvfIdx],
 
  720                    intersection.centerUnitOuterNormal(),
 
  721                    SubControlVolumeFace::FaceType::frontal,
 
  722                    SubControlVolumeFace::BoundaryType::physicalBoundary
 
  728        if constexpr (!ConsistentlyOrientedGrid<typename GridView::Grid>{})
 
  730            static const bool makeConsistentlyOriented = 
getParam<bool>(
"Grid.MakeConsistentlyOriented", 
true);
 
  731            if (makeConsistentlyOriented && scvfs_.size() > minNumScvfsPerElement)
 
  734                std::sort(scvfs_.begin() + minNumScvfsPerElement, scvfs_.end(),
 
  735                    [](
const auto& scvfLeft, 
const auto& scvfRight)
 
  736                    { return scvfLeft.insideScvIdx() < scvfRight.insideScvIdx(); }
 
  742    const auto& scvfIndices_()
 const 
  743    { 
return gridGeometry().scvfIndicesOfElement(eIdx_); }
 
  745    template<
class Entry, 
class Container>
 
  746    const LocalIndexType findLocalIndex_(
const Entry& entry,
 
  747                                         const Container& container)
 const 
  749        auto it = std::find(container.begin(), container.end(), entry);
 
  750        assert(it != container.end() && 
"Could not find the entry! Make sure to properly bind this class!");
 
  751        return std::distance(container.begin(), it);
 
  754    bool onDomainBoundary_(
const typename GridView::Intersection& intersection)
 const 
  756        return !intersection.neighbor() && intersection.boundary();
 
  759    bool onProcessorBoundary_(
const typename GridView::Intersection& intersection)
 const 
  761        return !intersection.neighbor() && !intersection.boundary();
 
  764    Dune::ReservedVector<SubControlVolumeFace, maxNumScvfsPerElement> scvfs_;
 
  766    Dune::ReservedVector<SubControlVolume, numLateralScvfsPerElement> neighborScvs_;
 
  767    Dune::ReservedVector<GridIndexType, numLateralScvfsPerElement> neighborScvIndices_;
 
  769    std::array<SubControlVolume, numScvsPerElement> scvs_;
 
  770    std::array<GridIndexType, numScvsPerElement> scvIndicesOfElement_;
 
  772    const GridGeometry* gridGeometry_;
 
  773    const Element* elementPtr_;
 
  775    typename GridGeometry::GeometryHelper geometryHelper_;
 
Definition discretization/facecentered/staggered/fvelementgeometry.hh:124
Helper type to determine whether a grid is guaranteed to be oriented consistently....
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:26
static std::size_t normalAxis(const Vector &v)
Returns the normal axis index of a unit vector (0 = x, 1 = y, 2 = z)
Definition normalaxis.hh:26
Corners::value_type center(const Corners &corners)
The center of a given list of corners.
Definition center.hh:24
T getParam(Args &&... args)
A free function to get a parameter from the parameter tree singleton.
Definition parameters.hh:139
Base class for the finite volume geometry vector for face-centered staggered models This builds up th...
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
unsigned int LocalIndex
Definition indextraits.hh:28