Brine-H2 PVT model To be used with H2STORE
Mostly copied CO2STORE and added specifications for brine-H2.
This commit is contained in:
376
opm/material/binarycoefficients/Brine_H2.hpp
Normal file
376
opm/material/binarycoefficients/Brine_H2.hpp
Normal file
@@ -0,0 +1,376 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::BinaryCoeff::Brine_H2
|
||||
*/
|
||||
#ifndef OPM_BINARY_COEFF_BRINE_H2_HPP
|
||||
#define OPM_BINARY_COEFF_BRINE_H2_HPP
|
||||
|
||||
#include <opm/material/IdealGas.hpp>
|
||||
#include <opm/material/binarycoefficients/FullerMethod.hpp>
|
||||
|
||||
#include <opm/material/components/H2O.hpp>
|
||||
#include <opm/material/components/H2.hpp>
|
||||
|
||||
namespace Opm {
|
||||
namespace BinaryCoeff {
|
||||
|
||||
/*!
|
||||
* \ingroup Binarycoefficients
|
||||
* \brief Binary coefficients for brine and CO2.
|
||||
*/
|
||||
template<class Scalar, class H2O, class H2, bool verbose = true>
|
||||
class Brine_H2 {
|
||||
using IdealGas = Opm::IdealGas<Scalar>;
|
||||
static const int liquidPhaseIdx = 0; // index of the liquid phase
|
||||
static const int gasPhaseIdx = 1; // index of the gas phase
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Returns the _mol_ (!) fraction of H2 in the liquid phase for a given temperature, pressure, H2 molality and
|
||||
* brine salinity. Implemented according to Li et al., Int. J. Hydrogen Energ., 2018.
|
||||
*
|
||||
* \param temperature temperature [K]
|
||||
* \param pg gas phase pressure [Pa]
|
||||
* \param salinity salinity [mol NaCl / kg solution]
|
||||
* \param knownPhaseIdx indicates which phases are present
|
||||
* \param xlH2 mole fraction of H2 in brine [mol/mol]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static void calculateMoleFractions(const Evaluation& temperature,
|
||||
const Evaluation& pg,
|
||||
Scalar salinity,
|
||||
Evaluation& xH2)
|
||||
{
|
||||
// All intermediate calculations
|
||||
Evaluation lnYH2 = moleFractionGasH2_(temperature, pg);
|
||||
Evaluation lnPg = log(pg / 1e6); // Pa --> MPa before ln
|
||||
Evaluation lnPhiH2 = fugacityCoefficientH2(temperature, pg);
|
||||
Evaluation lnKh = henrysConstant_(temperature);
|
||||
Evaluation PF = computePoyntingFactor_(temperature, pg);
|
||||
Evaluation lnGammaH2 = activityCoefficient_(temperature, salinity);
|
||||
|
||||
// Eq. (6) to get molality of H2 in brine
|
||||
Evaluation solH2 = exp(lnYH2 + lnPg + lnPhiH2 - lnKh - PF - lnGammaH2 - 4.0166);
|
||||
|
||||
// Convert to mole fraction
|
||||
xH2 = solH2 / (55.51 + solH2);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the Poynting Factor (PF) which is needed in calculation of H2 solubility in Li et al (2018).
|
||||
*
|
||||
* \param temperature temperature [K]
|
||||
* \param pg gas phase pressure [Pa]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation computePoyntingFactor_(const Evaluation& temperature, const Evaluation& pg)
|
||||
{
|
||||
// PF is approximated as a polynomial expansion in terms of temperature and pressure with the following
|
||||
// parameters (Table 4)
|
||||
static const Scalar a[4] = {6.156755, -2.502396e-2, 4.140593e-5, -1.322988e-3};
|
||||
|
||||
// Eq. (16)
|
||||
Evaluation pg_mpa = pg / 1.0e6; // convert from Pa to MPa
|
||||
Evaluation PF = a[0]*pg_mpa/temperature + a[1]*pg_mpa + a[2]*temperature*pg_mpa + a[3]*pg_mpa*pg_mpa/temperature;
|
||||
return PF;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the activity coefficient of H2 in brine which is needed in calculation of H2 solubility in Li et
|
||||
* al (2018). Note that we only include NaCl effects. Could be extended with other salts, e.g. from Duan & Sun,
|
||||
* Chem. Geol., 2003.
|
||||
*
|
||||
* \param temperature temperature [K]
|
||||
* \param salinity salinity [mol NaCl / kg solution]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation activityCoefficient_(const Evaluation& temperature, Scalar salinity)
|
||||
{
|
||||
// Linear approximation in temperature with following parameters (Table 5)
|
||||
static const Scalar a[2] = {0.64485, 0.00142};
|
||||
|
||||
// Eq. (17)
|
||||
Evaluation lnGamma = (a[0] - a[1]*temperature)*salinity;
|
||||
return lnGamma;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns Henry's constant of H2 in brine which is needed in calculation of H2 solubility in Li et al (2018).
|
||||
*
|
||||
* \param temperature temperature [K]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation henrysConstant_(const Evaluation& temperature)
|
||||
{
|
||||
// Polynomic approximation in temperature with following parameters (Table 2)
|
||||
static const Scalar a[5] = {2.68721e-5, -0.05121, 33.55196, -3411.0432, -31258.74683};
|
||||
|
||||
// Eq. (13)
|
||||
Evaluation lnKh = a[0]*temperature*temperature + a[1]*temperature + a[2] + a[3]/temperature
|
||||
+ a[4]/(temperature*temperature);
|
||||
return lnKh;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns mole fraction of H2 in gasous phase which is needed in calculation of H2 solubility in Li et al
|
||||
* (2018).
|
||||
*
|
||||
* \param temperature temperature [K]
|
||||
* \param pg gas phase pressure [Pa]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation moleFractionGasH2_(const Evaluation& temperature, const Evaluation& pg)
|
||||
{
|
||||
// Need saturaturated vapor pressure of pure water
|
||||
Evaluation pw_sat = H2O::vaporPressure(temperature);
|
||||
|
||||
// Eq. (12)
|
||||
Evaluation lnyH2 = log(1 - (pw_sat / pg));
|
||||
return lnyH2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Calculate fugacity coefficient for H2 which is needed in calculation of H2 solubility in Li et al (2018).
|
||||
* The equation used is based on Helmoltz free energy EOS. The formulas here are taken from Span et al., J. Phys.
|
||||
* Chem. Ref. Data 29, 2000 and adapted to H2 in Li et al (2018).
|
||||
*
|
||||
* \param temperature temperature [K]
|
||||
* \param pg gas phase pressure [Pa]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation fugacityCoefficientH2(const Evaluation& temperature, const Evaluation& pg)
|
||||
{
|
||||
// Convert pressure to reduced density and temperature to reduced temperature
|
||||
Evaluation rho_red = convertPgToReducedRho_(temperature, pg);
|
||||
Evaluation T_red = temperature / H2::criticalTemperature();
|
||||
|
||||
// Residual Helmholtz energy, Eq. (7) in Li et al. (2018)
|
||||
Evaluation resHelm = residualHelmholtz_(T_red, rho_red);
|
||||
|
||||
// Derivative of residual Helmholtz energy wrt to reduced density, Eq. (73) in Span et al. (2018)
|
||||
Evaluation dResdHelm = derivResidualHelmholtz_(T_red, rho_red);
|
||||
|
||||
// Fugacity coefficient, Eq. (8) in Li et al. (2018)
|
||||
Evaluation lnPhiH2 = resHelm + rho_red * dResdHelm - log(rho_red * dResdHelm + 1);
|
||||
|
||||
return lnPhiH2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Convert pressure to reduced density (rho/rho_crit) for further calculation of fugacity coefficient in Li et
|
||||
* al. (2018) and Span et al. (2000). The conversion is done using the simplest root-finding algorithm, i.e. the
|
||||
* bisection method.
|
||||
*
|
||||
* \param pg gas phase pressure [Pa]
|
||||
* \param temperature temperature [K]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation convertPgToReducedRho_(const Evaluation& temperature, const Evaluation& pg)
|
||||
{
|
||||
// Interval for search
|
||||
Scalar rho_red_min = 0.0;
|
||||
Scalar rho_red_max = 1.0;
|
||||
|
||||
// Obj. value at min, fmin=f(xmin) for first comparison with fmid=f(xmid)
|
||||
Evaluation fmin = -pg / 1.0e6; // at 0.0 we don't need to envoke function (see also why in rootFindingObj_)
|
||||
|
||||
// Bisection loop
|
||||
for (int iteration=1; iteration<100; ++iteration) {
|
||||
// New midpoint and its obj. value
|
||||
Evaluation rho_red = (rho_red_min + rho_red_max) / 2;
|
||||
Evaluation fmid = rootFindingObj_(rho_red, temperature, pg);
|
||||
|
||||
// Check if midpoint fulfills f=0 or x-xmin is sufficiently small
|
||||
if (Opm::abs(fmid) < 1e-8 || Opm::abs((rho_red_max - rho_red_min) / 2) < 1e-8) {
|
||||
return rho_red
|
||||
}
|
||||
|
||||
// Else we repeat with midpoint being either xmin or xmax (depending on the signs)
|
||||
else if (Dune::sign(fmid) != Dune::sign(fmin)) {
|
||||
// fmid has same sign as fmax so we set xmid as the new xmax
|
||||
rho_red_max = rho_red;
|
||||
}
|
||||
else {
|
||||
// fmid has same sign as fmin so we set xmid as the new xmin
|
||||
rho_red_min = rho_red;
|
||||
fmin = fmid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Objective function in root-finding done in convertPgToReducedRho_ taken from Li et al. (2018).
|
||||
*
|
||||
* \param rho_red reduced density [-]
|
||||
* \param pg gas phase pressure [Pa]
|
||||
* \param temperature temperature [K]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation rootFindingObj_(const Evaluation& rho_red, const Evaluation& temperature, const Evaluation& pg)
|
||||
{
|
||||
// Temporary calculations
|
||||
Evaluation T_red = temperature / H2::criticalTemperature(); // reduced temp.
|
||||
Evaluation p_MPa = pg / 1.0e6; // Pa --> MPa
|
||||
Scalar R = IdealGas::R;
|
||||
Evaluation rho_cRT = H2::criticalDensity() * R * temperature;
|
||||
|
||||
// Eq. (9)
|
||||
Evaluation dResdH = derivResidualHelmholtz_(T_red, rho_red);
|
||||
Evaluation obj = rho_red * rho_cRT * (1 + rho_red * dResdH) - p_MPa;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Derivative of the residual part of Helmholtz energy wrt. reduced density. Used primarily to calculate
|
||||
* fugacity coefficient for H2.
|
||||
*
|
||||
* \param T_red reduced temperature [-]
|
||||
* \param rho_red reduced density [-]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation derivResidualHelmholtz_(const Evaluation& T_red, const Evaluation& rho_red)
|
||||
{
|
||||
// Various parameter values needed in calculations (Table 1 in Li et al. (2018))
|
||||
static const Scalar N[14] = {-6.93643, 0.01, 2.1101, 4.52059, 0.732564, -1.34086, 0.130985, -0.777414,
|
||||
0.351944, -0.0211716, 0.0226312, 0.032187, -0.0231752, 0.0557346};
|
||||
|
||||
static const Scalar t[14] = {0.6844, 1.0, 0.989, 0.489, 0.803, 1.1444, 1.409, 1.754, 1.311, 4.187, 5.646,
|
||||
0.791, 7.249, 2.986};
|
||||
|
||||
static const int d[14] = {1, 4, 1, 1, 2, 2, 3, 1, 3, 2, 1, 3, 1, 1};
|
||||
|
||||
static const int p[2] = {1, 1};
|
||||
|
||||
static const Scalar phi[5] = {-1.685, -0.489, -0.103, -2.506, -1.607};
|
||||
|
||||
static const Scalar beta[5] = {-0.1710, -0.2245, -0.1304, -0.2785, -0.3967};
|
||||
|
||||
static const Scalar gamma[5] = {0.7164, 1.3444, 1.4517, 0.7204, 1.5445};
|
||||
|
||||
static const Scalar D[5] = {1.506, 0.156, 1.736, 0.670, 1.662};
|
||||
|
||||
// Derivative of Eq. (7) in Li et al. (2018), which can be compared with Eq. (73) in Span et al. (2000)
|
||||
// First sum term
|
||||
Evaluation s1 = 0.0;
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
s1 += d[i] * N[i] * pow(rho_red, d[i]-1) * pow(T_red, t[i]);
|
||||
}
|
||||
|
||||
// Second sum term
|
||||
Evaluation s2 = 0.0;
|
||||
for (int i = 7; i < 9; ++i) {
|
||||
s2 += N[i] * pow(T_red, t[i]) * pow(rho_red, d[i]-1) * exp(-pow(rho_red, p[i-7])) *
|
||||
(d[i] - p[i-7]*pow(rho_red, p[i-7]));
|
||||
}
|
||||
|
||||
// Third, and last, sum term
|
||||
Evaluation s3 = 0.0;
|
||||
for (int i = 9; i < 15; ++i) {
|
||||
s3 += N[i] * pow(T_red, t[i]) * pow(rho_red, d[i]-1) *
|
||||
exp(phi[i-9] * pow(rho_red - D[i-9], 2) + beta[i-9] * pow(T_red - gamma[i-9], 2)) *
|
||||
(d[i] + 2 * phi[i-9] * rho_red * (rho_red - D[i-9]));
|
||||
}
|
||||
|
||||
// Return total sum
|
||||
Evaluation s = s1 + s2 + s3;
|
||||
return s;
|
||||
}
|
||||
/*!
|
||||
* \brief The residual part of Helmholtz energy wrt. reduced density. Used primarily to calculate fugacity
|
||||
* coefficient for H2.
|
||||
*
|
||||
* \param T_red reduced temperature [-]
|
||||
* \param rho_red reduced density [-]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
static Evaluation residualHelmholtz_(const Evaluation& T_red, const Evaluation& rho_red)
|
||||
{
|
||||
// Various parameter values needed in calculations (Table 1 in Li et al. (2018))
|
||||
static const Scalar N[14] = {-6.93643, 0.01, 2.1101, 4.52059, 0.732564, -1.34086, 0.130985, -0.777414,
|
||||
0.351944, -0.0211716, 0.0226312, 0.032187, -0.0231752, 0.0557346};
|
||||
|
||||
static const Scalar t[14] = {0.6844, 1.0, 0.989, 0.489, 0.803, 1.1444, 1.409, 1.754, 1.311, 4.187, 5.646,
|
||||
0.791, 7.249, 2.986};
|
||||
|
||||
static const int d[14] = {1, 4, 1, 1, 2, 2, 3, 1, 3, 2, 1, 3, 1, 1};
|
||||
|
||||
static const int p[2] = {1, 1};
|
||||
|
||||
static const Scalar phi[5] = {-1.685, -0.489, -0.103, -2.506, -1.607};
|
||||
|
||||
static const Scalar beta[5] = {-0.1710, -0.2245, -0.1304, -0.2785, -0.3967};
|
||||
|
||||
static const Scalar gamma[5] = {0.7164, 1.3444, 1.4517, 0.7204, 1.5445};
|
||||
|
||||
static const Scalar D[5] = {1.506, 0.156, 1.736, 0.670, 1.662};
|
||||
|
||||
// Eq. (7) in Li et al. (2018), which can be compared with Eq. (55) in Span et al. (2000)
|
||||
// First sum term
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
s1 += N[i] * pow(rho_red, d[i]) * pow(T_red, t[i]);
|
||||
}
|
||||
|
||||
// Second sum term
|
||||
Evaluation s2 = 0.0;
|
||||
for (int i = 7; i < 9; ++i) {
|
||||
s2 += N[i] * pow(T_red, t[i]) * pow(rho_red, d[i]) * exp(-pow(rho_red, p[i-7]));
|
||||
}
|
||||
|
||||
// Third, and last, sum term
|
||||
Evaluation s3 = 0.0;
|
||||
for (int i = 9; i < 15; ++i) {
|
||||
s3 += N[i] * pow(T_red, t[i]) * pow(rho_red, d[i]) *
|
||||
exp(phi[i-9] * pow(rho_red - D[i-9], 2) + beta[i-9] * pow(T_red - gamma[i-9], 2));
|
||||
}
|
||||
|
||||
// Return total sum
|
||||
Evaluation s = s1 + s2 + s3;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Binary diffusion coefficent [m^2/s] for molecular water and H2 as an approximation for brine-H2 diffusion.
|
||||
*
|
||||
* To calculate the values, the \ref fullerMethod is used.
|
||||
*/
|
||||
template <class Scalar, class Evaluation = Scalar>
|
||||
static Evaluation gasDiffCoeff(const Evaluation& temperature, const Evaluation& pressure)
|
||||
{
|
||||
typedef H2O<Scalar> H2O;
|
||||
typedef H2<Scalar> H2;
|
||||
|
||||
// atomic diffusion volumes
|
||||
const Scalar SigmaNu[2] = { 13.1 /* H2O */, 7.07 /* CO2 */ };
|
||||
// molar masses [g/mol]
|
||||
const Scalar M[2] = { H2O::molarMass()*1e3, H2::molarMass()*1e3 };
|
||||
|
||||
return fullerMethod(M, SigmaNu, temperature, pressure);
|
||||
}
|
||||
}; // end class Brine_H2
|
||||
|
||||
} // end namespace BinaryCoeff
|
||||
} // end namespace Opm
|
||||
#endif
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "blackoilpvt/GasPvtMultiplexer.hpp"
|
||||
#include "blackoilpvt/WaterPvtMultiplexer.hpp"
|
||||
#include "blackoilpvt/BrineCo2Pvt.hpp"
|
||||
#include "blackoilpvt/BrineH2Pvt.hpp"
|
||||
|
||||
#include <opm/common/TimingMacros.hpp>
|
||||
|
||||
|
||||
427
opm/material/fluidsystems/blackoilpvt/BrineH2Pvt.hpp
Normal file
427
opm/material/fluidsystems/blackoilpvt/BrineH2Pvt.hpp
Normal file
@@ -0,0 +1,427 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
* \copydoc Opm::BrineH2Pvt
|
||||
*/
|
||||
#ifndef OPM_BRINE_H2_PVT_HPP
|
||||
#define OPM_BRINE_H2_PVT_HPP
|
||||
|
||||
#include <opm/material/binarycoefficients/Brine_H2.hpp>
|
||||
#include <opm/material/components/SimpleHuDuanH2O.hpp>
|
||||
#include <opm/material/components/Brine.hpp>
|
||||
#include <opm/material/components/H2.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#if HAVE_ECL_INPUT
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#endif
|
||||
|
||||
namespace Opm {
|
||||
/*!
|
||||
* \brief This class represents the Pressure-Volume-Temperature relations of the liquid phase for a H2-Brine system
|
||||
*/
|
||||
template <class Scalar>
|
||||
class BrineH2Pvt
|
||||
{
|
||||
static const bool extrapolate = true;
|
||||
public:
|
||||
typedef SimpleHuDuanH2O<Scalar> H2O;
|
||||
typedef ::Opm::Brine<Scalar, H2O> Brine;
|
||||
typedef ::Opm::H2<Scalar> H2;
|
||||
|
||||
// The binary coefficients for brine and H2 used by this fluid system
|
||||
typedef BinaryCoeff::Brine_H2<Scalar, H2O, H2> BinaryCoeffBrineH2;
|
||||
|
||||
explicit BrineH2Pvt() = default;
|
||||
BrineH2Pvt( const std::vector<Scalar>& brineReferenceDensity,
|
||||
const std::vector<Scalar>& h2ReferenceDensity,
|
||||
const std::vector<Scalar>& salinity)
|
||||
: brineReferenceDensity_(brineReferenceDensity),
|
||||
h2ReferenceDensity_(h2ReferenceDensity),
|
||||
salinity_(salinity)
|
||||
{
|
||||
}
|
||||
#if HAVE_ECL_INPUT
|
||||
/*!
|
||||
* \brief Initialize the parameters for Brine-H2 system using an ECL deck.
|
||||
*
|
||||
*/
|
||||
void initFromState(const EclipseState& eclState, const Schedule&)
|
||||
{
|
||||
// Error message for DENSITY keyword
|
||||
if (!eclState.getTableManager().getDensityTable().empty()) {
|
||||
std::cerr << "WARNING: H2STORE is enabled but DENSITY is in the deck. \n" <<
|
||||
"The surface density is computed based on H2-BRINE PVT at standard conditions (STCOND)" <<
|
||||
" and DENSITY is ignored " << std::endl;
|
||||
}
|
||||
// Error message for entering PVDO/PVTO in deck
|
||||
if (eclState.getTableManager().hasTables("PVDO") || !eclState.getTableManager().getPvtoTables().empty()) {
|
||||
std::cerr << "WARNING: H2STORE is enabled but PVDO or PVTO is in the deck. \n" <<
|
||||
"BRINE PVT properties are computed based on the Li et al. (2018) and PVDO/PVTO input" <<
|
||||
" is ignored. " << std::endl;
|
||||
}
|
||||
|
||||
// We only supported single pvt region for the H2-brine module
|
||||
size_t numRegions = 1;
|
||||
setNumRegions(numRegions);
|
||||
size_t regionIdx = 0;
|
||||
|
||||
// Currently we only support constant salinity
|
||||
const Scalar molality = eclState.getTableManager().salinity(); // mol/kg
|
||||
const Scalar MmNaCl = 58e-3; // molar mass of NaCl [kg/mol]
|
||||
Brine::salinity = 1 / ( 1 + 1 / (molality*MmNaCl)); // convert to mass fraction
|
||||
salinity_[regionIdx] = molality; // molality used in functions
|
||||
|
||||
// set the surface conditions using the STCOND keyword
|
||||
Scalar T_ref = eclState.getTableManager().stCond().temperature;
|
||||
Scalar P_ref = eclState.getTableManager().stCond().pressure;
|
||||
|
||||
brineReferenceDensity_[regionIdx] = Brine::liquidDensity(T_ref, P_ref, extrapolate);
|
||||
h2ReferenceDensity_[regionIdx] = H2::gasDensity(T_ref, P_ref);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setNumRegions(size_t numRegions)
|
||||
{
|
||||
brineReferenceDensity_.resize(numRegions);
|
||||
h2ReferenceDensity_.resize(numRegions);
|
||||
salinity_.resize(numRegions);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initialize the reference densities of all fluids for a given PVT region
|
||||
*/
|
||||
void setReferenceDensities(unsigned regionIdx,
|
||||
Scalar rhoRefBrine,
|
||||
Scalar rhoRefH2,
|
||||
Scalar /*rhoRefWater*/)
|
||||
{
|
||||
brineReferenceDensity_[regionIdx] = rhoRefBrine;
|
||||
h2ReferenceDensity_[regionIdx] = rhoRefH2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Finish initializing the oil phase PVT properties.
|
||||
*/
|
||||
void initEnd()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Return the number of PVT regions which are considered by this PVT-object.
|
||||
*/
|
||||
unsigned numRegions() const
|
||||
{ return brineReferenceDensity_.size(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns the specific enthalpy [J/kg] of gas given a set of parameters.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation internalEnergy(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
const Evaluation& Rs) const
|
||||
{
|
||||
// NOT IMPLEMENTED YET!
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation viscosity(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
const Evaluation& /*Rs*/) const
|
||||
{
|
||||
//TODO: The viscosity does not yet depend on the composition
|
||||
return saturatedViscosity(regionIdx, temperature, pressure);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the dynamic viscosity [Pa s] of oil saturated gas at given pressure.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedViscosity(unsigned /*regionIdx*/,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure) const
|
||||
{
|
||||
return Brine::liquidViscosity(temperature, pressure);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the formation volume factor [-] of the fluid phase.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
const Evaluation& Rs) const
|
||||
{
|
||||
return density_(regionIdx, temperature, pressure, Rs)/brineReferenceDensity_[regionIdx];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the formation volume factor [-] of brine saturated with CO2 at a given pressure.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure) const
|
||||
{
|
||||
Evaluation rsSat = rsSat_(regionIdx, temperature, pressure);
|
||||
return density_(regionIdx, temperature, pressure, rsSat)/brineReferenceDensity_[regionIdx];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the saturation pressure of the brine phase [Pa] depending on its mass fraction of the gas component
|
||||
*
|
||||
* \param Rs
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturationPressure(unsigned /*regionIdx*/,
|
||||
const Evaluation& /*temperature*/,
|
||||
const Evaluation& /*Rs*/) const
|
||||
{
|
||||
throw std::runtime_error("Requested the saturation pressure for the brine-co2 pvt module. Not yet implemented.");
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the gas dissoluiton factor \f$R_s\f$ [m^3/m^3] of the liquid phase.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
const Evaluation& /*oilSaturation*/,
|
||||
const Evaluation& /*maxOilSaturation*/) const
|
||||
{
|
||||
//TODO support VAPPARS
|
||||
return rsSat_(regionIdx, temperature, pressure);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns thegas dissoluiton factor \f$R_s\f$ [m^3/m^3] of the liquid phase.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure) const
|
||||
{
|
||||
return rsSat_(regionIdx, temperature, pressure);
|
||||
}
|
||||
|
||||
const Scalar oilReferenceDensity(unsigned regionIdx) const
|
||||
{ return brineReferenceDensity_[regionIdx]; }
|
||||
|
||||
const Scalar gasReferenceDensity(unsigned regionIdx) const
|
||||
{ return h2ReferenceDensity_[regionIdx]; }
|
||||
|
||||
const Scalar salinity(unsigned regionIdx) const
|
||||
{ return salinity_[regionIdx]; }
|
||||
|
||||
bool operator==(const BrineH2Pvt<Scalar>& data) const
|
||||
{
|
||||
return h2ReferenceDensity_ == data.h2ReferenceDensity_ &&
|
||||
brineReferenceDensity_ == data.brineReferenceDensity_;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Diffusion coefficient of H2 in water
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation diffusionCoefficient(const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
unsigned /*compIdx*/) const
|
||||
{
|
||||
// NOT IMPLEMENTED YET!
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Scalar> brineReferenceDensity_;
|
||||
std::vector<Scalar> h2ReferenceDensity_;
|
||||
std::vector<Scalar> salinity_;
|
||||
|
||||
/*!
|
||||
* \brief Calculate density of aqueous solution (H2O-NaCl/brine and H2).
|
||||
*
|
||||
* \param temperature temperature [K]
|
||||
* \param pressure pressure [Pa]
|
||||
* \param Rs gas dissolution factor [-]
|
||||
*/
|
||||
template <class LhsEval>
|
||||
LhsEval density_(unsigned regionIdx,
|
||||
const LhsEval& temperature,
|
||||
const LhsEval& pressure,
|
||||
const LhsEval& Rs) const
|
||||
{
|
||||
// convert Rs to mole fraction (via mass fraction)
|
||||
LhsEval xlH2 = convertXoGToxoG_(convertRsToXoG_(Rs,regionIdx));
|
||||
|
||||
// calculate the density of solution
|
||||
LhsEval result = liquidDensity_(temperature,
|
||||
pressure,
|
||||
xlH2);
|
||||
|
||||
Valgrind::CheckDefined(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Calculated the density of the aqueous solution where contributions of salinity and dissolved H2 is taken
|
||||
* into account.
|
||||
*
|
||||
* \param T temperature [K]
|
||||
* \param pl liquid pressure [Pa]
|
||||
* \param xlH2 mole fraction H2 [-]
|
||||
*/
|
||||
template <class LhsEval>
|
||||
LhsEval liquidDensity_(const LhsEval& T,
|
||||
const LhsEval& pl,
|
||||
const LhsEval& xlH2) const
|
||||
{
|
||||
// check input variables
|
||||
Valgrind::CheckDefined(T);
|
||||
Valgrind::CheckDefined(pl);
|
||||
Valgrind::CheckDefined(xlH2);
|
||||
|
||||
// calculate individual contribution to density
|
||||
const LhsEval& rho_brine = Brine::liquidDensity(T, pl, extrapolate);
|
||||
const LhsEval& rho_pure = H2O::liquidDensity(T, pl, extrapolate);
|
||||
const LhsEval& rho_lH2 = liquidDensityWaterH2_(T, pl, xlH2);
|
||||
const LhsEval& contribH2 = rho_lH2 - rho_pure;
|
||||
|
||||
return rho_brine + contribH2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Density of aqueous solution with dissolved H2. Formula from Li et al. (2018) and Garica, Lawrence Berkeley
|
||||
* National Laboratory, 2001.
|
||||
*
|
||||
* \param temperature [K]
|
||||
* \param pl liquid pressure [Pa]
|
||||
* \param xlH2 mole fraction [-]
|
||||
*/
|
||||
template <class LhsEval>
|
||||
LhsEval liquidDensityWaterH2_(const LhsEval& temperature,
|
||||
const LhsEval& pl,
|
||||
const LhsEval& xlH2) const
|
||||
{
|
||||
// molar masses
|
||||
Scalar M_H2 = H2::molarMass();
|
||||
Scalar M_H2O = H2O::molarMass();
|
||||
|
||||
// density of pure water
|
||||
const LhsEval& rho_pure = H2O::liquidDensity(temperature, pl, extrapolate);
|
||||
|
||||
// (apparent) molar volume of H2, Eq. (14) in Li et al. (2018)
|
||||
const LhsEval& A1 = 51.1904 - 0.208062*temperature + 3.4427e-4*temperature*temperature;
|
||||
const LhsEval& A2 = -0.022;
|
||||
const LhsEval& V_phi = A1 + A2 * pl;
|
||||
|
||||
// density of solution, Eq. (19) in Garcia (2001)
|
||||
const LhsEval xlH2O = 1.0 - xlH2;
|
||||
const LhsEval& M_T = M_H2O * xlH2O + M_H2 * xlH2;
|
||||
const LhsEval& rho_aq = 1 / (xlH2 * V_phi/M_T + M_H2O * xlH2O / (rho_pure * M_T));
|
||||
|
||||
return rho_aq;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Convert a gas dissolution factor to the the corresponding mass fraction of the gas component in the oil
|
||||
* phase.
|
||||
*
|
||||
* \param Rs gass dissolution factor [-]
|
||||
* \param regionIdx region index
|
||||
*/
|
||||
template <class LhsEval>
|
||||
LhsEval convertRsToXoG_(const LhsEval& Rs, unsigned regionIdx) const
|
||||
{
|
||||
Scalar rho_oRef = brineReferenceDensity_[regionIdx];
|
||||
Scalar rho_gRef = h2ReferenceDensity_[regionIdx];
|
||||
|
||||
const LhsEval& rho_oG = Rs*rho_gRef;
|
||||
return rho_oG/(rho_oRef + rho_oG);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Convert a gas mass fraction in the oil phase the corresponding mole fraction.
|
||||
*
|
||||
* \param XoG mass fraction [-]
|
||||
*/
|
||||
template <class LhsEval>
|
||||
LhsEval convertXoGToxoG_(const LhsEval& XoG) const
|
||||
{
|
||||
Scalar M_H2 = H2::molarMass();
|
||||
Scalar M_Brine = Brine::molarMass();
|
||||
return XoG*M_Brine / (M_H2*(1 - XoG) + XoG*M_Brine);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Convert the mass fraction of the gas component in the oil phase to the corresponding gas dissolution
|
||||
* factor.
|
||||
*
|
||||
* \param XoG mass fraction [-]
|
||||
* \param regionIdx region index
|
||||
*/
|
||||
template <class LhsEval>
|
||||
LhsEval convertXoGToRs(const LhsEval& XoG, unsigned regionIdx) const
|
||||
{
|
||||
Scalar rho_oRef = brineReferenceDensity_[regionIdx];
|
||||
Scalar rho_gRef = h2ReferenceDensity_[regionIdx];
|
||||
|
||||
return XoG/(1.0 - XoG)*(rho_oRef/rho_gRef);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Saturated gas dissolution factor, Rs.
|
||||
*
|
||||
* \param regionIdx region index
|
||||
* \param temperature [K]
|
||||
* \param pressure pressure [Pa]
|
||||
*/
|
||||
template <class LhsEval>
|
||||
LhsEval rsSat_(unsigned regionIdx,
|
||||
const LhsEval& temperature,
|
||||
const LhsEval& pressure) const
|
||||
{
|
||||
// calulate the equilibrium composition for the given temperature and pressure
|
||||
LhsEval xlH2;
|
||||
BinaryCoeffBrineH2::calculateMoleFractions(temperature,
|
||||
pressure,
|
||||
salinity_[regionIdx],
|
||||
xlH2);
|
||||
|
||||
// normalize the phase compositions
|
||||
xlH2 = max(0.0, min(1.0, xlH2));
|
||||
|
||||
return convertXoGToRs(convertxoGToXoG(xlH2), regionIdx);
|
||||
}
|
||||
}; // end class BrineH2Pvt
|
||||
} // end namespace Opm
|
||||
#endif
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "WetGasPvt.hpp"
|
||||
#include "GasPvtThermal.hpp"
|
||||
#include "Co2GasPvt.hpp"
|
||||
#include "H2GasPvt.hpp"
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -72,6 +73,11 @@ class Schedule;
|
||||
auto& pvtImpl = getRealPvt<GasPvtApproach::Co2Gas>(); \
|
||||
codeToCall; \
|
||||
break; \
|
||||
}
|
||||
case GasPvtApproach::H2GasPvt: { \
|
||||
auto& pvtImpl = getRealPvt<GasPvtApproach::H2GasPvt>(); \
|
||||
codeToCall; \
|
||||
break; \
|
||||
} \
|
||||
case GasPvtApproach::NoGas: \
|
||||
throw std::logic_error("Not implemented: Gas PVT of this deck!"); \
|
||||
@@ -85,6 +91,7 @@ enum class GasPvtApproach {
|
||||
WetGas,
|
||||
ThermalGas,
|
||||
Co2Gas
|
||||
H2GasPvt
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -144,6 +151,10 @@ public:
|
||||
delete &getRealPvt<GasPvtApproach::Co2Gas>();
|
||||
break;
|
||||
}
|
||||
case GasPvtApproach::H2GasPvt: {
|
||||
delete &getRealPvt<GasPvtApproach::H2GasPvt>();
|
||||
break;
|
||||
}
|
||||
case GasPvtApproach::NoGas:
|
||||
break;
|
||||
}
|
||||
@@ -185,6 +196,10 @@ public:
|
||||
realGasPvt_ = new Co2GasPvt<Scalar>;
|
||||
break;
|
||||
|
||||
case GasPvtApproach::H2GasPvt:
|
||||
realGasPvt_ = new H2GasPvt<Scalar>;
|
||||
break;
|
||||
|
||||
case GasPvtApproach::NoGas:
|
||||
throw std::logic_error("Not implemented: Gas PVT of this deck!");
|
||||
}
|
||||
@@ -416,6 +431,13 @@ public:
|
||||
return *static_cast<const Co2GasPvt<Scalar>* >(realGasPvt_);
|
||||
}
|
||||
|
||||
template <GasPvtApproach approachV>
|
||||
typename std::enable_if<approachV == GasPvtApproach::H2GasPvt, const H2GasPvt<Scalar> >::type& getRealPvt() const
|
||||
{
|
||||
assert(gasPvtApproach() == approachV);
|
||||
return *static_cast<const H2GasPvt<Scalar>* >(realGasPvt_);
|
||||
}
|
||||
|
||||
const void* realGasPvt() const { return realGasPvt_; }
|
||||
|
||||
GasPvtMultiplexer<Scalar,enableThermal>& operator=(const GasPvtMultiplexer<Scalar,enableThermal>& data)
|
||||
@@ -440,6 +462,9 @@ public:
|
||||
case GasPvtApproach::Co2Gas:
|
||||
realGasPvt_ = new Co2GasPvt<Scalar>(*static_cast<const Co2GasPvt<Scalar>*>(data.realGasPvt_));
|
||||
break;
|
||||
case GasPvtApproach::H2GasPvt:
|
||||
realGasPvt_ = new H2GasPvt<Scalar>(*static_cast<const H2GasPvt<Scalar>*>(data.realGasPvt_));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
229
opm/material/fluidsystems/blackoilpvt/H2GasPvt.hpp
Normal file
229
opm/material/fluidsystems/blackoilpvt/H2GasPvt.hpp
Normal file
@@ -0,0 +1,229 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
* \copydoc Opm::H2GasPvt
|
||||
*/
|
||||
#ifndef OPM_H2_GAS_PVT_HPP
|
||||
#define OPM_H2_GAS_PVT_HPP
|
||||
|
||||
#include <opm/material/components/SimpleHuDuanH2O.hpp>
|
||||
#include <opm/material/binarycoefficients/Brine_H2.hpp>
|
||||
|
||||
#if HAVE_ECL_INPUT
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \brief This class represents the Pressure-Volume-Temperature relations of the gas phase for H2
|
||||
*/
|
||||
template <class Scalar>
|
||||
class H2GasPvt
|
||||
{
|
||||
typedef SimpleHuDuanH2O<Scalar> H2O;
|
||||
typedef ::Opm::H2<Scalar> H2;
|
||||
|
||||
public:
|
||||
// The binary coefficients for brine and H2 used by this fluid system
|
||||
typedef BinaryCoeff::Brine_H2<Scalar, H2O, H2> BinaryCoeffBrineH2;
|
||||
|
||||
explicit H2GasPvt() = default;
|
||||
H2GasPvt(const std::vector<Scalar>& gasReferenceDensity)
|
||||
: gasReferenceDensity_(gasReferenceDensity)
|
||||
{
|
||||
}
|
||||
|
||||
#if HAVE_ECL_INPUT
|
||||
/*!
|
||||
* \brief Initialize the parameters for H2 gas using an ECL deck.
|
||||
*/
|
||||
void initFromState(const EclipseState& eclState, const Schedule&)
|
||||
{
|
||||
if( !eclState.getTableManager().getDensityTable().empty()) {
|
||||
std::cerr << "WARNING: H2STORE is enabled but DENSITY is in the deck. \n" <<
|
||||
"The surface density is computed based on H2-BRINE PVT at standard conditions (STCOND)" <<
|
||||
" and DENSITY is ignored " << std::endl;
|
||||
}
|
||||
|
||||
if( eclState.getTableManager().hasTables("PVDG") || !eclState.getTableManager().getPvtgTables().empty()) {
|
||||
std::cerr << "WARNING: H2STORE is enabled but PVDG or PVTG is in the deck. \n" <<
|
||||
"H2 pvt properties are calculated based on ideal gas relations, and PVDG/PVTG input" <<
|
||||
" is ignored. " << std::endl;
|
||||
}
|
||||
|
||||
// We only supported single pvt region for the H2-brine module
|
||||
size_t numRegions = 1;
|
||||
setNumRegions(numRegions);
|
||||
size_t regionIdx = 0;
|
||||
Scalar T_ref = eclState.getTableManager().stCond().temperature;
|
||||
Scalar P_ref = eclState.getTableManager().stCond().pressure;
|
||||
gasReferenceDensity_[regionIdx] = H2::gasDensity(T_ref, P_ref);
|
||||
initEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
void setNumRegions(size_t numRegions)
|
||||
{
|
||||
gasReferenceDensity_.resize(numRegions);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Initialize the reference densities of all fluids for a given PVT region
|
||||
*/
|
||||
void setReferenceDensities(unsigned regionIdx,
|
||||
Scalar /*rhoRefOil*/,
|
||||
Scalar rhoRefGas,
|
||||
Scalar /*rhoRefWater*/)
|
||||
{
|
||||
gasReferenceDensity_[regionIdx] = rhoRefGas;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Finish initializing the oil phase PVT properties.
|
||||
*/
|
||||
void initEnd()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Return the number of PVT regions which are considered by this PVT-object.
|
||||
*/
|
||||
unsigned numRegions() const
|
||||
{ return gasReferenceDensity_.size(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns the specific enthalpy [J/kg] of gas given a set of parameters.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation internalEnergy(unsigned,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
const Evaluation&) const
|
||||
{
|
||||
return H2::gasInternalEnergy(temperature, pressure);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation viscosity(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
const Evaluation& /*Rv*/) const
|
||||
{ return saturatedViscosity(regionIdx, temperature, pressure); }
|
||||
|
||||
/*!
|
||||
* \brief Returns the dynamic viscosity [Pa s] of oil saturated gas at given pressure.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedViscosity(unsigned /*regionIdx*/,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure) const
|
||||
{
|
||||
return H2::gasViscosity(temperature, pressure);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the formation volume factor [-] of the fluid phase.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
const Evaluation& /*Rv*/) const
|
||||
{ return saturatedInverseFormationVolumeFactor(regionIdx, temperature, pressure); }
|
||||
|
||||
/*!
|
||||
* \brief Returns the formation volume factor [-] of oil saturated gas at given pressure.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
|
||||
const Evaluation& temperature,
|
||||
const Evaluation& pressure) const
|
||||
{
|
||||
return H2::gasDensity(temperature, pressure, extrapolate)/gasReferenceDensity_[regionIdx];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the saturation pressure of the gas phase [Pa] depending on its mass fraction of the oil component
|
||||
*
|
||||
* \param Rv The surface volume of oil component dissolved in what will yield one cubic meter of gas at the surface [-]
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturationPressure(unsigned /*regionIdx*/,
|
||||
const Evaluation& /*temperature*/,
|
||||
const Evaluation& /*Rv*/) const
|
||||
{ return 0.0; /* this is dry gas! */ }
|
||||
|
||||
/*!
|
||||
* \brief Returns the oil vaporization factor \f$R_v\f$ [m^3/m^3] of the oil phase.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedOilVaporizationFactor(unsigned /*regionIdx*/,
|
||||
const Evaluation& /*temperature*/,
|
||||
const Evaluation& /*pressure*/,
|
||||
const Evaluation& /*oilSaturation*/,
|
||||
const Evaluation& /*maxOilSaturation*/) const
|
||||
{ return 0.0; /* this is dry gas! */ }
|
||||
|
||||
/*!
|
||||
* \brief Returns the oil vaporization factor \f$R_v\f$ [m^3/m^3] of the oil phase.
|
||||
*/
|
||||
template <class Evaluation>
|
||||
Evaluation saturatedOilVaporizationFactor(unsigned /*regionIdx*/,
|
||||
const Evaluation& /*temperature*/,
|
||||
const Evaluation& /*pressure*/) const
|
||||
{ return 0.0; /* this is dry gas! */ }
|
||||
|
||||
template <class Evaluation>
|
||||
Evaluation diffusionCoefficient(const Evaluation& temperature,
|
||||
const Evaluation& pressure,
|
||||
unsigned /*compIdx*/) const
|
||||
{
|
||||
return BinaryCoeffBrineH2::gasDiffCoeff(temperature, pressure);
|
||||
}
|
||||
|
||||
const Scalar gasReferenceDensity(unsigned regionIdx) const
|
||||
{ return gasReferenceDensity_[regionIdx]; }
|
||||
|
||||
bool operator==(const H2GasPvt<Scalar>& data) const
|
||||
{
|
||||
return gasReferenceDensity_ == data.gasReferenceDensity_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Scalar> gasReferenceDensity_;
|
||||
}; // end class H2GasPvt
|
||||
|
||||
} // end namspace Opm
|
||||
|
||||
#endif
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "LiveOilPvt.hpp"
|
||||
#include "OilPvtThermal.hpp"
|
||||
#include "BrineCo2Pvt.hpp"
|
||||
#include "BrineH2Pvt.hpp"
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -66,7 +67,12 @@ class Schedule;
|
||||
auto& pvtImpl = getRealPvt<OilPvtApproach::BrineCo2>(); \
|
||||
codeToCall; \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
case OilPvtApproach::BrineH2Pvt: { \
|
||||
auto& pvtImpl = getRealPvt<OilPvtApproach::BrineH2Pvt>(); \
|
||||
codeToCall; \
|
||||
break; \
|
||||
} \
|
||||
case OilPvtApproach::NoOil: \
|
||||
throw std::logic_error("Not implemented: Oil PVT of this deck!"); \
|
||||
}
|
||||
@@ -78,6 +84,7 @@ enum class OilPvtApproach {
|
||||
ConstantCompressibilityOil,
|
||||
ThermalOil,
|
||||
BrineCo2
|
||||
BrineH2Pvt
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -135,7 +142,10 @@ public:
|
||||
delete &getRealPvt<OilPvtApproach::BrineCo2>();
|
||||
break;
|
||||
}
|
||||
|
||||
case OilPvtApproach::BrineH2Pvt: {
|
||||
delete &getRealPvt<OilPvtApproach::BrineH2Pvt>();
|
||||
break;
|
||||
}
|
||||
case OilPvtApproach::NoOil:
|
||||
break;
|
||||
}
|
||||
@@ -281,6 +291,10 @@ public:
|
||||
realOilPvt_ = new BrineCo2Pvt<Scalar>;
|
||||
break;
|
||||
|
||||
case OilPvtApproach::BrineH2Pvt:
|
||||
realOilPvt_ = new BrineH2Pvt<Scalar>;
|
||||
break;
|
||||
|
||||
case OilPvtApproach::NoOil:
|
||||
throw std::logic_error("Not implemented: Oil PVT of this deck!");
|
||||
}
|
||||
@@ -388,6 +402,9 @@ public:
|
||||
case OilPvtApproach::BrineCo2:
|
||||
realOilPvt_ = new BrineCo2Pvt<Scalar>(*static_cast<const BrineCo2Pvt<Scalar>*>(data.realOilPvt_));
|
||||
break;
|
||||
case OilPvtApproach::BrineH2Pvt:
|
||||
realOilPvt_ = new BrineH2Pvt<Scalar>(*static_cast<const BrineH2Pvt<Scalar>*>(data.realOilPvt_));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user