From c6b36d3ec7680b5a57145a4fb6f674a13a501a8e Mon Sep 17 00:00:00 2001
From: becker <beatrix.becker@iws.uni-stuttgart.de>
Date: Thu, 29 Aug 2019 11:03:24 +0200
Subject: [PATCH] [test material] add test for compositionalflash

---
 dumux/material/fluidstates/compositional.hh   |   2 +-
 test/material/CMakeLists.txt                  |   1 +
 .../compositionalflash/CMakeLists.txt         |   2 +
 .../test_compositionalflash.cc                | 292 ++++++++++++++++++
 4 files changed, 296 insertions(+), 1 deletion(-)
 create mode 100644 test/material/compositionalflash/CMakeLists.txt
 create mode 100644 test/material/compositionalflash/test_compositionalflash.cc

diff --git a/dumux/material/fluidstates/compositional.hh b/dumux/material/fluidstates/compositional.hh
index 02ff7a44e3..91bf96b5c7 100644
--- a/dumux/material/fluidstates/compositional.hh
+++ b/dumux/material/fluidstates/compositional.hh
@@ -128,7 +128,7 @@ public:
      * \brief Returns the phase mass fraction, i.e. phase mass per total mass \f$\mathrm{[kg/kg]}\f$.
      * \param phaseIdx the index of the phase
      */
-    Scalar phaseMassFraction(int phaseIdx)
+    Scalar phaseMassFraction(int phaseIdx) const
     {
         Scalar totalMass = 0.0;
         for (int pIdx = 0; pIdx < numPhases; ++pIdx)
diff --git a/test/material/CMakeLists.txt b/test/material/CMakeLists.txt
index 1c6dbe1271..ea48b8f61b 100644
--- a/test/material/CMakeLists.txt
+++ b/test/material/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_subdirectory(binarycoefficients)
 add_subdirectory(components)
+add_subdirectory(compositionalflash)
 add_subdirectory(fluidsystems)
 add_subdirectory(fluidmatrixinteractions)
 add_subdirectory(immiscibleflash)
diff --git a/test/material/compositionalflash/CMakeLists.txt b/test/material/compositionalflash/CMakeLists.txt
new file mode 100644
index 0000000000..3efcca4912
--- /dev/null
+++ b/test/material/compositionalflash/CMakeLists.txt
@@ -0,0 +1,2 @@
+dune_add_test(SOURCES test_compositionalflash.cc
+              LABELS unit material)
diff --git a/test/material/compositionalflash/test_compositionalflash.cc b/test/material/compositionalflash/test_compositionalflash.cc
new file mode 100644
index 0000000000..2e9841046d
--- /dev/null
+++ b/test/material/compositionalflash/test_compositionalflash.cc
@@ -0,0 +1,292 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 3 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \ingroup MaterialTests
+ * \brief This is a program to test the flash calculation routines
+ * for compositional sequential models
+ *
+ * This flash calculation determines the full fluid state of all phases, including
+ * pressures, saturations and composition, given the total mass of one component
+ * related to the total fluid mass in the pore space.
+ */
+
+#include <config.h>
+
+#include <dumux/material/constraintsolvers/misciblemultiphasecomposition.hh>
+#include <dumux/material/constraintsolvers/computefromreferencephase.hh>
+#include <dumux/material/constraintsolvers/compositionalflash.hh>
+
+#include <dumux/material/fluidstates/compositional.hh>
+
+#include <dumux/material/fluidsystems/h2on2.hh>
+
+#include <dumux/material/fluidmatrixinteractions/mp/mpadapter.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh>
+
+template <class Scalar, class FluidState>
+void checkSame(const FluidState &fsRef, const FluidState &fsFlash)
+{
+    enum { numPhases = FluidState::numPhases };
+    enum { numComponents = FluidState::numComponents };
+
+    for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+        Scalar error;
+
+        // check the pressures
+        using std::abs;
+        error = 1 - fsRef.pressure(phaseIdx)/fsFlash.pressure(phaseIdx);
+        if (abs(error) > 1e-6) {
+            std::cout << "pressure error phase " << phaseIdx << ": "
+                      << fsFlash.pressure(phaseIdx)  << " flash vs "
+                      << fsRef.pressure(phaseIdx) << " reference"
+                      << " error=" << error << "\n";
+        }
+
+        // check the saturations
+        error = fsRef.saturation(phaseIdx) - fsFlash.saturation(phaseIdx);
+        if (abs(error) > 1e-6)
+            std::cout << "saturation error phase " << phaseIdx << ": "
+                      << fsFlash.saturation(phaseIdx) << " flash vs "
+                      << fsRef.saturation(phaseIdx) << " reference"
+                      << " error=" << error << "\n";
+
+        // check the compositions for existing phases
+        if(fsRef.saturation(phaseIdx) > 0.0)
+            for (int compIdx = 0; compIdx < numComponents; ++ compIdx) {
+                error = fsRef.moleFraction(phaseIdx, compIdx) - fsFlash.moleFraction(phaseIdx, compIdx);
+                if (abs(error) > 1e-6)
+                    std::cout << "composition error phase " << phaseIdx << ", component " << compIdx << ": "
+                    << fsFlash.moleFraction(phaseIdx, compIdx) << " flash vs "
+                    << fsRef.moleFraction(phaseIdx, compIdx) << " reference"
+                    << " error=" << error << "\n";
+            }
+    }
+}
+
+template <class Scalar, class FluidSystem, class MaterialLaw, class FluidState>
+void checkCompositionalFlash(const FluidState &fsRef)
+{
+    enum { numPhases = FluidSystem::numPhases };
+    enum { numComponents = FluidSystem::numComponents };
+    using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
+
+    // calculate the total mass of the first component related to the total mass
+    // of fluids
+    Scalar Z0(0.0);
+    for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+        Z0 +=
+        fsRef.phaseMassFraction(phaseIdx)*fsRef.massFraction(phaseIdx, 0);
+    }
+
+    PhaseVector phasePressures;
+    for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+        phasePressures[phaseIdx] += fsRef.pressure(phaseIdx);
+    }
+
+    // make a new flash
+    Dumux::CompositionalFlash<Scalar, FluidSystem> flash;
+
+    // call flash for testing
+    FluidState fsFlash;
+    flash.concentrationFlash2p2c(fsFlash, Z0, phasePressures, 0/*dummy*/, fsRef.temperature(/*phaseIdx=*/0));
+
+    // compare the "flashed" fluid state with the reference one
+    checkSame<Scalar>(fsRef, fsFlash);
+}
+
+
+template <class Scalar, class FluidSystem, class MaterialLaw, class FluidState>
+void completeReferenceFluidState(FluidState &fs,
+                                 typename MaterialLaw::Params &matParams,
+                                 int refPhaseIdx)
+{
+    enum { numPhases = FluidSystem::numPhases };
+
+    using ComputeFromReferencePhase = Dumux::ComputeFromReferencePhase<Scalar, FluidSystem>;
+    using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
+
+    int otherPhaseIdx = 1 - refPhaseIdx;
+
+    // calculate the other saturation
+    fs.setSaturation(otherPhaseIdx, 1.0 - fs.saturation(refPhaseIdx));
+
+    // calulate the capillary pressure
+    PhaseVector pc;
+    MaterialLaw::capillaryPressures(pc, matParams, fs, /*liquidPhaseIdx=*/0);
+    fs.setPressure(otherPhaseIdx,
+                   fs.pressure(refPhaseIdx)
+                   + (pc[otherPhaseIdx] - pc[refPhaseIdx]));
+
+    // make the fluid state consistent with local thermodynamic
+    // equilibrium
+    typename FluidSystem::ParameterCache paramCache;
+    ComputeFromReferencePhase::solve(fs,
+                                     paramCache,
+                                     refPhaseIdx);
+}
+
+
+int main()
+{
+    using Scalar = double;
+    using FluidSystem = Dumux::FluidSystems::H2ON2<Scalar, Dumux::FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/true>>;
+    using CompositionalFluidState = Dumux::CompositionalFluidState<Scalar, FluidSystem>;
+
+    enum { numPhases = FluidSystem::numPhases };
+    enum { numComponents = FluidSystem::numComponents };
+    enum { liquidPhaseIdx = FluidSystem::liquidPhaseIdx };
+    enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
+    enum { wPhaseIdx = liquidPhaseIdx };
+
+    enum { H2OIdx = FluidSystem::H2OIdx };
+    enum { N2Idx = FluidSystem::N2Idx };
+
+    using EffMaterialLaw = Dumux::RegularizedBrooksCorey<Scalar>;
+    using MaterialLaw = Dumux::EffToAbsLaw<EffMaterialLaw>;
+    using MaterialLawParams = MaterialLaw::Params;
+    using MPAdapter = Dumux::MPAdapter<MaterialLaw, numPhases>;
+
+    Scalar T = 273.15 + 25;
+
+    // initialize the tables of the fluid system
+    Scalar Tmin = T - 1.0;
+    Scalar Tmax = T + 1.0;
+    int nT = 3;
+
+    Scalar pmin = 0.0;
+    Scalar pmax = 1.25 * 2e6;
+    int np = 100;
+
+    FluidSystem::init(Tmin, Tmax, nT, pmin, pmax, np);
+
+    // set the parameters for the capillary pressure law
+    MaterialLawParams matParams;
+    matParams.setSwr(0.0);
+    matParams.setSnr(0.0);
+    matParams.setPe(0);
+    matParams.setLambda(2.0);
+
+    CompositionalFluidState fsRef;
+
+    // create a fluid state which is consistent
+
+    // set the fluid temperatures
+    fsRef.setTemperature(T);
+
+    ////////////////
+    // only liquid
+    ////////////////
+    std::cout << "testing single-phase liquid\n";
+
+    // set liquid saturation
+    fsRef.setSaturation(liquidPhaseIdx, 1.0);
+
+    // set pressure of the liquid phase
+    fsRef.setPressure(liquidPhaseIdx, 2e5);
+
+    // set the liquid composition to pure water
+    fsRef.setMoleFraction(liquidPhaseIdx, N2Idx, 0.0);
+    fsRef.setMoleFraction(liquidPhaseIdx, H2OIdx, 1.0);
+
+    fsRef.setWettingPhase(wPhaseIdx);
+
+    // "complete" the fluid state
+    completeReferenceFluidState<Scalar, FluidSystem, MPAdapter>(fsRef, matParams, liquidPhaseIdx);
+
+    // check the flash calculation
+    checkCompositionalFlash<Scalar, FluidSystem, MPAdapter>(fsRef);
+
+    ////////////////
+    // only gas
+    ////////////////
+    std::cout << "testing single-phase gas\n";
+    // set gas saturation
+    fsRef.setSaturation(gasPhaseIdx, 1.0);
+
+    // set pressure of the gas phase
+    fsRef.setPressure(gasPhaseIdx, 1e6);
+
+    // set the gas composition to 99.9% nitrogen and 0.1% water
+    fsRef.setMoleFraction(gasPhaseIdx, N2Idx, 0.999);
+    fsRef.setMoleFraction(gasPhaseIdx, H2OIdx, 0.001);
+
+    // "complete" the fluid state
+    completeReferenceFluidState<Scalar, FluidSystem, MPAdapter>(fsRef, matParams, gasPhaseIdx);
+
+    // check the flash calculation
+    checkCompositionalFlash<Scalar, FluidSystem, MPAdapter>(fsRef);
+
+    ////////////////
+    // both phases
+    ////////////////
+    std::cout << "testing two-phase\n";
+
+    // set saturations
+    fsRef.setSaturation(liquidPhaseIdx, 0.5);
+    fsRef.setSaturation(gasPhaseIdx, 0.5);
+
+    // set pressures
+    fsRef.setPressure(liquidPhaseIdx, 1e6);
+    fsRef.setPressure(gasPhaseIdx, 1e6);
+
+    FluidSystem::ParameterCache paramCache;
+    using MiscibleMultiPhaseComposition = Dumux::MiscibleMultiPhaseComposition<Scalar, FluidSystem>;
+    MiscibleMultiPhaseComposition::solve(fsRef, paramCache);
+
+    // check the flash calculation
+    checkCompositionalFlash<Scalar, FluidSystem, MPAdapter>(fsRef);
+
+    ////////////////
+    // with capillary pressure
+    ////////////////
+
+    MaterialLawParams matParams2;
+    matParams2.setSwr(0.0);
+    matParams2.setSnr(0.0);
+    matParams2.setPe(1e3);
+    matParams2.setLambda(2.0);
+
+    // set gas saturation
+    fsRef.setSaturation(gasPhaseIdx, 0.5);
+    fsRef.setSaturation(liquidPhaseIdx, 0.5);
+
+    // set pressure of the liquid phase
+    fsRef.setPressure(liquidPhaseIdx, 1e6);
+
+    // calulate the capillary pressure
+    using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
+    PhaseVector pc;
+    MPAdapter::capillaryPressures(pc, matParams2, fsRef, /*wPhaseIdx=*/0);
+    fsRef.setPressure(gasPhaseIdx,
+                      fsRef.pressure(liquidPhaseIdx)
+                      + (pc[gasPhaseIdx] - pc[liquidPhaseIdx]));
+
+    using MiscibleMultiPhaseComposition = Dumux::MiscibleMultiPhaseComposition<Scalar, FluidSystem>;
+    MiscibleMultiPhaseComposition::solve(fsRef, paramCache);
+
+
+    // check the flash calculation
+    checkCompositionalFlash<Scalar, FluidSystem, MPAdapter>(fsRef);
+
+    return 0;
+}
-- 
GitLab