From f60c2676ae558bb5de61533852e0a5b123504a97 Mon Sep 17 00:00:00 2001
From: Martin Schneider <martin.schneider@iws.uni-stuttgart.de>
Date: Wed, 28 Sep 2016 19:52:14 +0200
Subject: [PATCH] [adaptive] Update of Adaptionhelper

Check if fluids are incompressible because otherwise the
adaption process is not guaranteed to be mass conservative

Slight changes to increase readability
---
 .../2p/implicit/adaptionhelper.hh             | 83 ++++++++-----------
 1 file changed, 36 insertions(+), 47 deletions(-)

diff --git a/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh b/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh
index 300c770802..c69cba7691 100644
--- a/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh
+++ b/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh
@@ -43,6 +43,7 @@ private:
     typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
     typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
     typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
 
     enum {
@@ -94,7 +95,10 @@ public:
      *  @param gridView a DUNE gridview object
      */
     TwoPAdaptionHelper(Problem& problem) : ParentType(problem), adaptionMap_(problem.grid(), 0)
-    {}
+    {
+        if(FluidSystem::isCompressible(wPhaseIdx) || FluidSystem::isCompressible(nPhaseIdx))
+            DUNE_THROW(Dune::InvalidStateException, "Adaptionhelper is only for incompressible fluids mass-conservative!");
+    }
 
     /*!
      * Store primary variables
@@ -131,8 +135,7 @@ public:
                     for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
                     {
                         // get index
-                        auto subEntity = element.template subEntity <dofCodim>(scvIdx);
-                        int dofIdx = this->dofIndex(problem, subEntity);
+                        int dofIdx = this->dofIndex(problem, element, scvIdx);
 
                         adaptedValues.u.push_back(problem.model().curSol()[dofIdx]);
 
@@ -176,8 +179,7 @@ public:
 
                     for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
                     {
-                        auto subEntity = element.template subEntity <dofCodim>(scvIdx);
-                        int dofIdx = this->dofIndex(problem, subEntity);
+                        int dofIdx = this->dofIndex(problem, element, scvIdx);
 
                         adaptedValues.u.push_back(problem.model().curSol()[dofIdx]);
                     }
@@ -203,6 +205,7 @@ public:
     void reconstructPrimVars(Problem& problem)
     {
         adaptionMap_.resize();
+        //vectors storing the mass associated with each vertex, when using the box method
         std::vector<Scalar> massCoeff;
         std::vector<Scalar> associatedMass;
 
@@ -235,24 +238,34 @@ public:
                         for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
                         {
                             // get index
-                            auto subEntity = element.template subEntity <dofCodim>(scvIdx);
-                            int dofIdx = problem.model().dofMapper().index(subEntity);
+                            int dofIdx = this->dofIndex(problem, element, scvIdx);
+
+                            VolumeVariables volVars;
+                            volVars.update(adaptedValues.u[scvIdx],
+                                          problem,
+                                          element,
+                                          fvGeometry,
+                                          scvIdx,
+                                          false);
+
+                            Scalar volumeElement = fvGeometry.elementVolume;
 
                             this->setAdaptionValues(adaptedValues, problem.model().curSol()[dofIdx],scvIdx);
 
-                            if(isBox)
+                            if (int(formulation) == pwsn)
+                            {
+                                problem.model().curSol()[dofIdx][saturationIdx] = adaptedValues.associatedMass[nPhaseIdx];
+                                problem.model().curSol()[dofIdx][saturationIdx] /= volumeElement * volVars.density(nPhaseIdx) * volVars.porosity();
+                            }
+                            else if (int(formulation) == pnsw)
                             {
-                                VolumeVariables volVars;
-                                volVars.update(adaptedValues.u[scvIdx],
-                                              problem,
-                                              element,
-                                              fvGeometry,
-                                              scvIdx,
-                                              false);
+                                problem.model().curSol()[dofIdx][saturationIdx] = adaptedValues.associatedMass[wPhaseIdx];
+                                problem.model().curSol()[dofIdx][saturationIdx] /= volumeElement * volVars.density(wPhaseIdx) * volVars.porosity();
+                            }
 
+                            if(isBox)
+                            {
                                 Scalar volume = fvGeometry.subContVol[scvIdx].volume;
-                                Scalar volumeElement = fvGeometry.elementVolume;
-
                                 if (int(formulation) == pwsn)
                                 {
                                     massCoeff[dofIdx] += volume * volVars.density(nPhaseIdx) * volVars.porosity();
@@ -321,12 +334,12 @@ public:
                                 massCoeffSon = volume * volVars.density(wPhaseIdx) * volVars.porosity();
                             }
                             Scalar volumeFather = eFather.geometry().volume();
-                            adaptedValues.u[0][saturationIdx] = volume/volumeFather*massFather/massCoeffSon;
+                            adaptedValues.u[0][saturationIdx] = (volume/volumeFather*massFather)/massCoeffSon;
 
                             // if we are on leaf, store reconstructed values of son in CellData object
                             if (element.isLeaf())
                             {
-                                // acess new CellData object
+                                // access new CellData object
                                 int newIdxI = this->elementIndex(problem, element);
 
                                 this->setAdaptionValues(adaptedValues, problem.model().curSol()[newIdxI],0);
@@ -353,6 +366,7 @@ public:
                                 const LocalFiniteElementCache feCache;
                                 Dune::GeometryType geomType = eFather.geometry().type();
 
+                                // Interpolate values from father element by using ansatz functions
                                 const LocalFiniteElement &localFiniteElement = feCache.get(geomType);
                                 std::vector<Dune::FieldVector<Scalar, 1> > shapeVal;
                                 localFiniteElement.localBasis().evaluateFunction(dofCenterPos, shapeVal);
@@ -378,8 +392,7 @@ public:
                                     Scalar volume = fvGeometry.subContVol[scvIdx].volume;
                                     Scalar volumeFather = eFather.geometry().volume();
 
-                                    //int dofIdx = this->dofIndex(problem, subEntity);
-                                    int dofIdx = problem.model().dofMapper().subIndex(element,scvIdx,dofCodim);
+                                    int dofIdx = this->dofIndex(problem, element, scvIdx);
                                     if (int(formulation) == pwsn)
                                     {
                                         massCoeff[dofIdx] += volume * volVars.density(nPhaseIdx) * volVars.porosity();
@@ -446,7 +459,8 @@ public:
     {
         if(!isBox)
         {
-            if(adaptedValuesFather.u.size() == 0) adaptedValuesFather.u.resize(1);
+            if(adaptedValuesFather.u.size() == 0)
+                adaptedValuesFather.u.resize(1);
 
             adaptedValuesFather.u[0] += adaptedValues.u[0];
             adaptedValuesFather.u[0] /= adaptedValues.count;
@@ -454,7 +468,6 @@ public:
         }
         else
         {
-            //adaptedValuesFather.u = adaptedValues.u;
             adaptedValuesFather.associatedMass += adaptedValues.associatedMass;
         }
     }
@@ -482,30 +495,6 @@ public:
 
         u = uNew;
     }
-
-    //! Reconstructs sons entries from data of father cell
-    /**
-     * Reconstructs a new solution from a father cell into a newly
-     * generated son cell. New cell is stored into the global
-     * adaptionMap.
-     *
-     * \param adaptionMap Global map storing all values to be adapted
-     * \param father Entity Pointer to the father cell
-     * \param son Entity Pointer to the newly created son cell
-     * \param problem The problem
-     */
-    static void reconstructAdaptionValues(Dune::PersistentContainer<Grid, AdaptedValues>& adaptionMap,
-            const Element& father, const Element& son, const Problem& problem)
-    {
-        AdaptedValues& adaptedValues = adaptionMap[son];
-        AdaptedValues& adaptedValuesFather = adaptionMap[father];
-
-        adaptedValues.u = adaptedValuesFather.u;
-        adaptedValues.u /= adaptedValuesFather.count;
-    }
-
-
-
 };
 }
 #endif
-- 
GitLab