From df1d422f50b3784381ce959c2751264969086b80 Mon Sep 17 00:00:00 2001
From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de>
Date: Sun, 13 Nov 2016 19:05:59 +0100
Subject: [PATCH] [staggeredGrid] Improve geometryHelper

* Now calculates the parallel pairs
* Beautify test output
---
 .../staggered/staggeredgeometryhelper.hh      | 167 +++++++++++-------
 .../staggered/test_staggered.cc               |  21 ++-
 2 files changed, 116 insertions(+), 72 deletions(-)

diff --git a/dumux/discretization/staggered/staggeredgeometryhelper.hh b/dumux/discretization/staggered/staggeredgeometryhelper.hh
index 45799401c9..5befac8f4c 100644
--- a/dumux/discretization/staggered/staggeredgeometryhelper.hh
+++ b/dumux/discretization/staggered/staggeredgeometryhelper.hh
@@ -19,7 +19,7 @@
 /*!
  * \file
  * \brief Helper class constructing the dual grid finite volume geometries
- *        for the staggered discretizazion method
+ *        for the staggered discretization method
  */
 #ifndef DUMUX_DISCRETIZATION_STAGGERED_GEOMETRY_HELPER_HH
 #define DUMUX_DISCRETIZATION_STAGGERED_GEOMETRY_HELPER_HH
@@ -36,9 +36,9 @@ namespace Dumux
 template<class Scalar>
 struct PairData
 {
-    std::pair<int,int> parallelPair;
+    int outerParallel;
     std::pair<int,int> normalPair;
-    int localCommonEntIdx;
+    int globalCommonEntIdx;
     Scalar parallelDistance;
     Scalar normalDistance;
 };
@@ -68,13 +68,14 @@ class StaggeredGeometryHelper
 
 
     //TODO include assert that checks for quad geometry
+    static constexpr int codimCommonEntity = 2; //TODO: 3d?
 
 
 public:
 
 
     StaggeredGeometryHelper(const Intersection& intersection, const GridView& gridView)
-    : intersection_(intersection), elementGeometry_(intersection.inside().geometry()), gridView_(gridView), offset_(gridView.size(0))
+    : intersection_(intersection), element_(intersection.inside()), elementGeometry_(element_.geometry()), gridView_(gridView), offset_(gridView.size(0))
     {
         fillPairData();
     }
@@ -102,84 +103,97 @@ public:
 
     void fillPairData()
     {
-        const auto element = intersection_.inside();
-        const auto& referenceElement = ReferenceElements::general(element.geometry().type());
-
+        const auto& referenceElement = ReferenceElements::general(element_.geometry().type());
         const int indexInInside = intersection_.indexInInside();
 
+        // initialize outerParallel (in boundary case, where there is no outer parallel dof)
+        pairData_[0].outerParallel = 0;
+        pairData_[1].outerParallel = 0;
 
-        // store the element's own face info first
-        pairData_[0].parallelPair.first = dofIdxSelf();
-        pairData_[1].parallelPair.first = dofIdxSelf();
-
+        // set the inner parts of the normal pairs
         setInnerNormalPairs_(indexInInside);
 
-
-
-        // go into the direct neigbor element
+        // go into the direct neighbor element
         if(intersection_.neighbor())
         {
-            const int neighborIsIdx = intersection_.indexInOutside();
-
+            // the direct neighbor element and the respective intersection index
             const auto& directNeighbor = intersection_.outside();
 
-
-            for(const auto& is : intersections(gridView_, directNeighbor))
+            for(const auto& neighborIntersection : intersections(gridView_, directNeighbor))
             {
-                constexpr int codimCommonEntity = 2;// TODO: 3d?
-
-                auto isNormalSide = [&](const int idx)
-                {
-                    return !(idx == neighborIsIdx || localOppositeIdx_(idx) == neighborIsIdx);
-                };
-
-                auto localToGlobalEntityIdx = [&](const int localIdx)
-                {
-                    return gridView_.indexSet().subIndex(directNeighbor, localIdx, codimCommonEntity);
-                };
-                // skip the directly neighboring face itself
-                if(isNormalSide(is.indexInInside()))
+                // skip the directly neighboring face itself and its opposing one
+                if(neighborIntersectionNormalSide_(neighborIntersection.indexInInside(), intersection_.indexInOutside()))
                 {
                     // get facet
-//                     const auto& facet = directNeighbor.template subEntity < 1 > (is.indexInInside());
-//                     std::cout <<
+//                    const auto& facet = directNeighbor.template subEntity < 1 > (neighborIntersection.indexInInside());
 
                     // iterate over facets sub-entities // TODO: get number correctly
                     for(int i = 0; i < 2; ++i)
                     {
-                        int localCommonEntIdx = referenceElement.subEntity(is.indexInInside(), 1, i, dim);
-                        const auto& commonEnt = directNeighbor.template subEntity < codimCommonEntity > (localCommonEntIdx);
+                        int localCommonEntIdx = referenceElement.subEntity(neighborIntersection.indexInInside(), 1, i, dim);
+                        // const auto& commonEnt = directNeighbor.template subEntity < codimCommonEntity > (localCommonEntIdx);
 
 //                         int globalCommonEntIdx = gridView_.indexSet().subIndex(directNeighbor, localCommonEntIdx, codimCommonEntity);
-                        int globalCommonEntIdx = localToGlobalEntityIdx(localCommonEntIdx);
+                        // int globalCommonEntIdx = localToGlobalEntityIdx(localCommonEntIdx);
+                        int globalCommonEntIdx = localToGlobalEntityIdx_(localCommonEntIdx, directNeighbor);
 
 //                         int dofIdx = gridView_.indexSet().index(commonEnt);
 
 //                         if(globalCommonEntIdx != dofIdx)
 //                             std::cout << "error!";
 
-                        std::cout << "pos: " << commonEnt.geometry().center() << std::endl;
+                        // std::cout << "pos: " << commonEnt.geometry().center() << std::endl;
 
-                        if(globalCommonEntIdx == localToGlobalEntityIdx(pairData_[0].localCommonEntIdx))
+                        if(globalCommonEntIdx == pairData_[0].globalCommonEntIdx)
                         {
-                            pairData_[0].normalPair.second = gridView_.indexSet().subIndex(directNeighbor, is.indexInInside(), dim-1) + offset_;
+                            pairData_[0].normalPair.second = gridView_.indexSet().subIndex(directNeighbor, neighborIntersection.indexInInside(), dim-1) + offset_;
                         }
-                        if(globalCommonEntIdx == localToGlobalEntityIdx(pairData_[1].localCommonEntIdx))
+                        if(globalCommonEntIdx == pairData_[1].globalCommonEntIdx)
                         {
-                            pairData_[1].normalPair.second = gridView_.indexSet().subIndex(directNeighbor, is.indexInInside(), dim-1) + offset_;
+                            pairData_[1].normalPair.second = gridView_.indexSet().subIndex(directNeighbor, neighborIntersection.indexInInside(), dim-1) + offset_;
                         }
                     }
 
-                    std::cout << "inters: " << intersection_.geometry().center() <<
-                    " || side : " << is.geometry().center() << std::endl;
+                    // std::cout << "inters: " << intersection_.geometry().center() <<
+                    // " || side : " << neighborIntersection.geometry().center() << std::endl;
 
+                    // std::cout << "in element " << gridView_.indexSet().index(intersection_.inside()) << ", direct neighbor: " <<  gridView_.indexSet().index(directNeighbor)
+                    //           << std::endl;
 
-                }
 
+                    // go into the adjacent neighbor element
+                    if(neighborIntersection.neighbor())
+                    {
+                        const auto& diagonalNeighbor = neighborIntersection.outside();
+                        for(const auto& dIs : intersections(gridView_, diagonalNeighbor))
+                        {
+                            if(neighborIntersectionNormalSide_(dIs.indexInInside(), neighborIntersection.indexInOutside()))
+                            {
+                                for(int i = 0; i < 2; ++i)
+                                {
+                                    int localCommonEntIdx = referenceElement.subEntity(dIs.indexInInside(), 1, i, dim);
+                                    int globalCommonEntIdx = localToGlobalEntityIdx_(localCommonEntIdx, diagonalNeighbor);
+
+                                    // const auto& commonEnt = diagonalNeighbor.template subEntity < codimCommonEntity > (localCommonEntIdx);
+                                    // std::cout << "globalCommEnt:" << commonEnt.geometry().center() << std::endl;
+                                    //
+                                    // int dofIdx = gridView_.indexSet().index(commonEnt);
+                                    // if(globalCommonEntIdx != dofIdx)
+                                    //                             std::cout << "error!";
+
+
+                                    if(globalCommonEntIdx == pairData_[0].globalCommonEntIdx)
+                                        pairData_[0].outerParallel = gridView_.indexSet().subIndex(diagonalNeighbor, dIs.indexInInside(), dim-1) + offset_;
+
+                                    if(globalCommonEntIdx == pairData_[1].globalCommonEntIdx)
+                                        pairData_[1].outerParallel = gridView_.indexSet().subIndex(diagonalNeighbor, dIs.indexInInside(), dim-1) + offset_;
+                                }
+                            }
+                        }
+                    }
+                }
             }
         }
-
-//TODO: fill parallel faces
     }
 
 private:
@@ -189,48 +203,64 @@ private:
         return (idx % 2) ? (idx - 1) : (idx + 1);
     }
 
+    bool neighborIntersectionNormalSide_(const int isIdx, const int neighborIsIdx) const
+    {
+        return !(isIdx == neighborIsIdx || localOppositeIdx_(isIdx) == neighborIsIdx);
+    };
+
+    int localToGlobalEntityIdx_(const int localIdx, const Element& element)
+    {
+        return gridView_.indexSet().subIndex(element, localIdx, codimCommonEntity);
+    };
+
 
     template<class G = GridView>
     typename std::enable_if<G::dimension == 2, void>::type
-    setInnerNormalPairs_(const int isIdx)
+    setInnerNormalPairs_(const int directNeighborIsIdx)
     {
-        auto& data1 = pairData_[0];
-        auto& data2 = pairData_[1];
+        int normalLocalDofIdx1;
+        int normalLocalDofIdx2;
+        int localCommonEntIdx1;
+        int localCommonEntIdx2;
 
-        switch(isIdx)
+        switch(directNeighborIsIdx)
         {
             case 0:
-                data1.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 3, dim-1) + offset_;
-                data2.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 2, dim-1) + offset_;
-                data1.localCommonEntIdx = 2;
-                data2.localCommonEntIdx = 0;
+                normalLocalDofIdx1 = 3;
+                normalLocalDofIdx2 = 2;
+                localCommonEntIdx1 = 2;
+                localCommonEntIdx2 = 0;
                 break;
             case 1:
-                data1.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 2, dim-1) + offset_;
-                data2.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 3, dim-1) + offset_;
-                data1.localCommonEntIdx = 1;
-                data2.localCommonEntIdx = 3;
+                normalLocalDofIdx1 = 2;
+                normalLocalDofIdx2 = 3;
+                localCommonEntIdx1 = 1;
+                localCommonEntIdx2 = 3;
                 break;
             case 2:
-                data1.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 0, dim-1) + offset_;
-                data2.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 1, dim-1) + offset_;
-                data1.localCommonEntIdx = 0;
-                data2.localCommonEntIdx = 1;
+                normalLocalDofIdx1 = 0;
+                normalLocalDofIdx2 = 1;
+                localCommonEntIdx1 = 0;
+                localCommonEntIdx2 = 1;
                 break;
             case 3:
-                data1.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 1, dim-1) + offset_;
-                data2.normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), 0, dim-1) + offset_;
-                data1.localCommonEntIdx = 3;
-                data2.localCommonEntIdx = 2;
+                normalLocalDofIdx1 = 1;
+                normalLocalDofIdx2 = 0;
+                localCommonEntIdx1 = 3;
+                localCommonEntIdx2 = 2;
                 break;
             default:
-                DUNE_THROW(Dune::InvalidStateException, "foo");
+                DUNE_THROW(Dune::InvalidStateException, "Something went terribly wrong");
         }
+        pairData_[0].normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), normalLocalDofIdx1, dim-1) + offset_;
+        pairData_[1].normalPair.first = gridView_.indexSet().subIndex(intersection_.inside(), normalLocalDofIdx2, dim-1) + offset_;
+        pairData_[0].globalCommonEntIdx = gridView_.indexSet().subIndex(intersection_.inside(), localCommonEntIdx1, codimCommonEntity);
+        pairData_[1].globalCommonEntIdx = gridView_.indexSet().subIndex(intersection_.inside(), localCommonEntIdx2, codimCommonEntity);
     }
 
     template<class G = GridView>
     typename std::enable_if<G::dimension == 3, void>::type
-    setInnerNormalPairs_(const int isIdx)
+    setInnerNormalPairs_(const int directNeighborIsIdx)
     {
         // TODO: 3D
         DUNE_THROW(Dune::NotImplemented, "3d helper not ready yet");
@@ -238,6 +268,7 @@ private:
 
 
     const Intersection& intersection_;
+    const Element& element_;
     const typename Element::Geometry& elementGeometry_; //! Reference to the element geometry
     const GridView gridView_;
     const int offset_;
diff --git a/test/discretization/staggered/test_staggered.cc b/test/discretization/staggered/test_staggered.cc
index 9998cc4697..167d689a58 100644
--- a/test/discretization/staggered/test_staggered.cc
+++ b/test/discretization/staggered/test_staggered.cc
@@ -25,6 +25,7 @@
 
 #include <iostream>
 #include <utility>
+#include <iomanip>
 
 #include <dune/common/test/iteratortest.hh>
 #include <dune/grid/utility/structuredgridfactory.hh>
@@ -108,6 +109,12 @@ int main (int argc, char *argv[]) try
     GlobalFVGeometry global(leafGridView);
     global.update(problem);
 
+    std::cout << "Abbreviatons:\n"
+              << "ip - global postition of face center\n"
+              << "face - global face index\n"
+              << "self/oppo - global dofIdx on intersection (self/opposite)\n"
+              << "norm in/out - global dofIdx on side normal to intersection (within own element / in adjacent element)" << std::endl;
+
     // iterate over elements. For every element get fv geometry and loop over scvs and scvfaces
     for (const auto& element : elements(leafGridView))
     {
@@ -131,12 +138,18 @@ int main (int argc, char *argv[]) try
         if(0 != testForwardIterator(range2.begin(), range2.end(), op2))
             DUNE_THROW(Dune::Exception, "Iterator does not fulfill the forward iterator concept");
 
-//TODO: beautify output
+
         for (auto&& scvf : scvfs(fvGeometry))
         {
-            std::cout << "-- scvf " << scvf.index() << " ip at: " << scvf.ipGlobal() << ", self: " << scvf.dofIndexSelf() << ", opposite: " << scvf.dofIndexOpposite() << ", side1 in: " << scvf.pairData(0).normalPair.first << ", side2  in: " << scvf.pairData(1).normalPair.first << " , side1 out: " <<  scvf.pairData(0).normalPair.second
-            << ", side2out: " << scvf.pairData(1).normalPair.second;
-            if (scvf.boundary()) std::cout << " (on boundary).";
+            std::cout <<  std::fixed << std::left << std::setprecision(2)
+            << "ip "<< scvf.ipGlobal()
+            << "; face "  << std::setw(3)  << scvf.index()
+            << "; self/oppo " << std::setw(3) << scvf.dofIndexSelf() << "/" << std::setw(3) <<scvf.dofIndexOpposite()
+            << ", norm1 in/out " << std::setw(3) << scvf.pairData(0).normalPair.first << "/" << std::setw(3) << scvf.pairData(0).normalPair.second
+            << ", norm2 in/out " << std::setw(3) << scvf.pairData(1).normalPair.first << "/" << std::setw(3) << scvf.pairData(1).normalPair.second
+            << ", par1 in/out " << std::setw(3) << scvf.dofIndexSelf() << "/" << std::setw(3) << scvf.pairData(0).outerParallel
+            << ", par2 in/out " << std::setw(3) << scvf.dofIndexSelf() << "/" << std::setw(3) << scvf.pairData(1).outerParallel;
+            if (scvf.boundary()) std::cout << " (on boundary)";
             std::cout << std::endl;
         }
     }
-- 
GitLab