From aca0fe325c3006ee09c32354270f378c8b1543d3 Mon Sep 17 00:00:00 2001
From: "Dennis.Glaeser" <dennis.glaeser@iws.uni-stuttgart.de>
Date: Wed, 30 Sep 2020 14:11:33 +0200
Subject: [PATCH] [facet][tpfa] support gravity on surface grids

---
 .../facet/cellcentered/tpfa/darcyslaw.hh      | 72 +++++++++++++++----
 1 file changed, 60 insertions(+), 12 deletions(-)

diff --git a/dumux/multidomain/facet/cellcentered/tpfa/darcyslaw.hh b/dumux/multidomain/facet/cellcentered/tpfa/darcyslaw.hh
index a1a032e730..937c76b9a3 100644
--- a/dumux/multidomain/facet/cellcentered/tpfa/darcyslaw.hh
+++ b/dumux/multidomain/facet/cellcentered/tpfa/darcyslaw.hh
@@ -367,6 +367,9 @@ public:
     //! Export transmissibility storage type
     using AdvectionTransmissibilityContainer = std::array<Scalar, 2>;
 
+    //! Export the type used for the gravity coefficients
+    using GravityCoefficients = std::array<Scalar, 1>;
+
     //! update subject to a given problem
     template< class Problem, class ElementVolumeVariables >
     void updateAdvection(const Problem& problem,
@@ -375,7 +378,7 @@ public:
                          const ElementVolumeVariables& elemVolVars,
                          const SubControlVolumeFace &scvf)
     {
-        tij_ = AdvectionType::calculateTransmissibility(problem, element, fvGeometry, elemVolVars, scvf);
+        tij_ = AdvectionType::calculateTransmissibility(problem, element, fvGeometry, elemVolVars, scvf, g_);
     }
 
     //! We use the same name as in the TpfaDarcysLawCache so
@@ -393,8 +396,13 @@ public:
     Scalar advectionTijFacet() const
     { return tij_[facetTijIdx]; }
 
+    //! return the coefficients for the computation of gravity at the scvf
+    const GravityCoefficients& gravityCoefficients() const
+    { return g_; }
+
 private:
     AdvectionTransmissibilityContainer tij_;
+    GravityCoefficients g_;
 };
 
 /*!
@@ -436,24 +444,49 @@ class CCTpfaFacetCouplingDarcysLawImpl<ScalarType, GridGeometry, /*isNetwork*/tr
                        int phaseIdx,
                        const ElementFluxVarsCache& elemFluxVarsCache)
     {
-        static const Scalar gravity = getParamFromGroup<bool>(problem.paramGroup(), "Problem.EnableGravity");
-        if (gravity)
-            DUNE_THROW(Dune::NotImplemented, "Gravity for darcys law with facet coupling on surface grids");
-
         if (!problem.couplingManager().isOnInteriorBoundary(element, scvf))
             return TpfaDarcysLaw::flux(problem, element, fvGeometry, elemVolVars, scvf, phaseIdx, elemFluxVarsCache);
 
+        // On surface grids only xi = 1.0 can be used, as the coupling condition
+        // for xi != 1.0 does not generalize for surface grids where there can be
+        // seveal neighbor meeting at a branching point.
+        static const Scalar xi = getParamFromGroup<Scalar>(problem.paramGroup(), "FacetCoupling.Xi", 1.0);
+        if (Dune::FloatCmp::ne(xi, 1.0, 1e-6))
+            DUNE_THROW(Dune::InvalidStateException, "Xi != 1.0 cannot be used on surface grids");
+
         // Obtain inside and fracture pressures
         const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
+        const auto& facetVolVars = problem.couplingManager().getLowDimVolVars(element, scvf);
         const auto pInside = insideVolVars.pressure(phaseIdx);
-        const auto pFacet = problem.couplingManager().getLowDimVolVars(element, scvf).pressure(phaseIdx);
+        const auto pFacet = facetVolVars.pressure(phaseIdx);
 
-        // return flux
+        // compute and return flux
         const auto& fluxVarsCache = elemFluxVarsCache[scvf];
-        if (scvf.boundary())
-            return fluxVarsCache.advectionTijInside()*pInside + fluxVarsCache.advectionTijFacet()*pFacet;
-        else
-            return fluxVarsCache.advectionTijInside()*pInside + fluxVarsCache.advectionTijFacet()*pFacet;
+        Scalar flux = fluxVarsCache.advectionTijInside()*pInside + fluxVarsCache.advectionTijFacet()*pFacet;
+
+        static const Scalar gravity = getParamFromGroup<bool>(problem.paramGroup(), "Problem.EnableGravity");
+        if (gravity)
+        {
+            // compute alpha := n^T*K*g and add to flux (use arithmetic mean for density)
+            const auto& g = problem.spatialParams().gravity(scvf.ipGlobal());
+            const auto rho = 0.5*(insideVolVars.density(phaseIdx) + facetVolVars.density(phaseIdx));
+            const auto rhoTimesArea = rho*Extrusion::area(scvf);
+            const auto alpha_inside = rhoTimesArea*insideVolVars.extrusionFactor()
+                                      *vtmv(scvf.unitOuterNormal(), insideVolVars.permeability(), g);
+
+            flux += alpha_inside;
+
+            // maybe add further gravitational contributions
+            if ( !scvf.boundary() && problem.interiorBoundaryTypes(element, scvf).hasOnlyNeumann() )
+            {
+                const auto alpha_facet = rhoTimesArea*insideVolVars.extrusionFactor()
+                                         *vtmv(scvf.unitOuterNormal(), facetVolVars.permeability(), g);
+
+                flux -= fluxVarsCache.gravityCoefficients()[0]*(alpha_inside - alpha_facet);
+            }
+        }
+
+        return flux;
     }
 
     // The flux variables cache has to be bound to an element prior to flux calculations
@@ -464,6 +497,20 @@ class CCTpfaFacetCouplingDarcysLawImpl<ScalarType, GridGeometry, /*isNetwork*/tr
                                                   const FVElementGeometry& fvGeometry,
                                                   const ElementVolumeVariables& elemVolVars,
                                                   const SubControlVolumeFace& scvf)
+    {
+        typename Cache::GravityCoefficients g;
+        return calculateTransmissibility(problem, element, fvGeometry, elemVolVars, scvf, g);
+    }
+
+    // This overload additionally receives a container in which the coefficients required
+    // for the computation of the gravitational acceleration ar the scvf are stored
+    template< class Problem, class ElementVolumeVariables >
+    static TijContainer calculateTransmissibility(const Problem& problem,
+                                                  const Element& element,
+                                                  const FVElementGeometry& fvGeometry,
+                                                  const ElementVolumeVariables& elemVolVars,
+                                                  const SubControlVolumeFace& scvf,
+                                                  typename Cache::GravityCoefficients& g)
     {
         TijContainer tij;
         if (!problem.couplingManager().isCoupled(element, scvf))
@@ -504,7 +551,8 @@ class CCTpfaFacetCouplingDarcysLawImpl<ScalarType, GridGeometry, /*isNetwork*/tr
                                         *vtmv(scvf.unitOuterNormal(), facetVolVars.permeability(), scvf.unitOuterNormal());
 
             // TODO: check for division by zero??
-            tij[Cache::insideTijIdx] = wFacet*wIn/(wIn+wFacet);
+            g[0] = wIn/(wIn+wFacet);
+            tij[Cache::insideTijIdx] = wFacet*g[0];
             tij[Cache::facetTijIdx] = -tij[Cache::insideTijIdx];
         }
         else if (iBcTypes.hasOnlyDirichlet())
-- 
GitLab