From 4c43ba827aa29c00d1f789ad677469ef77194470 Mon Sep 17 00:00:00 2001 From: Timo Koch <timo.koch@iws.uni-stuttgart.de> Date: Thu, 12 Jul 2018 19:05:33 +0200 Subject: [PATCH] [periodic] Implement periodic boundaries for cctpfa --- .../cellcentered/tpfa/darcyslaw.hh | 12 ++++--- .../cellcentered/tpfa/fvelementgeometry.hh | 34 ++++++------------- .../cellcentered/tpfa/fvgridgeometry.hh | 16 ++++++--- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/dumux/discretization/cellcentered/tpfa/darcyslaw.hh b/dumux/discretization/cellcentered/tpfa/darcyslaw.hh index c80cc8c692..109ac32bc9 100644 --- a/dumux/discretization/cellcentered/tpfa/darcyslaw.hh +++ b/dumux/discretization/cellcentered/tpfa/darcyslaw.hh @@ -191,10 +191,12 @@ class CCTpfaDarcysLaw<ScalarType, FVGridGeometry, /*isNetwork*/ false> { const auto& outsideScv = fvGeometry.scv(scvf.outsideScvIdx()); const auto outsideK = outsideVolVars.permeability(); - const auto outsideTi = computeTpfaTransmissibility(scvf, outsideScv, outsideK, outsideVolVars.extrusionFactor()); + const auto outsideTi = fvGeometry.fvGridGeometry().isPeriodic() + ? computeTpfaTransmissibility(fvGeometry.flipScvf(scvf.index()), outsideScv, outsideK, outsideVolVars.extrusionFactor()) + : -1.0*computeTpfaTransmissibility(scvf, outsideScv, outsideK, outsideVolVars.extrusionFactor()); const auto alpha_outside = vtmv(scvf.unitOuterNormal(), outsideK, g)*outsideVolVars.extrusionFactor(); - flux += rho*tij/outsideTi*(alpha_inside - alpha_outside); + flux -= rho*tij/outsideTi*(alpha_inside - alpha_outside); } return flux; @@ -241,9 +243,9 @@ class CCTpfaDarcysLaw<ScalarType, FVGridGeometry, /*isNetwork*/ false> // refers to the scv of our element, so we use the scv method const auto& outsideScv = fvGeometry.scv(outsideScvIdx); const auto& outsideVolVars = elemVolVars[outsideScvIdx]; - const Scalar tj = -1.0*computeTpfaTransmissibility(scvf, outsideScv, - getPermeability_(problem, outsideVolVars, scvf.ipGlobal()), - outsideVolVars.extrusionFactor()); + const Scalar tj = fvGeometry.fvGridGeometry().isPeriodic() + ? computeTpfaTransmissibility(fvGeometry.flipScvf(scvf.index()), outsideScv, getPermeability_(problem, outsideVolVars, scvf.ipGlobal()), outsideVolVars.extrusionFactor()) + : -1.0*computeTpfaTransmissibility(scvf, outsideScv, getPermeability_(problem, outsideVolVars, scvf.ipGlobal()), outsideVolVars.extrusionFactor()); // harmonic mean (check for division by zero!) // TODO: This could lead to problems!? Is there a better way to do this? diff --git a/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh b/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh index fb1cf2a7fd..c1e4b4388b 100644 --- a/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh +++ b/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh @@ -281,8 +281,10 @@ public: std::vector<IndexType> handledNeighbors; handledNeighbors.reserve(element.subEntities(1)); + for (const auto& intersection : intersections(fvGridGeometry().gridView(), element)) { + // for inner intersections and periodic (according to grid interface) intersections make neighbor geometry if (intersection.neighbor()) { const auto outside = intersection.outside(); @@ -297,7 +299,8 @@ public: } } - if (dim < dimWorld) + // build flip index set for network, surface, and periodic grids + if (dim < dimWorld || fvGridGeometry().isPeriodic()) { flippedScvfIndices_.resize(scvfs_.size()); for (unsigned int localScvfIdx = 0; localScvfIdx < scvfs_.size(); ++localScvfIdx) @@ -332,21 +335,6 @@ public: } } } - - //! TODO Check if user added additional DOF dependencies, i.e. the residual of DOF globalI depends - //! on additional DOFs not included in the discretization schemes' occupation pattern - // const auto globalI = fvGridGeometry().elementMapper().index(element); - // const auto& additionalDofDependencies = problem.getAdditionalDofDependencies(globalI); - // if (!additionalDofDependencies.empty()) - // { - // neighborScvs_.reserve(neighborScvs_.size() + additionalDofDependencies.size()); - // neighborScvIndices_.reserve(neighborScvIndices_.size() + additionalDofDependencies.size()); - // for (auto globalJ : additionalDofDependencies) - // { - // neighborScvs_.emplace_back(fvGridGeometry().element(globalJ).geometry(), globalJ); - // neighborScvIndices_.emplace_back(globalJ); - // } - // } } //! Binding of an element preparing the geometries only inside the element @@ -418,7 +406,6 @@ private: continue; const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter]; - if (intersection.neighbor() || intersection.boundary()) { ScvfGridIndexStorage scvIndices; @@ -429,7 +416,7 @@ private: intersection.geometry(), scvFaceIndices[scvfCounter], scvIndices, - intersection.boundary()); + intersection.boundary() && !intersection.neighbor()); scvfIndices_.emplace_back(scvFaceIndices[scvfCounter]); scvfCounter++; @@ -466,14 +453,14 @@ private: if (handledScvf[intersection.indexInInside()]) continue; + // this catches inner and periodic scvfs const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter]; - - if (intersection.neighbor()) + if (scvfNeighborVolVarIndices[0] < fvGridGeometry().gridView().size(0)) { // only create subcontrol faces where the outside element is the bound element if (dim == dimWorld) { - if (intersection.outside() == *elementPtr_) + if (scvfNeighborVolVarIndices[0] == fvGridGeometry().elementMapper().index(*elementPtr_)) { ScvfGridIndexStorage scvIndices({eIdx, scvfNeighborVolVarIndices[0]}); neighborScvfs_.emplace_back(intersection, @@ -509,7 +496,6 @@ private: break; } } - } // for surface and network grids mark that we handled this face @@ -517,9 +503,11 @@ private: handledScvf[intersection.indexInInside()] = true; scvfCounter++; } + + // only increase counter for boundary intersections + // (exclude periodic boundaries according to dune grid interface, they have been handled in neighbor==true) else if (intersection.boundary()) { - // for surface and network grids mark that we handled this face if (dim < dimWorld) handledScvf[intersection.indexInInside()] = true; scvfCounter++; diff --git a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh index 71ea360571..a7d381f2c7 100644 --- a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh +++ b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh @@ -208,9 +208,13 @@ public: for (const auto& intersection : intersections(this->gridView(), element)) { - // inner sub control volume faces + // inner sub control volume faces (includes periodic boundaries) if (intersection.neighbor()) { + // update the grid geometry if we have periodic boundaries + if (intersection.boundary()) + this->setPeriodic(); + if (dim == dimWorld) { const auto nIdx = this->elementMapper().index(intersection.outside()); @@ -257,8 +261,8 @@ public: scvfIndicesOfScv_[eIdx] = scvfsIndexSet; } - // Make the flip index set for network and surface grids - if (dim < dimWorld) + // Make the flip index set for network, surface, and periodic grids + if (dim < dimWorld || this->isPeriodic()) { flipScvfIndices_.resize(scvfs_.size()); for (auto&& scvf : scvfs_) @@ -467,9 +471,13 @@ public: for (const auto& intersection : intersections(this->gridView(), element)) { - // inner sub control volume faces + // inner sub control volume faces (includes periodic boundaries) if (intersection.neighbor()) { + // update the grid geometry if we have periodic boundaries + if (intersection.boundary()) + this->setPeriodic(); + if (dim == dimWorld) { scvfsIndexSet.push_back(numScvf_++); -- GitLab