Merge pull request #473 from blattms/hardcode-extrapolation-co2
Use extrapolation for unreasonable/untabulated values for CO2 sequestration cases.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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*(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user