replace the blackoil PVT classes by the ones of opm-material
the opm-material classes are the ones which are now used by opm-autodiff and this patch makes it much easier to keep the opm-core and opm-autodiff results consistent. Also, the opm-material classes seem to be a bit faster than the opm-core ones (see https://github.com/OPM/opm-autodiff/pull/576) I ran the usual array of tests with `flow`: SPE1, SPE3, SPE9 and Norne all produce the same results at the identical runtime (modulo noise) and also "Model 2" seems to work.
This commit is contained in:
@@ -5,11 +5,22 @@
|
||||
|
||||
-- Copyright (C) 2015 Statoil
|
||||
|
||||
RUNSPEC
|
||||
|
||||
TABDIMS
|
||||
--ntsfun ntpvt nssfun nppvt ntfip nrpvt ntendp
|
||||
2 2 33 60 16 60 /
|
||||
|
||||
DIMENS
|
||||
1 1 1 /
|
||||
|
||||
GRID
|
||||
|
||||
PROPS
|
||||
|
||||
DENSITY
|
||||
859.5 1033.0 0.854 / Justert 22/7
|
||||
860.04 1033.0 0.853 / Justert 22/7
|
||||
|
||||
PVTG
|
||||
|
||||
|
||||
@@ -1,388 +0,0 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <opm/core/props/pvt/PvtConstCompr.hpp>
|
||||
#include <opm/core/props/pvt/PvtDead.hpp>
|
||||
#include <opm/core/props/pvt/PvtDeadSpline.hpp>
|
||||
#include <opm/core/props/pvt/PvtLiveOil.hpp>
|
||||
#include <opm/core/props/pvt/PvtLiveGas.hpp>
|
||||
#include <opm/core/props/phaseUsageFromDeck.hpp>
|
||||
#include <opm/core/props/BlackoilPhases.hpp>
|
||||
#include <opm/core/props/pvt/BlackoilPvtProperties.hpp>
|
||||
#include <opm/core/utility/Units.hpp>
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseMode.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
|
||||
#if HAVE_DYNAMIC_BOOST_TEST
|
||||
#define BOOST_TEST_DYN_LINK
|
||||
#endif
|
||||
#define NVERBOSE // to suppress our messages when throwing
|
||||
#define BOOST_TEST_MODULE BlackoilFluidTest
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace Opm;
|
||||
using namespace std;
|
||||
|
||||
|
||||
std::vector<std::shared_ptr<PvtInterface> > getProps(Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclipseState, PhaseUsage phase_usage_){
|
||||
enum PhaseIndex { Aqua = 0, Liquid = 1, Vapour = 2 };
|
||||
int samples = 0;
|
||||
std::shared_ptr<const TableManager> tables = eclipseState->getTableManager();
|
||||
std::vector<std::shared_ptr<PvtInterface> > props_;
|
||||
// Set the properties.
|
||||
props_.resize(phase_usage_.num_phases);
|
||||
|
||||
// Water PVT
|
||||
if (phase_usage_.phase_used[Aqua]) {
|
||||
if (deck->hasKeyword("PVTW")) {
|
||||
std::shared_ptr<PvtConstCompr> pvtw(new PvtConstCompr);
|
||||
pvtw->initFromWater(deck->getKeyword("PVTW"));
|
||||
|
||||
props_[phase_usage_.phase_pos[Aqua]] = pvtw;
|
||||
} else {
|
||||
// Eclipse 100 default.
|
||||
props_[phase_usage_.phase_pos[Aqua]].reset(new PvtConstCompr(0.5*Opm::prefix::centi*Opm::unit::Poise));
|
||||
}
|
||||
}
|
||||
|
||||
// Oil PVT
|
||||
if (phase_usage_.phase_used[Liquid]) {
|
||||
const auto& pvdoTables = tables->getPvdoTables();
|
||||
const auto& pvtoTables = tables->getPvtoTables();
|
||||
if (!pvdoTables.empty()) {
|
||||
if (samples > 0) {
|
||||
std::shared_ptr<PvtDeadSpline> splinePvt(new PvtDeadSpline);
|
||||
splinePvt->initFromOil(pvdoTables, samples);
|
||||
props_[phase_usage_.phase_pos[Liquid]] = splinePvt;
|
||||
} else {
|
||||
std::shared_ptr<PvtDead> deadPvt(new PvtDead);
|
||||
deadPvt->initFromOil(pvdoTables);
|
||||
props_[phase_usage_.phase_pos[Liquid]] = deadPvt;
|
||||
}
|
||||
} else if (!pvtoTables.empty()) {
|
||||
props_[phase_usage_.phase_pos[Liquid]].reset(new PvtLiveOil(pvtoTables));
|
||||
} else if (deck->hasKeyword("PVCDO")) {
|
||||
std::shared_ptr<PvtConstCompr> pvcdo(new PvtConstCompr);
|
||||
pvcdo->initFromOil(deck->getKeyword("PVCDO"));
|
||||
|
||||
props_[phase_usage_.phase_pos[Liquid]] = pvcdo;
|
||||
} else {
|
||||
OPM_THROW(std::runtime_error, "Input is missing PVDO, PVCDO or PVTO\n");
|
||||
}
|
||||
}
|
||||
// Gas PVT
|
||||
if (phase_usage_.phase_used[Vapour]) {
|
||||
const auto& pvdgTables = tables->getPvdgTables();
|
||||
const auto& pvtgTables = tables->getPvtgTables();
|
||||
if (!pvdgTables.empty()) {
|
||||
if (samples > 0) {
|
||||
std::shared_ptr<PvtDeadSpline> splinePvt(new PvtDeadSpline);
|
||||
splinePvt->initFromGas(pvdgTables, samples);
|
||||
props_[phase_usage_.phase_pos[Vapour]] = splinePvt;
|
||||
} else {
|
||||
std::shared_ptr<PvtDead> deadPvt(new PvtDead);
|
||||
deadPvt->initFromGas(pvdgTables);
|
||||
props_[phase_usage_.phase_pos[Vapour]] = deadPvt;
|
||||
}
|
||||
} else if (!pvtgTables.empty()) {
|
||||
props_[phase_usage_.phase_pos[Vapour]].reset(new PvtLiveGas(pvtgTables));
|
||||
} else {
|
||||
OPM_THROW(std::runtime_error, "Input is missing PVDG or PVTG\n");
|
||||
}
|
||||
}
|
||||
|
||||
return props_;
|
||||
}
|
||||
|
||||
void testmu(const double reltol, int n, int np, const std::vector<int> &pvtTableIdx, std::vector<double> p, std::vector<double> T, std::vector<double> r,std::vector<double> z,
|
||||
std::vector<std::shared_ptr<PvtInterface> > props_, std::vector<Opm::PhasePresence> condition)
|
||||
{
|
||||
std::vector<double> mu(n);
|
||||
std::vector<double> dmudp(n);
|
||||
std::vector<double> dmudr(n);
|
||||
std::vector<double> mu_new(n);
|
||||
double dmudp_diff;
|
||||
double dmudr_diff;
|
||||
double dmudp_diff_u;
|
||||
double dmudr_diff_u;
|
||||
|
||||
// test mu
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
props_[phase]->mu(n, &pvtTableIdx[0], &p[0], &T[0], &r[0], &condition[0], &mu_new[0], &dmudp[0], &dmudr[0]);
|
||||
props_[phase]->mu(n, &pvtTableIdx[0], &p[0], &T[0], &z[0], &mu[0]);
|
||||
dmudp_diff = (mu_new[1]-mu_new[0])/(p[1]-p[0]);
|
||||
dmudr_diff = (mu_new[2]-mu_new[0])/(r[2]-r[0]);
|
||||
dmudp_diff_u = (mu_new[4]-mu_new[3])/(p[4]-p[3]);
|
||||
dmudr_diff_u = (mu_new[5]-mu_new[3])/(r[5]-r[3]);
|
||||
|
||||
for (int i = 0; i < n; ++i){
|
||||
BOOST_CHECK_CLOSE(mu_new[i],mu[i],reltol);
|
||||
}
|
||||
|
||||
// saturated case
|
||||
BOOST_CHECK_CLOSE(dmudp_diff,dmudp[0],reltol);
|
||||
BOOST_CHECK_CLOSE(dmudr_diff,dmudr[0],reltol);
|
||||
|
||||
// unsaturated case
|
||||
BOOST_CHECK_CLOSE(dmudp_diff_u,dmudp[3],reltol);
|
||||
BOOST_CHECK_CLOSE(dmudr_diff_u,dmudr[3],reltol);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void testb(const double reltol, int n, int np, const std::vector<int> &pvtTableIdx, std::vector<double> p, std::vector<double> T, std::vector<double> r,std::vector<double> z,
|
||||
std::vector<std::shared_ptr<PvtInterface> > props_, std::vector<Opm::PhasePresence> condition)
|
||||
{
|
||||
// test b
|
||||
std::vector<double> b(n);
|
||||
std::vector<double> B(n);
|
||||
std::vector<double> invB(n);
|
||||
std::vector<double> dinvBdp(n);
|
||||
std::vector<double> dBdp(n);
|
||||
std::vector<double> dbdr(n);
|
||||
std::vector<double> dbdp(n);
|
||||
double dbdp_diff;
|
||||
double dbdr_diff;
|
||||
double dbdp_diff_u;
|
||||
double dbdr_diff_u;
|
||||
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
props_[phase]->b(n, &pvtTableIdx[0], &p[0], &T[0], &r[0], &condition[0], &b[0], &dbdp[0], &dbdr[0]);
|
||||
props_[phase]->dBdp(n, &pvtTableIdx[0], &p[0], &T[0], &z[0], &B[0], &dBdp[0]);
|
||||
dbdp_diff = (b[1]-b[0])/(p[1]-p[0]);
|
||||
dbdr_diff = (b[2]-b[0])/(r[2]-r[0]);
|
||||
dbdp_diff_u = (b[4]-b[3])/(p[4]-p[3]);
|
||||
dbdr_diff_u = (b[5]-b[3])/(r[5]-r[3]);
|
||||
for (int i = 0; i < n; ++i){
|
||||
invB[i] = 1/B[i];
|
||||
dinvBdp[i] = -1/pow(B[i],2) * dBdp[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; ++i){
|
||||
BOOST_CHECK_CLOSE(invB[i],b[i] , reltol);
|
||||
BOOST_CHECK_CLOSE(dinvBdp[i],dbdp[i] , reltol);
|
||||
|
||||
}
|
||||
// saturated case
|
||||
BOOST_CHECK_CLOSE(dbdp_diff,dbdp[0], reltol);
|
||||
BOOST_CHECK_CLOSE(dbdr_diff,dbdr[0], reltol);
|
||||
|
||||
// unsaturated case
|
||||
BOOST_CHECK_CLOSE(dbdp_diff_u,dbdp[3], reltol);
|
||||
BOOST_CHECK_CLOSE(dbdr_diff_u,dbdr[3], reltol);
|
||||
}
|
||||
}
|
||||
|
||||
void testrsSat(double reltol, int n, int np, const std::vector<int> &pvtTableIdx, std::vector<double> p, std::vector<std::shared_ptr<PvtInterface> > props_){
|
||||
// test bublepoint pressure
|
||||
std::vector<double> rs(n);
|
||||
std::vector<double> drsdp(n);
|
||||
double drsdp_diff;
|
||||
double drsdp_diff_u;
|
||||
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
props_[phase] ->rsSat(n, &pvtTableIdx[0], &p[0], &rs[0], &drsdp[0]);
|
||||
|
||||
drsdp_diff = (rs[1]-rs[0])/(p[1]-p[0]);
|
||||
drsdp_diff_u = (rs[4]-rs[3])/(p[4]-p[3]);
|
||||
|
||||
// saturated case
|
||||
BOOST_CHECK_CLOSE(drsdp_diff,drsdp[0], reltol);
|
||||
|
||||
// unsaturad case
|
||||
BOOST_CHECK_CLOSE(drsdp_diff_u,drsdp[3], reltol);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void testrvSat(double reltol, int n, int np, const std::vector<int> &pvtTableIdx, std::vector<double> p, std::vector<std::shared_ptr<PvtInterface> > props_){
|
||||
// test rv saturated
|
||||
std::vector<double> rv(n);
|
||||
std::vector<double> drvdp(n);
|
||||
double drvdp_diff;
|
||||
double drvdp_diff_u;
|
||||
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
props_[phase] ->rvSat(n, &pvtTableIdx[0], &p[0], &rv[0], &drvdp[0]);
|
||||
|
||||
drvdp_diff = (rv[1]-rv[0])/(p[1]-p[0]);
|
||||
drvdp_diff_u = (rv[4]-rv[3])/(p[4]-p[3]);
|
||||
|
||||
// saturated case
|
||||
BOOST_CHECK_CLOSE(drvdp_diff,drvdp[0], reltol);
|
||||
|
||||
// unsaturad case
|
||||
BOOST_CHECK_CLOSE(drvdp_diff_u,drvdp[3], reltol);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_liveoil)
|
||||
{
|
||||
|
||||
|
||||
// read eclipse deck
|
||||
const std::string filename = "liveoil.DATA";
|
||||
cout << "Reading deck: " << filename << endl;
|
||||
Opm::ParserPtr parser(new Opm::Parser());
|
||||
Opm::ParseMode parseMode;
|
||||
Opm::DeckConstPtr deck(parser->parseFile(filename , parseMode));
|
||||
Opm::EclipseStateConstPtr eclipseState(new EclipseState(deck, parseMode));
|
||||
|
||||
// setup pvt interface
|
||||
PhaseUsage phase_usage_ = phaseUsageFromDeck(deck);
|
||||
std::vector<std::shared_ptr<PvtInterface> > props_ = getProps(deck, eclipseState, phase_usage_);
|
||||
|
||||
|
||||
// setup a test case. We will check 6 [p,r] pairs and compare them to both the [p,z] interface and a finite difference
|
||||
// approximation of the derivatives.
|
||||
const int n = 6;
|
||||
const int np = phase_usage_.num_phases;
|
||||
std::vector<int> pvtRegionIdx(n, 0);
|
||||
|
||||
// the relative tolerance in percentage for acceptable difference in values
|
||||
const double reltolper = 1e-9;
|
||||
// the relative tolerance in percentage for acceptable difference in values for viscosity
|
||||
const double reltolpermu = 1e-1;
|
||||
|
||||
std::vector<double> p(n);
|
||||
std::vector<double> T(n, 273.15 + 20);
|
||||
std::vector<double> r(n);
|
||||
std::vector<PhasePresence> condition(n);
|
||||
std::vector<double> z(n * np);
|
||||
|
||||
|
||||
// Used for forward difference calculations
|
||||
const double h_p = 1e4;
|
||||
const double h_r = 1;
|
||||
|
||||
// saturated
|
||||
p[0] = 1e7;
|
||||
p[1] = p[0] + h_p;
|
||||
p[2] = p[0];
|
||||
|
||||
r[0] = 200;
|
||||
r[1] = 200;
|
||||
r[2] = 200 + h_r;
|
||||
|
||||
condition[0].setFreeGas();
|
||||
condition[1].setFreeGas();
|
||||
condition[2].setFreeGas();
|
||||
|
||||
|
||||
// undersaturated
|
||||
p[3] = p[0];
|
||||
p[4] = p[1];
|
||||
p[5] = p[2];
|
||||
|
||||
r[3] = 50;
|
||||
r[4] = 50;
|
||||
r[5] = 50 +h_r;
|
||||
|
||||
// Corresponing z factors, used to compare with the [p,z] interface
|
||||
for (int i = 0; i < n; ++i) {
|
||||
z[0+i*np] = 0; z[1+i*np] = 1;
|
||||
z[2+i*np] = r[i];
|
||||
|
||||
}
|
||||
|
||||
testmu(reltolpermu, n, np, pvtRegionIdx, p, T, r,z, props_, condition);
|
||||
|
||||
testb(reltolper,n,np,pvtRegionIdx,p,T,r,z,props_,condition);
|
||||
|
||||
testrsSat(reltolper,n,np,pvtRegionIdx,p,props_);
|
||||
|
||||
testrvSat(reltolper,n,np,pvtRegionIdx,p,props_);
|
||||
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_wetgas)
|
||||
{
|
||||
|
||||
|
||||
// read eclipse deck
|
||||
|
||||
const std::string filename = "wetgas.DATA";
|
||||
cout << "Reading deck: " << filename << endl;
|
||||
Opm::ParserPtr parser(new Opm::Parser());
|
||||
Opm::ParseMode parseMode;
|
||||
Opm::DeckConstPtr deck(parser->parseFile(filename , parseMode));
|
||||
Opm::EclipseStateConstPtr eclipseState(new EclipseState(deck, parseMode));
|
||||
|
||||
// setup pvt interface
|
||||
PhaseUsage phase_usage_ = phaseUsageFromDeck(deck);
|
||||
std::vector<std::shared_ptr<PvtInterface> > props_ = getProps(deck,eclipseState,phase_usage_);
|
||||
|
||||
|
||||
// setup a test case. We will check 6 [p,r] pairs and compare them to both the [p,z] interface and a finite difference
|
||||
// approximation of the derivatives.
|
||||
const int n = 6;
|
||||
const int np = phase_usage_.num_phases;
|
||||
std::vector<int> pvtRegionIdx(n, 0);
|
||||
|
||||
// the relative tolerance in percentage for acceptable difference in values
|
||||
const double reltolper = 1e-9;
|
||||
// the relative tolerance in percentage for acceptable difference in values for viscosity
|
||||
const double reltolpermu = 1e-1;
|
||||
|
||||
std::vector<double> p(n);
|
||||
std::vector<double> T(n, 273.15+20);
|
||||
std::vector<double> r(n);
|
||||
std::vector<PhasePresence> condition(n);
|
||||
std::vector<double> z(n * np);
|
||||
|
||||
|
||||
// Used for forward difference calculations
|
||||
const double h_p = 1e4;
|
||||
const double h_r = 1e-7;
|
||||
|
||||
// saturated
|
||||
p[0] = 1e7;
|
||||
p[1] = p[0] + h_p;
|
||||
p[2] = p[0];
|
||||
|
||||
r[0] = 5e-5;
|
||||
r[1] = 5e-5;
|
||||
r[2] = 5e-5 + h_r;
|
||||
|
||||
condition[0].setFreeOil();
|
||||
condition[1].setFreeOil();
|
||||
condition[2].setFreeOil();
|
||||
|
||||
|
||||
// undersaturated
|
||||
p[3] = p[0];
|
||||
p[4] = p[1];
|
||||
p[5] = p[2];
|
||||
|
||||
r[3] = 1e-5;
|
||||
r[4] = 1e-5;
|
||||
r[5] = 1e-5 +h_r;
|
||||
|
||||
// Corresponing z factors, used to compare with the [p,z] interface
|
||||
for (int i = 0; i < n; ++i) {
|
||||
z[0+i*np] = 0; z[1+i*np] = r[i];
|
||||
z[2+i*np] = 1;
|
||||
|
||||
}
|
||||
|
||||
testmu(reltolpermu, n, np, pvtRegionIdx, p,T, r,z, props_, condition);
|
||||
|
||||
testb(reltolper,n,np,pvtRegionIdx,p,T,r,z,props_,condition);
|
||||
|
||||
testrsSat(reltolper,n,np,pvtRegionIdx,p,props_);
|
||||
|
||||
testrvSat(reltolper,n,np,pvtRegionIdx,p,props_);
|
||||
|
||||
}
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
|
||||
#include <opm/core/props/pvt/PvtLiveOil.hpp>
|
||||
#include <opm/material/fluidsystems/blackoilpvt/LiveOilPvt.hpp>
|
||||
|
||||
|
||||
using namespace Opm;
|
||||
@@ -57,19 +57,9 @@ using namespace Opm;
|
||||
further semantic meaning.
|
||||
*/
|
||||
|
||||
|
||||
void check_vectors( const std::vector<double>& v1 , const std::vector<double>& v2) {
|
||||
double tol = 1e-5;
|
||||
for (decltype(v1.size()) i = 0; i < v1.size(); i++) {
|
||||
BOOST_CHECK_CLOSE( v1[i] , v2[i] , tol );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void verify_norne_oil_pvt_region2(const TableManager& tableManager) {
|
||||
auto pvtoTables = tableManager.getPvtoTables();
|
||||
PvtLiveOil oilPvt(pvtoTables);
|
||||
void verify_norne_oil_pvt_region1(Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclState) {
|
||||
Opm::LiveOilPvt<double> oilPvt;
|
||||
oilPvt.initFromDeck(deck, eclState);
|
||||
|
||||
std::vector<double> rs = {33, 33,
|
||||
43, 43,
|
||||
@@ -113,33 +103,37 @@ void verify_norne_oil_pvt_region2(const TableManager& tableManager) {
|
||||
{
|
||||
std::vector<int> tableIndex(P.size() , 0);
|
||||
|
||||
std::vector<double> mu(P.size());
|
||||
std::vector<double> dmudp(P.size());
|
||||
std::vector<double> dmudr(P.size());
|
||||
|
||||
std::vector<double> b(P.size());
|
||||
std::vector<double> dbdp(P.size());
|
||||
std::vector<double> dbdr(P.size());
|
||||
|
||||
|
||||
// convert the pressures to SI units (bar to Pascal)
|
||||
for (auto& value : P)
|
||||
value *= Metric::Pressure;
|
||||
|
||||
// convert the gas dissolution factors to SI units
|
||||
for (auto& value : rs)
|
||||
value *= Metric::GasDissolutionFactor;
|
||||
|
||||
oilPvt.mu( P.size() , tableIndex.data() , P.data() , NULL , rs.data() , mu.data() , dmudp.data() , dmudr.data());
|
||||
oilPvt.b( P.size() , tableIndex.data() , P.data() , NULL , rs.data() , b.data() , dbdp.data() , dbdr.data());
|
||||
for (unsigned i = 0; i < P.size(); ++i) {
|
||||
double mu;
|
||||
double b;
|
||||
double RsSat = oilPvt.saturatedGasDissolutionFactor(/*tableIndex=*/0, /*T=*/273.15, P[i]);
|
||||
if (rs[i] >= RsSat) {
|
||||
mu = oilPvt.saturatedViscosity(/*tableIndex=*/0, /*T=*/273.15, P[i]);
|
||||
b = oilPvt.saturatedInverseFormationVolumeFactor(/*tableIndex=*/0, /*T=*/273.15, P[i]);
|
||||
}
|
||||
else {
|
||||
mu = oilPvt.viscosity(/*tableIndex=*/0, /*T=*/273.15, P[i], rs[i]);
|
||||
b = oilPvt.inverseFormationVolumeFactor(/*tableIndex=*/0, /*T=*/273.15, P[i], rs[i]);
|
||||
}
|
||||
|
||||
check_vectors( mu , mu_expected );
|
||||
check_vectors( b , b_expected );
|
||||
BOOST_CHECK_CLOSE( mu , mu_expected[i], 1e-5 );
|
||||
BOOST_CHECK_CLOSE( b , b_expected[i], 1e-5 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void verify_norne_oil_pvt_region1(const TableManager& tableManager) {
|
||||
auto pvtoTables = tableManager.getPvtoTables();
|
||||
PvtLiveOil oilPvt(pvtoTables);
|
||||
void verify_norne_oil_pvt_region2(Opm::DeckConstPtr deck, Opm::EclipseStateConstPtr eclState) {
|
||||
Opm::LiveOilPvt<double> oilPvt;
|
||||
oilPvt.initFromDeck(deck, eclState);
|
||||
|
||||
std::vector<double> rs = {21 , 21,
|
||||
30 , 30,
|
||||
@@ -254,50 +248,41 @@ void verify_norne_oil_pvt_region1(const TableManager& tableManager) {
|
||||
0.57289091037, 0.56019050084,
|
||||
0.55474601877, 0.55809201119, 0.54526832277};
|
||||
|
||||
{
|
||||
std::vector<int> tableIndex(P.size() , 1);
|
||||
// convert the pressures to SI units (bar to Pascal)
|
||||
for (auto& value : P)
|
||||
value *= Metric::Pressure;
|
||||
|
||||
std::vector<double> mu(P.size());
|
||||
std::vector<double> dmudp(P.size());
|
||||
std::vector<double> dmudr(P.size());
|
||||
// convert the gas dissolution factors to SI units
|
||||
for (auto& value : rs)
|
||||
value *= Metric::GasDissolutionFactor;
|
||||
|
||||
std::vector<double> b(P.size());
|
||||
std::vector<double> dbdp(P.size());
|
||||
std::vector<double> dbdr(P.size());
|
||||
for (unsigned i = 0; i < P.size(); ++i) {
|
||||
double mu;
|
||||
double b;
|
||||
double RsSat = oilPvt.saturatedGasDissolutionFactor(/*tableIndex=*/1, /*T=*/273.15, P[i]);
|
||||
if (rs[i] >= RsSat) {
|
||||
mu = oilPvt.saturatedViscosity(/*tableIndex=*/1, /*T=*/273.15, P[i]);
|
||||
b = oilPvt.saturatedInverseFormationVolumeFactor(/*tableIndex=*/1, /*T=*/273.15, P[i]);
|
||||
}
|
||||
else {
|
||||
mu = oilPvt.viscosity(/*tableIndex=*/1, /*T=*/273.15, P[i], rs[i]);
|
||||
b = oilPvt.inverseFormationVolumeFactor(/*tableIndex=*/1, /*T=*/273.15, P[i], rs[i]);
|
||||
}
|
||||
|
||||
|
||||
for (auto& value : P)
|
||||
value *= Metric::Pressure;
|
||||
|
||||
for (auto& value : rs)
|
||||
value *= Metric::GasDissolutionFactor;
|
||||
|
||||
oilPvt.mu( P.size() , tableIndex.data() , P.data() , NULL , rs.data() , mu.data() , dmudp.data() , dmudr.data());
|
||||
oilPvt.b( P.size() , tableIndex.data() , P.data() , NULL , rs.data() , b.data() , dbdp.data() , dbdr.data());
|
||||
|
||||
check_vectors( mu , mu_expected );
|
||||
check_vectors( b , b_expected );
|
||||
BOOST_CHECK_CLOSE( mu , mu_expected[i], 1e-5 );
|
||||
BOOST_CHECK_CLOSE( b , b_expected[i], 1e-5 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TableManager loadTables( const std::string& deck_file) {
|
||||
BOOST_AUTO_TEST_CASE( Test_Norne_PVT) {
|
||||
Opm::ParseMode parseMode({{ ParseMode::PARSE_RANDOM_SLASH , InputError::IGNORE }});
|
||||
Opm::ParserPtr parser(new Parser());
|
||||
|
||||
std::shared_ptr<const Deck> deck;
|
||||
deck = parser->parseFile("norne_pvt.data", parseMode);
|
||||
|
||||
deck = parser->parseFile(deck_file, parseMode);
|
||||
return TableManager(*deck);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( Test_Norne_PVT) {
|
||||
TableManager tableManager = loadTables( "norne_pvt.data" );
|
||||
|
||||
verify_norne_oil_pvt_region1( tableManager );
|
||||
verify_norne_oil_pvt_region2( tableManager );
|
||||
Opm::EclipseStateConstPtr eclState(new EclipseState(deck, parseMode));
|
||||
|
||||
verify_norne_oil_pvt_region1( deck, eclState );
|
||||
verify_norne_oil_pvt_region2( deck, eclState );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user