From 85d53c3deff3f97154fa2f727573d2c2af55fe83 Mon Sep 17 00:00:00 2001
From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de>
Date: Sat, 6 Jan 2018 18:32:03 +0100
Subject: [PATCH] [staggered] Improve fluxOverPlane calculation

* add convenience functions to get mass/mole or volume fluxes
* make more generic, for compositional models
---
 .../navierstokes/staggered/fluxoverplane.hh   | 155 ++++++++++++++++--
 1 file changed, 142 insertions(+), 13 deletions(-)

diff --git a/dumux/freeflow/navierstokes/staggered/fluxoverplane.hh b/dumux/freeflow/navierstokes/staggered/fluxoverplane.hh
index 965bb82f6c..90717077df 100644
--- a/dumux/freeflow/navierstokes/staggered/fluxoverplane.hh
+++ b/dumux/freeflow/navierstokes/staggered/fluxoverplane.hh
@@ -52,6 +52,10 @@ class FluxOverPlane
     using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
     using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
     using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
+    using LocalResidual = typename GET_PROP_TYPE(TypeTag, LocalResidual);
+    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
+    using CellCenterPrimaryVariables = typename GET_PROP_TYPE(TypeTag, CellCenterPrimaryVariables);
+    using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
     using Element = typename GridView::template Codim<0>::Entity;
 
     using DofTypeIndices = typename GET_PROP(TypeTag, DofTypeIndices);
@@ -93,14 +97,14 @@ class FluxOverPlane
             geometries_ = std::forward<decltype(geo)>(geo);
         }
 
-        void addValue(int planeIdx, Scalar value)
+        void addValue(int planeIdx, const CellCenterPrimaryVariables& value)
         {
             values_[planeIdx] += value;
         }
 
         void addSubPlane(Geo&& geo)
         {
-            values_.push_back(0.0);
+            values_.emplace_back(0.0);
             geometries_.push_back(std::move(geo));
         }
 
@@ -109,7 +113,7 @@ class FluxOverPlane
             return geometries_;
         }
 
-        Scalar value(int planeIdx) const
+        CellCenterPrimaryVariables& value(int planeIdx) const
         {
             return values_[planeIdx];
         }
@@ -128,13 +132,13 @@ class FluxOverPlane
 
         void resetValues()
         {
-            std::fill(values_.begin(), values_.end(), 0.0);
+            std::fill(values_.begin(), values_.end(), CellCenterPrimaryVariables(0.0));
         }
 
     private:
 
         std::vector<Geo> geometries_;
-        std::vector<Scalar> values_;
+        std::vector<CellCenterPrimaryVariables> values_;
     };
 
 
@@ -240,14 +244,47 @@ public:
 #endif
     }
 
+    /*!
+     * \brief Calculate the mass or mole fluxes over all planes
+     */
+    void calculateMassOrMoleFluxes()
+    {
+        auto fluxType = [this](const auto& problem,
+                               const auto& element,
+                               const auto& fvGeometry,
+                               const auto& elemVolVars,
+                               const auto& elemFaceVars,
+                               const auto& scvf,
+                               const auto& elemFluxVarsCache)
+        {
+            return localResidual_.computeFluxForCellCenter(problem, element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
+        };
+
+        calculateFluxes(fluxType);
+    }
+
+    /*!
+     * \brief Calculate the volume fluxes over all planes.
+     *        This method simply averages the densities between two adjacent cells.
+     */
+    void calculateVolumeFluxes()
+    {
+        const auto isCompositional = std::integral_constant<bool, (GET_PROP_VALUE(TypeTag, NumComponents) > 1) >();
+        calculateVolumeFluxesImpl_(isCompositional);
+    }
+
     /*!
      * \brief Calculate the fluxes over all planes for a given flux type.
      *
      * \param fluxType The flux type. This can be a lambda of the following form:
-     *                 [](const auto& element,
-     *                    const auto& fvGeometry,
-     *                    const auto& scvf,
-     *                    const Scalar velocity) { return velocity * ... ;}
+     *                 [](const auto& problem,
+                          const auto& element,
+                          const auto& fvGeometry,
+                          const auto& elemVolVars,
+                          const auto& elemFaceVars,
+                          const auto& scvf,
+                          const auto& elemFluxVarsCache)
+                          { return ... ; }
      */
     template<class FluxType>
     void calculateFluxes(const FluxType& fluxType)
@@ -259,10 +296,20 @@ public:
         // make sure not to iterate over the same dofs twice
         std::vector<bool> dofVisited(problem_.fvGridGeometry().numFaceDofs(), false);
 
+        LocalResidual localResidual;
+        auto elemVolVars = localView(gridVariables_.curGridVolVars());
+        auto elemFluxVarsCache = localView(gridVariables_.gridFluxVarsCache());
+        auto elemFaceVars = localView(gridVariables_.curGridFaceVars());
+
         for(auto&& element : elements(problem_.fvGridGeometry().gridView()))
         {
             auto fvGeometry = localView(problem_.fvGridGeometry());
             fvGeometry.bindElement(element);
+
+            elemVolVars.bind(element, fvGeometry, sol_);
+            elemFaceVars.bind(element, fvGeometry, sol_);
+            elemFluxVarsCache.bind(element, fvGeometry, elemVolVars);
+
             for(auto && scvf : scvfs(fvGeometry))
             {
                 const auto dofIdx = scvf.dofIndex();
@@ -282,8 +329,8 @@ public:
                     {
                         if(intersectsPointGeometry(scvf.center(), subPlanes[planeIdx]))
                         {
-                            const Scalar velocity = sol_[faceIdx][dofIdx][0];
-                            const Scalar result = fluxType(element, fvGeometry, scvf, velocity);
+                            const auto result = fluxType(problem_, element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
+
                             plane.second.addValue(planeIdx, result);
 
                             if(verbose_)
@@ -315,19 +362,101 @@ public:
      *
      * \param name The name of the plane
      */
-    Scalar netFlux(const std::string& name) const
+    auto netFlux(const std::string& name) const
     {
         const auto& planeResults = values(name);
-        return std::accumulate(planeResults.begin(), planeResults.end(), 0.0);
+        return std::accumulate(planeResults.begin(), planeResults.end(), CellCenterPrimaryVariables(0.0));
     }
 
 private:
 
+    /*!
+     * \brief Calculate the volume fluxes over all planes for compositional models.
+     *        This method simply averages the densities between two adjacent cells.
+     */
+    void calculateVolumeFluxesImpl_(std::true_type)
+    {
+        auto fluxType = [this](const auto& problem,
+                               const auto& element,
+                               const auto& fvGeometry,
+                               const auto& elemVolVars,
+                               const auto& elemFaceVars,
+                               const auto& scvf,
+                               const auto& elemFluxVarsCache)
+        {
+            const auto massOrMoleFlux = localResidual_.computeFluxForCellCenter(problem, element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
+
+            const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
+            const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
+
+            constexpr bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
+            const auto density = [useMoles](const auto& volVars)
+            {
+                return useMoles ? volVars.molarDensity() : volVars.density() ;
+            };
+
+            const auto avgDensity = 0.5*density(insideVolVars) + 0.5*density(outsideVolVars);
+
+            constexpr auto replaceCompEqIdx = GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx);
+            constexpr auto numComponents = GET_PROP_VALUE(TypeTag, NumComponents);
+
+            const Scalar cumulativeFlux = [replaceCompEqIdx, numComponents, &massOrMoleFlux]()
+            {
+                Scalar result = 0.0;
+                if(replaceCompEqIdx < numComponents)
+                {
+                    for(int i = 0; i < numComponents; ++i)
+                        result += massOrMoleFlux[i];
+                }
+                else
+                    result = massOrMoleFlux[replaceCompEqIdx];
+
+                return result;
+            }();
+
+            CellCenterPrimaryVariables tmp(0.0);
+            tmp[Indices::conti0EqIdx] = cumulativeFlux / avgDensity;
+            return tmp;
+        };
+
+        calculateFluxes(fluxType);
+    }
+
+    /*!
+     * \brief Calculate the volume fluxes over all planes for non-compositional models.
+     *        This method simply averages the densities between two adjacent cells.
+     */
+    void calculateVolumeFluxesImpl_(std::false_type)
+    {
+        auto fluxType = [this](const auto& problem,
+                               const auto& element,
+                               const auto& fvGeometry,
+                               const auto& elemVolVars,
+                               const auto& elemFaceVars,
+                               const auto& scvf,
+                               const auto& elemFluxVarsCache)
+        {
+            const Scalar massFlux = localResidual_.computeFluxForCellCenter(problem, element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache)[Indices::conti0EqIdx];
+
+            const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
+            const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
+
+            const auto avgDensity = 0.5*insideVolVars.density() + 0.5*outsideVolVars.density();
+
+            CellCenterPrimaryVariables tmp(0.0);
+            tmp[Indices::conti0EqIdx] = massFlux / avgDensity;
+            return tmp;
+        };
+
+        calculateFluxes(fluxType);
+    }
+
     std::map<std::string, PlaneData<planeDim ,dim> > planes_;
     const Problem& problem_;
     const GridVariables& gridVariables_;
     const SolutionVector& sol_;
     bool verbose_;
+    LocalResidual localResidual_;
 };
 
 } //end namespace
-- 
GitLab