135    using Scalar = 
typename GridView::ctype;
 
  136    static constexpr auto dim = GridView::dimension;
 
  138    using Element = 
typename GridView::template Codim<0>::Entity;
 
  139    using Intersection = 
typename GridView::Intersection;
 
  140    using GlobalPosition = 
typename Element::Geometry::GlobalCoordinate;
 
  146    static constexpr auto codimIntersection =  1;
 
  147    static constexpr auto numFacets = dim * 2;
 
  148    static constexpr auto numPairs = 2 * (dim - 1);
 
  150    static constexpr bool useHigherOrder = upwindSchemeOrder > 1;
 
  158    , gridView_(gridView)
 
 
  162    template<
class IntersectionMapper>
 
  165        intersection_ = intersection;
 
 
  175        return intersection_.indexInInside();
 
 
  218        if constexpr (useHigherOrder)
 
  219            fillOuterAxisData_();
 
  221        const auto inIdx = intersection_.indexInInside();
 
  222        const auto oppIdx = localOppositeIdx_(inIdx);
 
  225        axisData_.
selfDof = gridView_.indexSet().subIndex(intersection_.inside(), inIdx, codimIntersection);
 
  228        axisData_.
oppositeDof = gridView_.indexSet().subIndex(intersection_.inside(), oppIdx, codimIntersection);
 
  231        const auto self = getFacet_(inIdx, element_);
 
  232        const auto opposite = getFacet_(oppIdx, element_);
 
  242    void fillOuterAxisData_()
 
  248        const auto thisFaceLocalIdx = intersection_.indexInInside();
 
  249        const auto& faceCenterPos = getFacet_(thisFaceLocalIdx, element_).geometry().center();
 
  250        if (intersection_.neighbor())
 
  251            addForwardNeighborAxisData_(intersection_.outside(), 0, thisFaceLocalIdx, faceCenterPos);
 
  254        const auto oppositeFaceLocalIdx = localOppositeIdx_(thisFaceLocalIdx);
 
  255        const auto& oppositeFaceCenterPos = getFacet_(oppositeFaceLocalIdx, element_).geometry().center();
 
  256        for (
const auto& intersection : intersections(gridView_, element_))
 
  258            if (intersection.indexInInside() == oppositeFaceLocalIdx && intersection.neighbor())
 
  260                addBackwardNeighborAxisData_(intersection.outside(), 0, oppositeFaceLocalIdx, oppositeFaceCenterPos);
 
  269    void addForwardNeighborAxisData_(
const Element& neighbor,
 
  271                                     const unsigned int localIntersectionIndex,
 
  272                                     const GlobalPosition& faceCenterPos)
 
  275        axisData_.hasForwardNeighbor.set(
distance, 
true);
 
  276        axisData_.inAxisForwardDofs[
distance] = gridView_.indexSet().subIndex(neighbor, localIntersectionIndex, codimIntersection);
 
  277        const auto& forwardFacePos = getFacet_(localIntersectionIndex, neighbor).geometry().center();
 
  278        axisData_.inAxisForwardDistances[
distance] = (forwardFacePos - faceCenterPos).two_norm();
 
  281        const auto numForwardBackwardAxisDofs = axisData_.inAxisForwardDofs.size();
 
  282        if (
distance >= numForwardBackwardAxisDofs-1)
 
  285        for (
const auto& intersection : intersections(gridView_, neighbor))
 
  287            if (intersection.indexInInside() == localIntersectionIndex && intersection.neighbor())
 
  289                addForwardNeighborAxisData_(intersection.outside(), 
distance+1, localIntersectionIndex, forwardFacePos);
 
  298    void addBackwardNeighborAxisData_(
const Element& neighbor,
 
  300                                      const unsigned int localIntersectionIndex,
 
  301                                      const GlobalPosition& faceCenterPos)
 
  304        axisData_.hasBackwardNeighbor.set(
distance, 
true);
 
  305        axisData_.inAxisBackwardDofs[
distance] = gridView_.indexSet().subIndex(neighbor, localIntersectionIndex, codimIntersection);
 
  306        const auto& backwardFacePos = getFacet_(localIntersectionIndex, neighbor).geometry().center();
 
  307        axisData_.inAxisBackwardDistances[
distance] = (backwardFacePos - faceCenterPos).two_norm();
 
  310        const auto numForwardBackwardAxisDofs = axisData_.inAxisForwardDofs.size();
 
  311        if (
distance >= numForwardBackwardAxisDofs-1)
 
  314        for (
const auto& intersection : intersections(gridView_, neighbor))
 
  316            if (intersection.indexInInside() == localIntersectionIndex && intersection.neighbor())
 
  318                addBackwardNeighborAxisData_(intersection.outside(), 
distance+1, localIntersectionIndex, backwardFacePos);
 
  334        const auto& selfElementCenter = element_.geometry().center();
 
  335        const auto& selfFacetCenter = intersection_.geometry().center();
 
  338        SmallLocalIndexType numPairInnerLateralIdx = 0;
 
  339        for (
const auto& innerElementIntersection : intersections(gridView_, element_))
 
  341            if (facetIsNormal_(innerElementIntersection.indexInInside(), intersection_.indexInInside()))
 
  343                const auto innerElementIntersectionIdx = innerElementIntersection.indexInInside();
 
  344                setLateralPairFirstInfo_(innerElementIntersectionIdx, element_, numPairInnerLateralIdx);
 
  346                const auto distance = innerElementIntersection.geometry().center() - selfElementCenter;
 
  347                pairData_[numPairInnerLateralIdx].lateralStaggeredFaceCenter = selfFacetCenter+
distance;
 
  349                numPairInnerLateralIdx++;
 
  354        SmallLocalIndexType numPairOuterLateralIdx = 0;
 
  355        if (intersection_.neighbor())
 
  358            const auto& directNeighborElement = intersection_.outside();
 
  360            for (
const auto& directNeighborElementIntersection : intersections(gridView_, directNeighborElement))
 
  363                if (facetIsNormal_(directNeighborElementIntersection.indexInInside(), intersection_.indexInOutside()))
 
  365                    const auto directNeighborElemIsIdx = directNeighborElementIntersection.indexInInside();
 
  366                    setLateralPairSecondInfo_(directNeighborElemIsIdx, directNeighborElement, numPairOuterLateralIdx);
 
  367                    numPairOuterLateralIdx++;
 
  373            for (
const auto& intersection : intersections(gridView_, element_))
 
  375                if (facetIsNormal_(intersection.indexInInside(), intersection_.indexInInside()))
 
  377                    assert(!pairData_[numPairOuterLateralIdx].hasOuterLateral);
 
  379                    const auto normalDistanceoffset = selfFacetCenter - selfElementCenter;
 
  380                    pairData_[numPairOuterLateralIdx].lateralDistance = normalDistanceoffset.two_norm();
 
  381                    numPairOuterLateralIdx++;
 
  387        const auto parallelLocalIdx = intersection_.indexInInside();
 
  388        SmallLocalIndexType numPairParallelIdx = 0;
 
  389        for (
const auto& intersection : intersections(gridView_, element_))
 
  391            if (facetIsNormal_(intersection.indexInInside(), parallelLocalIdx))
 
  393                if (intersection.neighbor())
 
  397                    const auto localLateralIntersectionIndex = intersection.indexInInside();
 
  412                   if (intersection_.neighbor())
 
  413                        for (
const auto& outerIntersection : intersections(gridView_, intersection_.outside()))
 
  414                            if (intersection.indexInInside() == outerIntersection.indexInInside())
 
  415                                if (!outerIntersection.neighbor())
 
  416                                    pairData_[numPairParallelIdx].hasHalfParallelNeighbor = 
true;
 
  430                   if (!intersection_.neighbor())
 
  431                        for (
const auto& outerIntersection : intersections(gridView_, intersection.outside()))
 
  432                            if (intersection_.indexInInside() == outerIntersection.indexInInside())
 
  433                                if (outerIntersection.neighbor())
 
  434                                    pairData_[numPairParallelIdx].hasCornerParallelNeighbor = 
true;
 
  437                    addParallelNeighborPairData_(intersection.outside(), 0, localLateralIntersectionIndex, parallelLocalIdx, parallelAxisIdx, numPairParallelIdx);
 
  440                ++numPairParallelIdx;
 
  446    void addParallelNeighborPairData_(
const Element& neighbor,
 
  448                                      const unsigned int localLateralIntersectionIndex,
 
  449                                      const unsigned int parallelLocalIdx,
 
  450                                      const unsigned int parallelAxisIdx,
 
  451                                      const SmallLocalIndexType dataIdx)
 
  454        pairData_[dataIdx].hasParallelNeighbor.set(
distance, 
true);
 
  455        pairData_[dataIdx].parallelDofs[
distance] = gridView_.indexSet().subIndex(neighbor, parallelLocalIdx, codimIntersection);
 
  456        pairData_[dataIdx].parallelCellWidths[
distance] = setParallelPairCellWidths_(neighbor, parallelAxisIdx);
 
  459        const auto numParallelFaces = pairData_[0].parallelCellWidths.size();
 
  464        for (
const auto& lateralIntersection : intersections(gridView_, neighbor))
 
  467            if (lateralIntersection.indexInInside() == localLateralIntersectionIndex)
 
  470                if (lateralIntersection.neighbor())
 
  471                    addParallelNeighborPairData_(lateralIntersection.outside(), 
distance+1,
 
  472                                                 localLateralIntersectionIndex, parallelLocalIdx, parallelAxisIdx, dataIdx);
 
  483    int localOppositeIdx_(
const int idx)
 const 
  485        return (idx % 2) ? (idx - 1) : (idx + 1);
 
  494    bool facetIsNormal_(
const int selfIdx, 
const int otherIdx)
 const 
  496        return !(selfIdx == otherIdx || localOppositeIdx_(selfIdx) == otherIdx);
 
  499    auto getFacet_(
const int localFacetIdx, 
const Element& element)
 const 
  501        return element.template subEntity <1> (localFacetIdx);
 
  505    void setLateralPairFirstInfo_(
const int isIdx, 
const Element& element, 
const int numPairsIdx)
 
  508        pairData_[numPairsIdx].lateralPair.first = gridView_.indexSet().subIndex(element, isIdx, codimIntersection);
 
  511        pairData_[numPairsIdx].localLateralFaceIdx = isIdx;
 
  515    void setLateralPairSecondInfo_(
const int isIdx, 
const Element& element, 
const int numPairsIdx)
 
  518        pairData_[numPairsIdx].hasOuterLateral = 
true;
 
  519        pairData_[numPairsIdx].lateralPair.second = gridView_.indexSet().subIndex(element, isIdx, codimIntersection);
 
  522        const auto& selfFacetCenter = intersection_.geometry().center();
 
  523        const auto& selfElementCenter = element_.geometry().center();
 
  525        const auto& neighborElement = intersection_.outside();
 
  526        const auto& neighborElementCenter = neighborElement.geometry().center();
 
  527        const auto& neighborFacetCenter = getFacet_(intersection_.indexInOutside(), neighborElement).geometry().center();
 
  529        const Scalar insideLateralDistance = (selfFacetCenter - selfElementCenter).two_norm();
 
  530        const Scalar outsideLateralDistance = (neighborFacetCenter - neighborElementCenter).two_norm();
 
  532        pairData_[numPairsIdx].lateralDistance = insideLateralDistance + outsideLateralDistance;
 
  536    Scalar setParallelPairCellWidths_(
const Element& element, 
const int parallelAxisIdx)
 const 
  538        std::vector<GlobalPosition> faces;
 
  539        faces.reserve(numFacets);
 
  540        for (
const auto& intersection : intersections(gridView_, element))
 
  541            faces.push_back(intersection.geometry().center());
 
  543        switch (parallelAxisIdx)
 
  546                return (faces[1] - faces[0]).two_norm();
 
  548                return (faces[3] - faces[2]).two_norm();
 
  552                return (faces[5] - faces[4]).two_norm();
 
  555                DUNE_THROW(Dune::InvalidStateException, 
"Something went terribly wrong");
 
  559    Intersection intersection_; 
 
  560    const Element& element_; 
 
  561    const GridView gridView_; 
 
  563    std::array<PairData, numPairs> pairData_;