Merge pull request #473 from blattms/hardcode-extrapolation-co2

Use extrapolation for unreasonable/untabulated values for CO2 sequestration cases.
This commit is contained in:
Tor Harald Sandve
2021-09-29 08:42:04 +02:00
committed by GitHub
8 changed files with 82 additions and 31 deletions

View File

@@ -31,6 +31,11 @@
#include <opm/material/common/Exceptions.hpp>
#include <opm/material/common/MathToolbox.hpp>
#if HAVE_OPM_COMMON
#include <opm/common/OpmLog/OpmLog.hpp>
#else
#include <iostream>
#endif
#include <vector>
@@ -185,22 +190,36 @@ public:
/*!
* \brief Evaluate the function at a given (x,y) position.
*
* If this method is called for a value outside of the tabulated
* range, a \c Opm::NumericalIssue exception is thrown.
* \param x x-position
* \param y y-position
* \param extrapolate Whether to extrapolate for untabulated values. If false then
* an exception might be thrown.
*/
template <class Evaluation>
Evaluation eval(const Evaluation& x, const Evaluation& y) const
Evaluation eval(const Evaluation& x, const Evaluation& y, bool extrapolate) const
{
#ifndef NDEBUG
if (!applies(x,y))
{
throw NumericalIssue("Attempt to get tabulated value for ("
+std::to_string(double(scalarValue(x)))+", "+std::to_string(double(scalarValue(y)))
+") on a table of extend "
+std::to_string(xMin())+" to "+std::to_string(xMax())+" times "
+std::to_string(yMin())+" to "+std::to_string(yMax()));
};
std::string msg = "Attempt to get tabulated value for ("
+std::to_string(double(scalarValue(x)))+", "+std::to_string(double(scalarValue(y)))
+") on a table of extent "
+std::to_string(xMin())+" to "+std::to_string(xMax())+" times "
+std::to_string(yMin())+" to "+std::to_string(yMax());
if (!extrapolate)
{
throw NumericalIssue(msg);
}
else
{
#if HAVE_OPM_COMMON
OpmLog::warning("PVT Table evaluation:" + msg + ". Will use extrapolation");
#else
std::cerr << "warning: "<< msg<<std::endl;
#endif
}
};
Evaluation alpha = xToI(x);
Evaluation beta = yToJ(y);
@@ -281,6 +300,7 @@ private:
Scalar yMin_;
Scalar yMax_;
};
} // namespace Opm
#endif

View File

@@ -252,7 +252,7 @@ public:
Evaluation tempC = temperature - 273.15;
Evaluation pMPa = pressure/1.0E6;
const Evaluation rhow = H2O::liquidDensity(temperature, pressure);
const Evaluation rhow = H2O::liquidDensity(temperature, pressure, true);
return
rhow +
1000*salinity*(

View File

@@ -52,7 +52,6 @@ template <class Scalar, class CO2Tables>
class CO2 : public Component<Scalar, CO2<Scalar, CO2Tables> >
{
static const Scalar R;
static bool warningPrinted;
public:
/*!
@@ -165,7 +164,8 @@ public:
static Evaluation gasEnthalpy(const Evaluation& temperature,
const Evaluation& pressure)
{
return CO2Tables::tabulatedEnthalpy.eval(temperature, pressure);
return CO2Tables::tabulatedEnthalpy.eval(temperature, pressure,
/* extrapolate = */ true);
}
/*!
@@ -187,7 +187,8 @@ public:
template <class Evaluation>
static Evaluation gasDensity(const Evaluation& temperature, const Evaluation& pressure)
{
return CO2Tables::tabulatedDensity.eval(temperature, pressure);
return CO2Tables::tabulatedDensity.eval(temperature, pressure,
/* extrapolate = */ true);
}
/*!
@@ -261,8 +262,6 @@ public:
}
};
template <class Scalar, class CO2Tables>
bool CO2<Scalar, CO2Tables>::warningPrinted = false;
template <class Scalar, class CO2Tables>
const Scalar CO2<Scalar, CO2Tables>::R = Constants<Scalar>::R;

View File

@@ -689,7 +689,7 @@ public:
* \param pressure Phase pressure in \f$\mathrm{[Pa]}\f$
*/
template <class Evaluation>
static Evaluation liquidDensity(const Evaluation& temperature, const Evaluation& pressure)
static Evaluation liquidDensity(const Evaluation& temperature, const Evaluation& pressure, bool = false)
{
if (!Region1::isValid(temperature, pressure))
{

View File

@@ -37,6 +37,12 @@
#include <opm/material/common/Unused.hpp>
#if HAVE_OPM_COMMON
#include <opm/common/OpmLog/OpmLog.hpp>
#else
#include <iostream>
#endif
#include <cmath>
namespace Opm {
@@ -296,11 +302,14 @@ public:
*
* \param temperature temperature of component in \f$\mathrm{[K]}\f$
* \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
* \param extrapolate Whether to extrapolate for untabulated/unreasonable
* values. If false an exception might be thrown.
*/
template <class Evaluation>
static Evaluation liquidDensity(const Evaluation& temperature, const Evaluation& pressure)
static Evaluation liquidDensity(const Evaluation& temperature, const Evaluation& pressure,
bool extrapolate)
{
return liquidDensity_(temperature, pressure);
return liquidDensity_(temperature, pressure, extrapolate);
}
/*!
@@ -334,18 +343,30 @@ public:
*
* \param temperature temperature of component in \f$\mathrm{[K]}\f$
* \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
* \param extrapolate Whether to extrapolate for untabulated/unreasonable
* values. If false an exception might be thrown.
*/
template <class Evaluation>
static Evaluation liquidViscosity(const Evaluation& temperature, const Evaluation& pressure)
static Evaluation liquidViscosity(const Evaluation& temperature, const Evaluation& pressure,
bool extrapolate)
{
if (temperature > 570) {
std::ostringstream oss;
oss << "Viscosity of water based on Hu et al is too different from IAPWS for T above 570K and "
<< "(T = " << temperature << ")";
throw NumericalIssue(oss.str());
if(extrapolate)
{
#if HAVE_OPM_COMMON
OpmLog::warning(oss.str());
#else
std::cerr << "warning: "<< oss.str() <<std::endl;
#endif
}
else
throw NumericalIssue(oss.str());
}
const Evaluation& rho = liquidDensity(temperature, pressure);
const Evaluation& rho = liquidDensity(temperature, pressure, extrapolate);
return Common::viscosity(temperature, rho);
}
@@ -356,9 +377,11 @@ private:
*
* \param temperature temperature of component in \f$\mathrm{[K]}\f$
* \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
* \param extrapolate Whether to extrapolate for untabulated/unreasonable
* values. If false an exception might be thrown.
*/
template <class Evaluation>
static Evaluation liquidDensity_(const Evaluation& T, const Evaluation& pressure) {
static Evaluation liquidDensity_(const Evaluation& T, const Evaluation& pressure, bool extrapolate) {
// Hu, Duan, Zhu and Chou: PVTx properties of the CO2-H2O and CO2-H2O-NaCl
// systems below 647 K: Assessment of experimental data and
// thermodynamics models, Chemical Geology, 2007.
@@ -366,7 +389,16 @@ private:
std::ostringstream oss;
oss << "Density of water is only implemented for temperatures below 647K and "
<< "pressures below 100MPa. (T = " << T << ", p=" << pressure;
throw NumericalIssue(oss.str());
if(extrapolate)
{
#if HAVE_OPM_COMMON
OpmLog::warning(oss.str());
#else
std::cerr << "warning: "<< oss.str() <<std::endl;
#endif
}
else
throw NumericalIssue(oss.str());
}
Evaluation p = pressure / 1e6; // to MPa

View File

@@ -286,7 +286,7 @@ public:
const Evaluation log_D_H20 = -4.1764 + 712.52 / temperature - 2.5907e5 / (temperature*temperature);
//Diffusion coefficient of CO2 in the brine phase modified following (Ratcliff and Holdcroft,1963 and Al-Rawajfeh, 2004)
const Evaluation& mu_H20 = H2O::liquidViscosity(temperature, pressure); // Water viscosity
const Evaluation& mu_H20 = H2O::liquidViscosity(temperature, pressure, true); // Water viscosity
const Evaluation& mu_Brine = Brine::liquidViscosity(temperature, pressure); // Brine viscosity
const Evaluation log_D_Brine = log_D_H20 - 0.87*log10(mu_Brine / mu_H20);
@@ -337,7 +337,7 @@ private:
}
const LhsEval& rho_brine = Brine::liquidDensity(T, pl);
const LhsEval& rho_pure = H2O::liquidDensity(T, pl);
const LhsEval& rho_pure = H2O::liquidDensity(T, pl, true);
const LhsEval& rho_lCO2 = liquidDensityWaterCO2_(T, pl, xlCO2);
const LhsEval& contribCO2 = rho_lCO2 - rho_pure;
@@ -353,7 +353,7 @@ private:
Scalar M_H2O = H2O::molarMass();
const LhsEval& tempC = temperature - 273.15; /* tempC : temperature in <20>C */
const LhsEval& rho_pure = H2O::liquidDensity(temperature, pl);
const LhsEval& rho_pure = H2O::liquidDensity(temperature, pl, true);
// calculate the mole fraction of CO2 in the liquid. note that xlH2O is available
// as a function parameter, but in the case of a pure gas phase the value of M_T
// for the virtual liquid phase can become very large

View File

@@ -181,8 +181,8 @@ struct Test
for (unsigned j = 0; j < numY; ++j) {
Scalar y = yMin + Scalar(j)/numY*(yMax - yMin);
if (std::abs(table->eval(x, y) - f(x, y)) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": table->eval("<<x<<","<<y<<") != f("<<x<<","<<y<<"): " << table->eval(x,y) << " != " << f(x,y) << "\n";
if (std::abs(table->eval(x, y, false) - f(x, y)) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": table->eval("<<x<<","<<y<<") != f("<<x<<","<<y<<"): " << table->eval(x,y, false) << " != " << f(x,y) << "\n";
return false;
}
}

View File

@@ -80,13 +80,13 @@ void testSimpleH2O()
T += 5;
for (int iP = 0; iP < numP; ++iP) {
p *= 1.1;
if (!EvalToolbox::isSame(H2O::liquidDensity(T,p), SimpleHuDuanH2O::liquidDensity(T,p), /*tolerance=*/1e-3*H2O::liquidDensity(T,p).value()))
if (!EvalToolbox::isSame(H2O::liquidDensity(T,p), SimpleHuDuanH2O::liquidDensity(T,p,false), /*tolerance=*/1e-3*H2O::liquidDensity(T,p).value()))
throw std::logic_error("oops: the water density based on Hu-Duan has more then 1e-3 deviation from IAPWS'97");
if (T >= 570) // for temperature larger then 570 the viscosity based on HuDuan is too far from IAPWS.
continue;
if (!EvalToolbox::isSame(H2O::liquidViscosity(T,p), SimpleHuDuanH2O::liquidViscosity(T,p), /*tolerance=*/5.e-2*H2O::liquidViscosity(T,p).value())){
if (!EvalToolbox::isSame(H2O::liquidViscosity(T,p), SimpleHuDuanH2O::liquidViscosity(T,p,false), /*tolerance=*/5.e-2*H2O::liquidViscosity(T,p).value())){
throw std::logic_error("oops: the water viscosity based on Hu-Duan has more then 5e-2 deviation from IAPWS'97");
}
}