From ba299b504f64b638da8416f3a590686cb42e326a Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de> Date: Sat, 12 Nov 2016 12:59:16 +0100 Subject: [PATCH] [staggeredGrid] Improve helper class *Now finds adjacent normal faces *Put some output in test --- .../staggered/globalfvgeometry.hh | 2 +- .../staggered/staggeredgeometryhelper.hh | 184 ++++++++++++++++-- .../staggered/subcontrolvolumeface.hh | 16 ++ .../staggered/test_staggered.cc | 4 +- 4 files changed, 189 insertions(+), 17 deletions(-) diff --git a/dumux/discretization/staggered/globalfvgeometry.hh b/dumux/discretization/staggered/globalfvgeometry.hh index 333265e638..d7e16024e5 100644 --- a/dumux/discretization/staggered/globalfvgeometry.hh +++ b/dumux/discretization/staggered/globalfvgeometry.hh @@ -64,7 +64,7 @@ class StaggeredGlobalFVGeometry<TypeTag, true> dimWorld = GridView::dimensionworld }; - using GeometryHelper = StaggeredGeometryHelper<GridView, dim>; + using GeometryHelper = StaggeredGeometryHelper<GridView>; public: //! Constructor diff --git a/dumux/discretization/staggered/staggeredgeometryhelper.hh b/dumux/discretization/staggered/staggeredgeometryhelper.hh index 5a81f1368f..45799401c9 100644 --- a/dumux/discretization/staggered/staggeredgeometryhelper.hh +++ b/dumux/discretization/staggered/staggeredgeometryhelper.hh @@ -28,23 +28,33 @@ #include <dune/geometry/referenceelements.hh> #include <dumux/common/math.hh> +#include <type_traits> namespace Dumux { -//! Create sub control volumes and sub control volume face geometries -template<class GridView, int dim> -class StaggeredGeometryHelper; +template<class Scalar> +struct PairData +{ + std::pair<int,int> parallelPair; + std::pair<int,int> normalPair; + int localCommonEntIdx; + Scalar parallelDistance; + Scalar normalDistance; +}; //! A class to create sub control volume and sub control volume face geometries per element template <class GridView> -class StaggeredGeometryHelper<GridView, 2> +// class StaggeredGeometryHelper<GridView, dim> +class StaggeredGeometryHelper { using Scalar = typename GridView::ctype; static const int dim = GridView::dimension; static const int dimWorld = GridView::dimensionworld; + static constexpr int numPairs = (dimWorld == 2) ? 2 : 4; + using ScvGeometry = Dune::CachedMultiLinearGeometry<Scalar, dim, dimWorld>; using ScvfGeometry = Dune::CachedMultiLinearGeometry<Scalar, dim-1, dimWorld>; @@ -56,40 +66,184 @@ class StaggeredGeometryHelper<GridView, 2> using ReferenceElements = typename Dune::ReferenceElements<Scalar, dim>; - //! the maximum number of helper points used to construct the geometries - //! Using a statically sized point array is much faster than dynamic allocation - static constexpr int maxPoints = 9; + + //TODO include assert that checks for quad geometry + public: + StaggeredGeometryHelper(const Intersection& intersection, const GridView& gridView) - : intersection_(intersection), elementGeometry_(intersection.inside().geometry()), gridView_(gridView)//, corners_(geometry.corners()) + : intersection_(intersection), elementGeometry_(intersection.inside().geometry()), gridView_(gridView), offset_(gridView.size(0)) { + fillPairData(); } int dofIdxSelf() const { //TODO: use proper intersection mapper! const auto inIdx = intersection_.indexInInside(); - const int numElements = gridView_.size(0); - return gridView_.indexSet().subIndex(intersection_.inside(), inIdx, dim-1) + numElements; + return gridView_.indexSet().subIndex(intersection_.inside(), inIdx, dim-1) + offset_; } int dofIdxOpposite() const { //TODO: use proper intersection mapper! const auto inIdx = intersection_.indexInInside(); - const int numElements = gridView_.size(0); - const int localOppositeIdx = (inIdx % 2) ? (inIdx - 1) : (inIdx + 1); - return gridView_.indexSet().subIndex(intersection_.inside(), localOppositeIdx, dim-1) + numElements; + return gridView_.indexSet().subIndex(intersection_.inside(), localOppositeIdx_(inIdx), dim-1) + offset_; + } + + + auto pairData() const + { + return pairData_; + } + + + void fillPairData() + { + const auto element = intersection_.inside(); + const auto& referenceElement = ReferenceElements::general(element.geometry().type()); + + const int indexInInside = intersection_.indexInInside(); + + + // store the element's own face info first + pairData_[0].parallelPair.first = dofIdxSelf(); + pairData_[1].parallelPair.first = dofIdxSelf(); + + setInnerNormalPairs_(indexInInside); + + + + // go into the direct neigbor element + if(intersection_.neighbor()) + { + const int neighborIsIdx = intersection_.indexInOutside(); + + const auto& directNeighbor = intersection_.outside(); + + + for(const auto& is : 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())) + { + // get facet +// const auto& facet = directNeighbor.template subEntity < 1 > (is.indexInInside()); +// std::cout << + + // 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 globalCommonEntIdx = gridView_.indexSet().subIndex(directNeighbor, localCommonEntIdx, codimCommonEntity); + int globalCommonEntIdx = localToGlobalEntityIdx(localCommonEntIdx); + +// int dofIdx = gridView_.indexSet().index(commonEnt); + +// if(globalCommonEntIdx != dofIdx) +// std::cout << "error!"; + + std::cout << "pos: " << commonEnt.geometry().center() << std::endl; + + if(globalCommonEntIdx == localToGlobalEntityIdx(pairData_[0].localCommonEntIdx)) + { + pairData_[0].normalPair.second = gridView_.indexSet().subIndex(directNeighbor, is.indexInInside(), dim-1) + offset_; + } + if(globalCommonEntIdx == localToGlobalEntityIdx(pairData_[1].localCommonEntIdx)) + { + pairData_[1].normalPair.second = gridView_.indexSet().subIndex(directNeighbor, is.indexInInside(), dim-1) + offset_; + } + } + + std::cout << "inters: " << intersection_.geometry().center() << + " || side : " << is.geometry().center() << std::endl; + + + } + + } + } + +//TODO: fill parallel faces } private: + + int localOppositeIdx_(const int idx) const + { + return (idx % 2) ? (idx - 1) : (idx + 1); + } + + + template<class G = GridView> + typename std::enable_if<G::dimension == 2, void>::type + setInnerNormalPairs_(const int isIdx) + { + auto& data1 = pairData_[0]; + auto& data2 = pairData_[1]; + + switch(isIdx) + { + 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; + 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; + 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; + 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; + break; + default: + DUNE_THROW(Dune::InvalidStateException, "foo"); + } + } + + template<class G = GridView> + typename std::enable_if<G::dimension == 3, void>::type + setInnerNormalPairs_(const int isIdx) + { + // TODO: 3D + DUNE_THROW(Dune::NotImplemented, "3d helper not ready yet"); + } + + const Intersection& intersection_; const typename Element::Geometry& elementGeometry_; //! Reference to the element geometry const GridView gridView_; -// GlobalPosition p[maxPoints]; // the points needed for construction of the geometries -// std::size_t corners_; // number of element corners + const int offset_; + + std::array<PairData<Scalar>, numPairs> pairData_; + }; diff --git a/dumux/discretization/staggered/subcontrolvolumeface.hh b/dumux/discretization/staggered/subcontrolvolumeface.hh index b00a83e396..2a65374624 100644 --- a/dumux/discretization/staggered/subcontrolvolumeface.hh +++ b/dumux/discretization/staggered/subcontrolvolumeface.hh @@ -26,8 +26,11 @@ #include <utility> #include <dune/common/fvector.hh> #include <dumux/discretization/subcontrolvolumefacebase.hh> +#include <dumux/discretization/staggered/staggeredgeometryhelper.hh> #include <dumux/common/optional.hh> +#include <typeinfo> + namespace Dumux { @@ -67,6 +70,9 @@ class StaggeredSubControlVolumeFace : public SubControlVolumeFaceBase<StaggeredS using StaggeredSubFace = Dumux::StaggeredSubFace<G,I>; + static constexpr int numPairs = (dimworld == 2) ? 2 : 4; + + public: // the default constructor StaggeredSubControlVolumeFace() = default; @@ -94,6 +100,8 @@ public: selfIdx_ = geometryHelper.dofIdxSelf(); oppositeIdx_ = geometryHelper.dofIdxOpposite(); + + pairData_ = geometryHelper.pairData(); } /*//! The copy constrcutor @@ -193,6 +201,12 @@ public: return oppositeIdx_; } + + auto pairData(const int idx) const + { + return pairData_[idx]; + } + private: Dune::GeometryType geomType_; std::vector<GlobalPosition> corners_; @@ -206,6 +220,8 @@ private: int selfIdx_; int oppositeIdx_; std::vector<StaggeredSubFace> subfaces_; + std::array<PairData<Scalar>, numPairs> pairData_; + }; diff --git a/test/discretization/staggered/test_staggered.cc b/test/discretization/staggered/test_staggered.cc index 2a798b6412..9998cc4697 100644 --- a/test/discretization/staggered/test_staggered.cc +++ b/test/discretization/staggered/test_staggered.cc @@ -131,9 +131,11 @@ 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() << ", doIdx (self): " << scvf.dofIndexSelf() << ", doIdx (opposite): " << scvf.dofIndexOpposite(); + 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::endl; } -- GitLab