From b1e657e7a8317dd8d02f4b2ff1a1079a1b049c23 Mon Sep 17 00:00:00 2001 From: DennisGlaeser <dennis.glaeser@iws.uni-stuttgart.de> Date: Fri, 3 Feb 2017 18:47:36 +0100 Subject: [PATCH] [mpfa-l] port to new flux var cache concept --- .../cellcentered/mpfa/lmethod/helper.hh | 15 ++- .../mpfa/lmethod/interactionregions.hh | 24 ++-- .../mpfa/lmethod/interactionvolume.hh | 108 +++++++++++------- .../mpfa/lmethod/subcontrolvolumeface.hh | 4 +- 4 files changed, 90 insertions(+), 61 deletions(-) diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh b/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh index f5d88a6897..1ca199a5d2 100644 --- a/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh +++ b/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh @@ -98,7 +98,6 @@ public: const Matrix& M1, const Matrix& M2) { - Scalar eps = 1e-10; Scalar t11, t12, t21, t22; t11 = M1[I1.contiFaceLocalIdx][0]; t21 = M2[I2.contiFaceLocalIdx][0]; @@ -116,7 +115,7 @@ public: Scalar s1 = std::abs(t11-t12); Scalar s2 = std::abs(t22-t21); - if (s1 < s2 + eps*s1) + if (s1 < s2) return 0; else return 1; @@ -132,16 +131,16 @@ private: const SubControlVolumeFace& scvf) { // make the first scv seed, we know this element will NOT be on the lowest local level - auto scvfVector = Implementation::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry); - auto localScvfIdx = Implementation::getLocalFaceIndex(scvf, scvfVector); + const auto scvfVector = Implementation::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry); + const auto localScvfIdx = Implementation::getLocalFaceIndex(scvf, scvfVector); scvSeeds.emplace_back( GlobalIndexSet({scvfVector[0]->index(), scvfVector[1]->index()}), scvf.insideScvIdx(), localScvfIdx ); // get the surrounding elements and "outside" data LocalIndexType otherScvfIdx = 1-localScvfIdx; - auto e2 = problem.model().globalFvGeometry().element(scvf.outsideScvIdx()); - auto e3 = problem.model().globalFvGeometry().element(scvfVector[otherScvfIdx]->outsideScvIdx()); + const auto e2 = problem.model().globalFvGeometry().element(scvf.outsideScvIdx()); + const auto e3 = problem.model().globalFvGeometry().element(scvfVector[otherScvfIdx]->outsideScvIdx()); auto e2Geometry = localView(problem.model().globalFvGeometry()); auto e3Geometry = localView(problem.model().globalFvGeometry()); @@ -166,10 +165,10 @@ private: e3Scvfs[localScvfIdx]->index()); // Outer seed for outside of e2, we know the local scvf index here will be localScvfIdx in 2d - auto e4 = problem.model().globalFvGeometry().element(e2Scvfs[localScvfIdx]->outsideScvIdx()); + const auto e4 = problem.model().globalFvGeometry().element(e2Scvfs[localScvfIdx]->outsideScvIdx()); auto e4Geometry = localView(problem.model().globalFvGeometry()); e4Geometry.bindElement(e4); - auto e4Scvfs = Implementation::getCommonAndNextScvFace(*e2Scvfs[localScvfIdx], e4Geometry, /*clockwise?*/localScvfIdx == 1); + const auto e4Scvfs = Implementation::getCommonAndNextScvFace(*e2Scvfs[localScvfIdx], e4Geometry, /*clockwise?*/localScvfIdx == 1); outerScvSeeds.emplace_back(e4Scvfs[otherScvfIdx]->insideScvIdx(), e4Scvfs[otherScvfIdx]->index()); diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh b/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh index fc4c039ea1..17380bc1a9 100644 --- a/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh +++ b/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh @@ -58,22 +58,22 @@ public: std::vector<Scalar> detX; std::vector<Element> elements; - std::array<GlobalIndexType, 2> globalScvfs; + std::array<GlobalIndexType, 2> globalScvfIndices; // Constructor signature for dim == 2 - template<class ScvSeedType, class OuterScvSeedType> + template<class ScvSeed, class OuterScvSeed> InteractionRegion(const Problem& problem, const FVElementGeometry& fvGeometry, - const ScvSeedType& scvSeed, - const OuterScvSeedType& outerSeed1, - const OuterScvSeedType& outerSeed2, + const ScvSeed& scvSeed, + const OuterScvSeed& outerSeed1, + const OuterScvSeed& outerSeed2, const Element& element1, const Element& element2, const Element& element3) { contiFaceLocalIdx = scvSeed.contiFaceLocalIdx(); - globalScvfs[0] = scvSeed.globalScvfIndices()[contiFaceLocalIdx]; - globalScvfs[1] = contiFaceLocalIdx == 0 ? outerSeed1.globalScvfIndex() : outerSeed2.globalScvfIndex(); + globalScvfIndices[0] = scvSeed.globalScvfIndices()[contiFaceLocalIdx]; + globalScvfIndices[1] = contiFaceLocalIdx == 0 ? outerSeed1.globalScvfIndex() : outerSeed2.globalScvfIndex(); elements.resize(3); elements[0] = element1; @@ -81,11 +81,11 @@ public: elements[2] = element3; // The participating sub control entities - auto&& scv1 = fvGeometry.scv(scvSeed.globalIndex()); - auto&& scv2 = fvGeometry.scv(outerSeed1.globalIndex()); - auto&& scv3 = fvGeometry.scv(outerSeed2.globalIndex()); - auto&& scvf1 = fvGeometry.scvf(scvSeed.globalScvfIndices()[0]); - auto&& scvf2 = fvGeometry.scvf(scvSeed.globalScvfIndices()[1]); + const auto& scv1 = fvGeometry.scv(scvSeed.globalIndex()); + const auto& scv2 = fvGeometry.scv(outerSeed1.globalIndex()); + const auto& scv3 = fvGeometry.scv(outerSeed2.globalIndex()); + const auto& scvf1 = fvGeometry.scvf(scvSeed.globalScvfIndices()[0]); + const auto& scvf2 = fvGeometry.scvf(scvSeed.globalScvfIndices()[1]); // The necessary coordinates and normals GlobalPosition v = scvf1.vertexCorner(); diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh b/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh index 51e7929705..e56cb825c5 100644 --- a/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh +++ b/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh @@ -80,6 +80,7 @@ class CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::lMethod> : pub using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); + using InteriorBoundaryData = typename GET_PROP_TYPE(TypeTag, InteriorBoundaryData); static const int dim = GridView::dimension; static const int dimWorld = GridView::dimensionworld; @@ -93,6 +94,7 @@ class CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::lMethod> : pub public: using Matrix = typename Traits::Matrix; + using typename ParentType::GlobalLocalFaceDataPair; using typename ParentType::LocalIndexType; using typename ParentType::LocalIndexSet; using typename ParentType::LocalFaceData; @@ -108,7 +110,8 @@ public: const Problem& problem, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) - : problemPtr_(&problem), + : seedPtr_(&seed), + problemPtr_(&problem), fvGeometryPtr_(&fvGeometry), elemVolVarsPtr_(&elemVolVars), regionUnique_(seed.isUnique()), @@ -125,7 +128,9 @@ public: { const auto& ir = interactionRegions_[0]; T_ = assembleMatrix_(getTensor, ir); - postSolve_(ir); + interactionRegionId_ = 0; + updateGlobalLocalFaceData(); + systemSolved_ = true; } else { @@ -133,22 +138,25 @@ public: M[0] = assembleMatrix_(getTensor, interactionRegions_[0]); M[1] = assembleMatrix_(getTensor, interactionRegions_[1]); - auto id = MpfaHelper::selectionCriterion(interactionRegions_[0], interactionRegions_[1], M[0], M[1]); - postSolve_(interactionRegions_[id]); - T_ = M[id]; + interactionRegionId_ = MpfaHelper::selectionCriterion(interactionRegions_[0], interactionRegions_[1], M[0], M[1]); + updateGlobalLocalFaceData(); + systemSolved_ = true; + T_ = M[interactionRegionId_]; } } //! returns the local index pair. This holds the scvf's local index and a boolean whether or not the flux has to be inverted - LocalFaceData getLocalFaceData(const SubControlVolumeFace& scvf) const + const LocalFaceData getLocalFaceData(const SubControlVolumeFace& scvf) const { assert(systemSolved_ && "Scvf Indices not set yet. You have to call solveLocalSystem() beforehand."); - assert((scvf.index() == globalScvfIndices_[0] || scvf.index() == globalScvfIndices_[1]) && "The provided scvf is not the flux face of the interaction volume."); + assert((scvf.index() == globalLocalScvfPairedData_[0].first->index() + || scvf.index() == globalLocalScvfPairedData_[1].first->index()) + && "The provided scvf is not the flux face of the interaction volume."); - if (globalScvfIndices_[0] == scvf.index()) - return LocalFaceData(contiFaceLocalIdx_, /*dummy*/0, false); + if (globalLocalScvfPairedData_[0].first->index() == scvf.index()) + return globalLocalScvfPairedData_[0].second; else - return LocalFaceData(contiFaceLocalIdx_, /*dummy*/0, true); + return globalLocalScvfPairedData_[1].second; } //! returns the transmissibilities corresponding to the bound scvf @@ -164,21 +172,18 @@ public: const GlobalIndexSet& volVarsStencil() const { - assert(systemSolved_ && "volVarsStencil not set yet. You have to call solveLocalSystem() beforehand."); - return volVarsStencil_; + assert(systemSolved_ && "stencil not set yet. You have to call solveLocalSystem() beforehand."); + return interactionRegion().scvIndices; } const PositionVector& volVarsPositions() const { - assert(systemSolved_ && "globalScvfs not set yet. You have to call solveLocalSystem() beforehand."); - return volVarsPositions_; + assert(systemSolved_ && "stencil not set yet. You have to call solveLocalSystem() beforehand."); + return interactionRegion().scvCenters; } - const GlobalIndexSet& globalScvfs() const - { - assert(systemSolved_ && "globalScvfs not set yet. You have to call solveLocalSystem() beforehand."); - return globalScvfIndices_; - } + const std::vector<GlobalLocalFaceDataPair>& globalLocalScvfPairedData() const + { return globalLocalScvfPairedData_; } //! Boundaries will be treated by a different mpfa method (e.g. o method). Thus, on //! faces in l-method interaction volumes there will never be a Neumann flux contribution. @@ -192,6 +197,13 @@ public: const Matrix& matrix() const { return T_; } + const InteractionRegion& interactionRegion() const + { return interactionRegions_[interactionRegionId_]; } + + // The l-method can't treat interior boundaries + const std::vector<InteriorBoundaryData> interiorBoundaryData() const + { return std::vector<InteriorBoundaryData>(); } + private: //! Assembles and solves the local equation system //! Specialization for dim = 2 @@ -210,9 +222,9 @@ private: const auto scv3 = fvGeometry_().scv(ir.scvIndices[2]); // Get diffusion tensors in the three scvs - const auto T1 = getTensor(e1, elemVolVars_()[scv1], scv1); - const auto T2 = getTensor(e2, elemVolVars_()[scv2], scv2); - const auto T3 = getTensor(e3, elemVolVars_()[scv3], scv3); + const auto T1 = getTensor(problem_(), e1, elemVolVars_()[scv1], fvGeometry_(), scv1); + const auto T2 = getTensor(problem_(), e2, elemVolVars_()[scv2], fvGeometry_(), scv2); + const auto T3 = getTensor(problem_(), e3, elemVolVars_()[scv3], fvGeometry_(), scv3); // required omega factors Scalar w111 = calculateOmega_(ir.normal[0], ir.nu[0], ir.detX[0], T1); @@ -248,7 +260,7 @@ private: B[1][1] = 0.0; B[1][2] = -w235 - w236; - // T = CA^-1B + D + // T = C*A^-1*B + D A.invert(); auto T = (A.leftmultiply(C)).rightmultiplyany(B); T[0][0] += w111 + w112; @@ -274,8 +286,10 @@ private: auto e1 = globalFvGeometry.element(scvSeed1.globalIndex()); auto e2 = globalFvGeometry.element(scvSeed2.globalIndex()); auto e3 = globalFvGeometry.element(scvSeed3.globalIndex()); - interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, scvSeed2, scvSeed3, e1, e2, e3); - + if (scvSeed1.contiFaceLocalIdx() == 0) + interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, scvSeed2, scvSeed3, e1, e2, e3); + else + interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, scvSeed3, scvSeed2, e1, e3, e2); } else { @@ -301,17 +315,36 @@ private: interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed2, OuterScvSeedType(scvSeed1), outerScvSeed2, e2, e1, e4); } } + + // as an initial guess we set the first interaction region as the one used + // this is updated after solution of the local system + interactionRegionId_ = 0; + updateGlobalLocalFaceData(); } - void postSolve_(const InteractionRegion& ir) + //! set the global&local face data according to the current choice for the interaction region + void updateGlobalLocalFaceData() { - globalScvfIndices_.resize(2); - globalScvfIndices_[0] = ir.globalScvfs[0]; - globalScvfIndices_[1] = ir.globalScvfs[1]; - volVarsStencil_ = ir.scvIndices; - volVarsPositions_ = ir.scvCenters; - contiFaceLocalIdx_ = ir.contiFaceLocalIdx; - systemSolved_ = true; + const auto numPairs = globalLocalScvfPairedData_.size(); + + // if no data has been stored yet, initialize + if (numPairs == 0) + { + globalLocalScvfPairedData_.clear(); + globalLocalScvfPairedData_.reserve(2); + globalLocalScvfPairedData_.emplace_back(&fvGeometry_().scvf(seed_().globalScvfIndices()[0]), + LocalFaceData(interactionRegion().contiFaceLocalIdx, /*dummy*/0, false)); + globalLocalScvfPairedData_.emplace_back(&fvGeometry_().scvf(seed_().globalScvfIndices()[1]), + LocalFaceData(interactionRegion().contiFaceLocalIdx, /*dummy*/0, true)); + } + // if order was swapped, change bools indicating which face is the "outside" version of the local face + else if (globalLocalScvfPairedData_[1].first->index() == interactionRegion().globalScvfIndices[0]) + { + globalLocalScvfPairedData_[0].second.localScvfIndex = interactionRegion().contiFaceLocalIdx; + globalLocalScvfPairedData_[1].second.localScvfIndex = interactionRegion().contiFaceLocalIdx; + globalLocalScvfPairedData_[0].second.isOutside = true; + globalLocalScvfPairedData_[1].second.isOutside = false; + } } Scalar calculateOmega_(const GlobalPosition& normal, @@ -347,7 +380,7 @@ private: } const Seed& seed_() const - { return seedPtr_; } + { return *seedPtr_; } const Problem& problem_() const { return *problemPtr_; } @@ -366,12 +399,9 @@ private: bool regionUnique_; bool systemSolved_; - LocalIndexType contiFaceLocalIdx_; - GlobalIndexSet globalScvfIndices_; - GlobalIndexSet volVarsStencil_; - PositionVector volVarsPositions_; - + LocalIndexType interactionRegionId_; std::vector<InteractionRegion> interactionRegions_; + std::vector<GlobalLocalFaceDataPair> globalLocalScvfPairedData_; Matrix T_; }; diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh b/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh index 13e90f8edc..9468f8c2fb 100644 --- a/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh +++ b/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh @@ -61,8 +61,8 @@ public: Scalar q, bool boundary) : ParentType(helper, - std::move(corners), - std::move(unitOuterNormal), + std::forward<std::vector<GlobalPosition>>(corners), + std::forward<GlobalPosition>(unitOuterNormal), vertexIndex, localIndex, scvfIndex, -- GitLab