14#ifndef DUMUX_DISCRETIZATION_CCTPFA_FV_ELEMENT_GEOMETRY_HH 
   15#define DUMUX_DISCRETIZATION_CCTPFA_FV_ELEMENT_GEOMETRY_HH 
   23#include <dune/common/exceptions.hh> 
   25#include <dune/common/iteratorrange.hh> 
   32template<
class Gr
idIndexType>
 
   34                    const std::vector<GridIndexType>& indices)
 
   36    auto it = std::find(indices.begin(), indices.end(), idx);
 
   37    assert(it != indices.end() && 
"Could not find the scv/scvf! Make sure to properly bind this class!");
 
   38    return std::distance(indices.begin(), it);
 
 
 
   52template<
class GG, 
bool enableGr
idGeometryCache>
 
   65    using GridView = 
typename GG::GridView;
 
   71    using Element = 
typename GridView::template Codim<0>::Entity;
 
   73    using SubControlVolume = 
typename GG::SubControlVolume;
 
   75    using SubControlVolumeFace = 
typename GG::SubControlVolumeFace;
 
   77    using GridGeometry = GG;
 
   80    static constexpr std::size_t maxNumElementScvs = 1;
 
   82    static constexpr std::size_t maxNumElementScvfs = 2*GridView::dimension;
 
   86    : gridGeometryPtr_(&gridGeometry) {}
 
   90    const SubControlVolume& scv(GridIndexType scvIdx)
 const 
   92        return gridGeometry().scv(scvIdx);
 
   97    const SubControlVolumeFace& scvf(GridIndexType scvfIdx)
 const 
   99        return gridGeometry().scvf(scvfIdx);
 
  104    const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx, 
unsigned int outsideScvIdx = 0)
 const 
  106        return gridGeometry().flipScvf(scvfIdx, outsideScvIdx);
 
  114    friend inline Dune::IteratorRange< ScvIterator<SubControlVolume, std::array<GridIndexType, 1>, ThisType> >
 
  115    scvs(
const CCTpfaFVElementGeometry& fvGeometry)
 
  117        using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::array<GridIndexType, 1>, ThisType>;
 
  118        return Dune::IteratorRange<ScvIterator>(ScvIterator(fvGeometry.scvIndices_.begin(), fvGeometry),
 
  119                                                ScvIterator(fvGeometry.scvIndices_.end(), fvGeometry));
 
  127    friend inline Dune::IteratorRange< ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType> >
 
  128    scvfs(
const CCTpfaFVElementGeometry& fvGeometry)
 
  130        const auto& g = fvGeometry.gridGeometry();
 
  131        const auto scvIdx = fvGeometry.scvIndices_[0];
 
  132        using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType>;
 
  133        return Dune::IteratorRange<ScvfIterator>(ScvfIterator(g.scvfIndicesOfScv(scvIdx).begin(), fvGeometry),
 
  134                                                 ScvfIterator(g.scvfIndicesOfScv(scvIdx).end(), fvGeometry));
 
  138    std::size_t numScv()
 const 
  140        return scvIndices_.size();
 
  144    std::size_t numScvf()
 const 
  146        return gridGeometry().scvfIndicesOfScv(scvIndices_[0]).size();
 
  154    CCTpfaFVElementGeometry bind(
const Element& element) &&
 
  156        this->bindElement(element);
 
  157        return std::move(*
this);
 
  160    void bind(
const Element& element) &
 
  162        this->bindElement(element);
 
  170    CCTpfaFVElementGeometry bindElement(
const Element& element) &&
 
  172        this->bindElement(element);
 
  173        return std::move(*
this);
 
  177    void bindElement(
const Element& element) &
 
  180        scvIndices_[0] = gridGeometry().elementMapper().index(*element_);
 
  185    { 
return static_cast<bool>(element_); }
 
  189    { 
return *element_; }
 
  192    const GridGeometry& gridGeometry()
 const 
  193    { 
return *gridGeometryPtr_; }
 
  196    bool hasBoundaryScvf()
 const 
  197    { 
return gridGeometry().hasBoundaryScvf(scvIndices_[0]); }
 
  199    typename Element::Geometry geometry(
const SubControlVolume& scv)
 const 
  200    { 
return gridGeometryPtr_->element(scv.dofIndex()).geometry(); }
 
  202    typename GridView::Intersection::Geometry geometry(
const SubControlVolumeFace& scvf)
 const 
  204        const auto element = gridGeometryPtr_->element(scvf.insideScvIdx());
 
  205        const auto& scvfIndices = gridGeometryPtr_->scvfIndicesOfScv(scvf.insideScvIdx());
 
  207        LocalIndexType localIdx = 0;
 
  208        for (
const auto& intersection : intersections(gridGeometryPtr_->gridView(), element))
 
  210            if (intersection.neighbor() || intersection.boundary())
 
  212                if (localIdx == localScvfIdx)
 
  213                    return intersection.geometry();
 
  219        DUNE_THROW(Dune::InvalidStateException, 
"Could not find scvf geometry");
 
  224    std::optional<Element> element_;
 
  225    std::array<GridIndexType, 1> scvIndices_;
 
  226    const GridGeometry* gridGeometryPtr_;
 
  237    using ThisType = CCTpfaFVElementGeometry<GG, false>;
 
  238    using GridView = 
typename GG::GridView;
 
  242    static const int dim = GridView::dimension;
 
  243    static const int dimWorld = GridView::dimensionworld;
 
  247    using Element = 
typename GridView::template Codim<0>::Entity;
 
  249    using SubControlVolume = 
typename GG::SubControlVolume;
 
  251    using SubControlVolumeFace = 
typename GG::SubControlVolumeFace;
 
  253    using GridGeometry = GG;
 
  255    static constexpr std::size_t maxNumElementScvs = 1;
 
  257    static constexpr std::size_t maxNumElementScvfs = 2*dim;
 
  260    CCTpfaFVElementGeometry(
const GridGeometry& gridGeometry)
 
  261    : gridGeometryPtr_(&gridGeometry) {}
 
  265    const SubControlVolume& scv(GridIndexType scvIdx)
 const 
  267        if (scvIdx == scvIndices_[0])
 
  275    const SubControlVolumeFace& scvf(GridIndexType scvfIdx)
 const 
  277        auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
 
  278        if (it != scvfIndices_.end())
 
  279            return scvfs_[std::distance(scvfIndices_.begin(), it)];
 
  286    const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx, 
unsigned int outsideScvIdx = 0)
 const 
  288        auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
 
  289        if (it != scvfIndices_.end())
 
  291            const auto localScvfIdx = std::distance(scvfIndices_.begin(), it);
 
  292            return neighborScvfs_[flippedScvfIndices_[localScvfIdx][outsideScvIdx]];
 
  297            const auto localFlippedIndex = flippedNeighborScvfIndices_[localScvfIdx][outsideScvIdx];
 
  298            if (localFlippedIndex < scvfs_.size())
 
  299                return scvfs_[localFlippedIndex];
 
  301                return neighborScvfs_[localFlippedIndex - scvfs_.size()];
 
  310    friend inline Dune::IteratorRange<typename std::array<SubControlVolume, 1>::const_iterator>
 
  311    scvs(
const ThisType& g)
 
  313        using IteratorType = 
typename std::array<SubControlVolume, 1>::const_iterator;
 
  314        return Dune::IteratorRange<IteratorType>(g.scvs_.begin(), g.scvs_.end());
 
  322    friend inline Dune::IteratorRange<typename std::vector<SubControlVolumeFace>::const_iterator>
 
  323    scvfs(
const ThisType& g)
 
  325        using IteratorType = 
typename std::vector<SubControlVolumeFace>::const_iterator;
 
  326        return Dune::IteratorRange<IteratorType>(g.scvfs_.begin(), g.scvfs_.end());
 
  330    std::size_t numScv()
 const 
  331    { 
return scvs_.size(); }
 
  334    std::size_t numScvf()
 const 
  335    { 
return scvfs_.size(); }
 
  342    CCTpfaFVElementGeometry bind(
const Element& element) &&
 
  344        this->bind_(element);
 
  345        return std::move(*
this);
 
  348    void bind(
const Element& element) &
 
  350        this->bind_(element);
 
  358    CCTpfaFVElementGeometry bindElement(
const Element& element) &&
 
  360        this->bindElement_(element);
 
  361        return std::move(*
this);
 
  364    void bindElement(
const Element& element) &
 
  366        this->bindElement_(element);
 
  371    { 
return static_cast<bool>(element_); }
 
  375    { 
return *element_; }
 
  378    const GridGeometry& gridGeometry()
 const 
  379    { 
return *gridGeometryPtr_; }
 
  382    bool hasBoundaryScvf()
 const 
  383    { 
return hasBoundaryScvf_; }
 
  385    typename Element::Geometry geometry(
const SubControlVolume& scv)
 const 
  386    { 
return gridGeometryPtr_->element(scv.dofIndex()).geometry(); }
 
  388    typename GridView::Intersection::Geometry geometry(
const SubControlVolumeFace& scvf)
 const 
  390        const auto element = gridGeometryPtr_->element(scvf.insideScvIdx());
 
  391        const auto& scvfIndices = gridGeometryPtr_->scvfIndicesOfScv(scvf.insideScvIdx());
 
  393        LocalIndexType localIdx = 0;
 
  394        for (
const auto& intersection : intersections(gridGeometryPtr_->gridView(), element))
 
  396            if (intersection.neighbor() || intersection.boundary())
 
  398                if (localIdx == localScvfIdx)
 
  399                    return intersection.geometry();
 
  405        DUNE_THROW(Dune::InvalidStateException, 
"Could not find scvf geometry");
 
  411    void bind_(
const Element& element)
 
  413        bindElement_(element);
 
  415        neighborScvs_.reserve(
element.subEntities(1));
 
  416        neighborScvfIndices_.reserve(
element.subEntities(1));
 
  417        neighborScvfs_.reserve(
element.subEntities(1));
 
  419        std::vector<GridIndexType> handledNeighbors;
 
  420        handledNeighbors.reserve(
element.subEntities(1));
 
  422        for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
 
  425            if (intersection.neighbor())
 
  427                const auto outside = intersection.outside();
 
  428                const auto outsideIdx = gridGeometry().elementMapper().index(outside);
 
  431                if ( std::find(handledNeighbors.begin(), handledNeighbors.end(), outsideIdx) == handledNeighbors.end() )
 
  433                    makeNeighborGeometries(outside, outsideIdx);
 
  434                    handledNeighbors.push_back(outsideIdx);
 
  440        if (dim < dimWorld || gridGeometry().isPeriodic())
 
  442            flippedScvfIndices_.resize(scvfs_.size());
 
  443            for (
unsigned int localScvfIdx = 0; localScvfIdx < scvfs_.size(); ++localScvfIdx)
 
  445                const auto& scvf = scvfs_[localScvfIdx];
 
  449                flippedScvfIndices_[localScvfIdx].resize(scvf.numOutsideScvs());
 
  450                for (
unsigned int localOutsideScvIdx = 0; localOutsideScvIdx < scvf.numOutsideScvs(); ++localOutsideScvIdx)
 
  452                    const auto globalOutsideScvIdx = scvf.outsideScvIdx(localOutsideScvIdx);
 
  453                    for (
unsigned int localNeighborScvfIdx = 0; localNeighborScvfIdx < neighborScvfs_.size(); ++localNeighborScvfIdx)
 
  455                        if (neighborScvfs_[localNeighborScvfIdx].insideScvIdx() == globalOutsideScvIdx)
 
  457                            flippedScvfIndices_[localScvfIdx][localOutsideScvIdx] = localNeighborScvfIdx;
 
  464            flippedNeighborScvfIndices_.resize(neighborScvfs_.size());
 
  465            for (
unsigned int localScvfIdx = 0; localScvfIdx < neighborScvfs_.size(); ++localScvfIdx)
 
  467                const auto& neighborScvf = neighborScvfs_[localScvfIdx];
 
  468                flippedNeighborScvfIndices_[localScvfIdx].resize(neighborScvf.numOutsideScvs());
 
  469                for (
unsigned int localOutsideScvIdx = 0; localOutsideScvIdx < neighborScvf.numOutsideScvs(); ++localOutsideScvIdx)
 
  471                    flippedNeighborScvfIndices_[localScvfIdx][localOutsideScvIdx] = findFlippedScvfIndex_(neighborScvf.insideScvIdx(), neighborScvf.outsideScvIdx(localOutsideScvIdx));
 
  478    void bindElement_(
const Element& element)
 
  482        scvfs_.reserve(
element.subEntities(1));
 
  483        scvfIndices_.reserve(
element.subEntities(1));
 
  484        makeElementGeometries(element);
 
  487    GridIndexType findFlippedScvfIndex_(GridIndexType insideScvIdx, GridIndexType globalOutsideScvIdx)
 
  489        for (
unsigned int localNeighborScvfIdx = 0; localNeighborScvfIdx < neighborScvfs_.size(); ++localNeighborScvfIdx)
 
  491            if (neighborScvfs_[localNeighborScvfIdx].insideScvIdx() == globalOutsideScvIdx)
 
  493                return scvfs_.size() + localNeighborScvfIdx;
 
  498        for (
unsigned int localOutsideScvfIdx = 0; localOutsideScvfIdx < scvfs_.size(); ++localOutsideScvfIdx)
 
  500            const auto& outsideScvf = scvfs_[localOutsideScvfIdx];
 
  501            for (
unsigned int j = 0; j < outsideScvf.numOutsideScvs(); ++j)
 
  503                if (outsideScvf.outsideScvIdx(j) == insideScvIdx)
 
  505                    return localOutsideScvfIdx;
 
  510        DUNE_THROW(Dune::InvalidStateException, 
"No flipped version of this scvf found!");
 
  514    void makeElementGeometries(
const Element& element)
 
  516        using ScvfGridIndexStorage = 
typename SubControlVolumeFace::Traits::GridIndexStorage;
 
  518        const auto eIdx = gridGeometry().elementMapper().index(element);
 
  519        scvs_[0] = SubControlVolume(
element.geometry(), eIdx);
 
  520        scvIndices_[0] = eIdx;
 
  522        const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdx);
 
  523        const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx);
 
  528        std::vector<bool> handledScvf;
 
  530            handledScvf.resize(
element.subEntities(1), 
false);
 
  533        for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
 
  536                if (handledScvf[intersection.indexInInside()])
 
  539            const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter];
 
  540            if (intersection.neighbor() || intersection.boundary())
 
  542                ScvfGridIndexStorage scvIndices;
 
  543                scvIndices.resize(scvfNeighborVolVarIndices.size() + 1);
 
  544                scvIndices[0] = eIdx;
 
  545                std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1);
 
  547                const bool onBoundary = intersection.boundary() && !intersection.neighbor();
 
  548                hasBoundaryScvf_ = (hasBoundaryScvf_ || onBoundary);
 
  550                scvfs_.emplace_back(intersection,
 
  551                                    intersection.geometry(),
 
  552                                    scvFaceIndices[scvfCounter],
 
  555                scvfIndices_.emplace_back(scvFaceIndices[scvfCounter]);
 
  560                    handledScvf[intersection.indexInInside()] = 
true;
 
  566    void makeNeighborGeometries(
const Element& element, 
const GridIndexType eIdx)
 
  568        using ScvfGridIndexStorage = 
typename SubControlVolumeFace::Traits::GridIndexStorage;
 
  571        neighborScvs_.emplace_back(
element.geometry(), eIdx);
 
  572        neighborScvIndices_.push_back(eIdx);
 
  574        const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdx);
 
  575        const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx);
 
  580        std::vector<bool> handledScvf;
 
  582            handledScvf.resize(
element.subEntities(1), 
false);
 
  585        for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
 
  588                if (handledScvf[intersection.indexInInside()])
 
  591            if (intersection.neighbor())
 
  594                const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter];
 
  595                if (scvfNeighborVolVarIndices[0] < gridGeometry().gridView().size(0))
 
  600                        if (scvfNeighborVolVarIndices[0] == gridGeometry().elementMapper().index(*element_))
 
  602                            ScvfGridIndexStorage scvIndices({eIdx, scvfNeighborVolVarIndices[0]});
 
  603                            neighborScvfs_.emplace_back(intersection,
 
  604                                                        intersection.geometry(),
 
  605                                                        scvFaceIndices[scvfCounter],
 
  609                            neighborScvfIndices_.push_back(scvFaceIndices[scvfCounter]);
 
  618                        for (
unsigned outsideScvIdx = 0; outsideScvIdx < scvfNeighborVolVarIndices.size(); ++outsideScvIdx)
 
  620                            if (scvfNeighborVolVarIndices[outsideScvIdx] == gridGeometry().elementMapper().index(*element_))
 
  622                                ScvfGridIndexStorage scvIndices;
 
  623                                scvIndices.resize(scvfNeighborVolVarIndices.size() + 1);
 
  624                                scvIndices[0] = eIdx;
 
  625                                std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1);
 
  626                                neighborScvfs_.emplace_back(intersection,
 
  627                                                            intersection.geometry(),
 
  628                                                            scvFaceIndices[scvfCounter],
 
  632                                neighborScvfIndices_.push_back(scvFaceIndices[scvfCounter]);
 
  640                        handledScvf[intersection.indexInInside()] = 
true;
 
  647            else if (intersection.boundary())
 
  650                    handledScvf[intersection.indexInInside()] = 
true;
 
  659        scvfIndices_.clear();
 
  661        flippedScvfIndices_.clear();
 
  663        neighborScvIndices_.clear();
 
  664        neighborScvfIndices_.clear();
 
  665        neighborScvs_.clear();
 
  666        neighborScvfs_.clear();
 
  667        flippedNeighborScvfIndices_.clear();
 
  669        hasBoundaryScvf_ = 
false;
 
  672    std::optional<Element> element_; 
 
  673    const GridGeometry* gridGeometryPtr_;  
 
  676    std::array<GridIndexType, 1> scvIndices_;
 
  677    std::array<SubControlVolume, 1> scvs_;
 
  679    std::vector<GridIndexType> scvfIndices_;
 
  680    std::vector<SubControlVolumeFace> scvfs_;
 
  681    std::vector<std::vector<GridIndexType>> flippedScvfIndices_;
 
  683    std::vector<GridIndexType> neighborScvIndices_;
 
  684    std::vector<SubControlVolume> neighborScvs_;
 
  686    std::vector<GridIndexType> neighborScvfIndices_;
 
  687    std::vector<SubControlVolumeFace> neighborScvfs_;
 
  688    std::vector<std::vector<GridIndexType>> flippedNeighborScvfIndices_;
 
  690    bool hasBoundaryScvf_ = 
false;
 
Stencil-local finite volume geometry (scvs and scvfs) for cell-centered TPFA models This builds up th...
Definition discretization/cellcentered/tpfa/fvelementgeometry.hh:53
Definition discretization/cellcentered/tpfa/fvelementgeometry.hh:30
auto findLocalIndex(const GridIndexType idx, const std::vector< GridIndexType > &indices)
Definition discretization/cellcentered/tpfa/fvelementgeometry.hh:33
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