Minor refactoring of VFPProperties to prepare for support for VFPINJ tables

This commit is contained in:
babrodtk 2015-07-06 15:34:22 +02:00
parent 15d3171ae1
commit 3260e978da
3 changed files with 111 additions and 68 deletions

View File

@ -33,40 +33,63 @@ namespace Opm {
VFPProperties::VFPProperties() {
}
void VFPProperties::init(const VFPProdTable* table) {
m_tables[table->getTableNum()] = table;
VFPProperties::VFPProperties(const VFPInjTable* inj_table, const VFPProdTable* prod_table) {
if (inj_table != NULL) {
m_inj_tables[inj_table->getTableNum()] = inj_table;
}
if (prod_table != NULL) {
m_prod_tables[prod_table->getTableNum()] = prod_table;
}
}
void VFPProperties::init(const std::vector<VFPProdTable>& tables) {
//Loop through all tables, and add to our map
for (unsigned int i=0; i<tables.size(); ++i) {
int table_number = tables[i].getTableNum();
if (m_tables.find(table_number) != m_tables.end()) {
OPM_THROW(std::invalid_argument, "Duplicate table numbers found for VFPPROD");
}
else {
m_tables[table_number] = &tables[i];
}
VFPProperties::VFPProperties(const std::map<int, VFPInjTable>& inj_tables,
const std::map<int, VFPProdTable>& prod_tables) {
init(inj_tables);
init(prod_tables);
}
VFPProperties::VFPProperties(const std::map<int, VFPInjTable>& inj_tables) {
init(inj_tables);
}
VFPProperties::VFPProperties(const std::map<int, VFPProdTable>& prod_tables) {
init(prod_tables);
}
void VFPProperties::init(const std::map<int, VFPInjTable>& inj_tables) {
//Populate injection table pointers.
for (const auto& table : inj_tables) {
m_inj_tables[table.first] = &table.second;
}
}
void VFPProperties::init(const std::map<int, VFPProdTable>& prod_tables) {
//Populate production table pointers
for (const auto& table : prod_tables) {
m_prod_tables[table.first] = &table.second;
}
}
double VFPProperties::bhp(int table, const double& flo, const double& thp, const double& wfr, const double& gfr, const double& alq) {
if (m_tables.find(table) == m_tables.end()) {
OPM_THROW(std::invalid_argument, "Nonexistant table " << table << " referenced.");
double VFPProperties::prod_bhp(int table, const double& flo, const double& thp, const double& wfr, const double& gfr, const double& alq) {
if (m_prod_tables.find(table) == m_prod_tables.end()) {
OPM_THROW(std::invalid_argument, "Nonexistent table " << table << " referenced.");
}
const auto* tab = m_prod_tables[table];
//First, find the values to interpolate between
auto flo_i = find_interp_data(flo, m_tables[table]->getFloAxis());
auto thp_i = find_interp_data(thp, m_tables[table]->getTHPAxis());
auto wfr_i = find_interp_data(wfr, m_tables[table]->getWFRAxis());
auto gfr_i = find_interp_data(gfr, m_tables[table]->getGFRAxis());
auto alq_i = find_interp_data(alq, m_tables[table]->getALQAxis());
auto flo_i = find_interp_data(flo, tab->getFloAxis());
auto thp_i = find_interp_data(thp, tab->getTHPAxis());
auto wfr_i = find_interp_data(wfr, tab->getWFRAxis());
auto gfr_i = find_interp_data(gfr, tab->getGFRAxis());
auto alq_i = find_interp_data(alq, tab->getALQAxis());
//Then perform the interpolation itself
return interpolate(m_tables[table]->getTable(), flo_i, thp_i, wfr_i, gfr_i, alq_i);
return interpolate(tab->getTable(), flo_i, thp_i, wfr_i, gfr_i, alq_i);
}
VFPProperties::ADB VFPProperties::bhp(int table, const ADB& flo, const ADB& thp, const ADB& wfr, const ADB& gfr, const ADB& alq) {
VFPProperties::ADB VFPProperties::prod_bhp(int table, const ADB& flo, const ADB& thp, const ADB& wfr, const ADB& gfr, const ADB& alq) {
const ADB::V& f_v = flo.value();
const ADB::V& t_v = thp.value();
const ADB::V& w_v = wfr.value();
@ -79,7 +102,7 @@ VFPProperties::ADB VFPProperties::bhp(int table, const ADB& flo, const ADB& thp,
ADB::V bhp_vals;
bhp_vals.resize(nw);
for (int i=0; i<nw; ++i) {
bhp_vals[i] = bhp(table, f_v[i], t_v[i], w_v[i], g_v[i], a_v[i]);
bhp_vals[i] = prod_bhp(table, f_v[i], t_v[i], w_v[i], g_v[i], a_v[i]);
}
//Create an ADB constant value.
return ADB::constant(bhp_vals);
@ -87,8 +110,8 @@ VFPProperties::ADB VFPProperties::bhp(int table, const ADB& flo, const ADB& thp,
VFPProperties::ADB VFPProperties::bhp(int table, const Wells& wells, const ADB& qs, const ADB& thp, const ADB& alq) {
if (m_tables.find(table) == m_tables.end()) {
VFPProperties::ADB VFPProperties::prod_bhp(int table, const Wells& wells, const ADB& qs, const ADB& thp, const ADB& alq) {
if (m_prod_tables.find(table) == m_prod_tables.end()) {
OPM_THROW(std::invalid_argument, "Nonexistant table " << table << " referenced.");
}
@ -102,13 +125,14 @@ VFPProperties::ADB VFPProperties::bhp(int table, const Wells& wells, const ADB&
const ADB& o = subset(qs, Span(nw, 1, BlackoilPhases::Liquid*nw));
const ADB& g = subset(qs, Span(nw, 1, BlackoilPhases::Vapour*nw));
ADB flo = getFlo(w, o, g, m_tables[table]->getFloType());
ADB wfr = getWFR(w, o, g, m_tables[table]->getWFRType());
ADB gfr = getGFR(w, o, g, m_tables[table]->getGFRType());
const auto* tab = m_prod_tables[table];
ADB flo = getFlo(w, o, g, tab->getFloType());
ADB wfr = getWFR(w, o, g, tab->getWFRType());
ADB gfr = getGFR(w, o, g, tab->getGFRType());
//TODO: Check ALQ type here?
return bhp(table, flo, thp, wfr, gfr, alq);
return prod_bhp(table, flo, thp, wfr, gfr, alq);
}

View File

@ -23,38 +23,57 @@
#include <opm/core/wells.h>
#include <opm/autodiff/AutoDiffBlock.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/VFPProdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/VFPInjTable.hpp>
#include <boost/multi_array.hpp>
#include <map>
namespace Opm {
class VFPProdTable;
/**
* Class which linearly interpolates BHP as a function of rate type, tubing head pressure,
* water fraction, gas fraction, and artificial lift.
* Class which linearly interpolates BHP as a function of rate, tubing head pressure,
* water fraction, gas fraction, and artificial lift for production VFP tables, and similarly
* the BHP as a function of the rate and tubing head pressure.
*/
class VFPProperties {
public:
typedef AutoDiffBlock<double> ADB;
/**
* Constructor
* Empty constructor
*/
VFPProperties();
/**
* Initialization routine for a single production table, takes *no* ownership of data.
* @param table A single VFPPROD table
* Constructor
* Takes *no* ownership of data.
* @param inj_table A *single* VFPINJ table or NULL (no table)
* @param prod_table A *single* VFPPROD table or NULL (no table)
*/
void init(const VFPProdTable* table);
VFPProperties(const VFPInjTable* inj_table, const VFPProdTable* prod_table);
/**
* Initialization routine, takes *no* ownership of data.
* @param tables A vector of different VFPPROD tables. Must have unique table numbers
* Constructor
* Takes *no* ownership of data.
* @param inj_tables A map of different VFPINJ tables.
* @param prod_tables A map of different VFPPROD tables.
*/
void init(const std::vector<VFPProdTable>& tables);
VFPProperties(const std::map<int, VFPInjTable>& inj_tables,
const std::map<int, VFPProdTable>& prod_tables);
/**
* Constructor
* Takes *no* ownership of data.
* @param inj_tables A map of different VFPINJ tables.
*/
VFPProperties(const std::map<int, VFPInjTable>& inj_tables);
/**
* Constructor
* Takes *no* ownership of data.
* @param prod_tables A map of different VFPPROD tables.
*/
VFPProperties(const std::map<int, VFPProdTable>& prod_tables);
/**
* Linear interpolation of bhp as function of the input parameters.
@ -67,7 +86,7 @@ public:
* @return The bottom hole pressure, interpolated/extrapolated linearly using
* the above parameters from the values in the input table.
*/
ADB bhp(int table,
ADB prod_bhp(int table,
const Wells& wells,
const ADB& qs,
const ADB& thp,
@ -85,7 +104,7 @@ public:
* @return The bottom hole pressure, interpolated/extrapolated linearly using
* the above parameters from the values in the input table.
*/
double bhp(int table,
double prod_bhp(int table,
const double& flo,
const double& thp,
const double& wfr,
@ -105,13 +124,15 @@ public:
* the above parameters from the values in the input table, for each entry in the
* input ADB objects.
*/
ADB bhp(int table,
ADB prod_bhp(int table,
const ADB& flo,
const ADB& thp,
const ADB& wfr,
const ADB& gfr,
const ADB& alq);
//FIXME: ARB: Implement inj_bhp to match the prod_bhp's, but for injection wells.
/**
* Computes the flo parameter according to the flo_type_
* @return Production rate of oil, gas or liquid.
@ -135,7 +156,8 @@ public:
private:
// Map which connects the table number with the table itself
std::map<int, const VFPProdTable*> m_tables;
std::map<int, const VFPProdTable*> m_prod_tables;
std::map<int, const VFPInjTable*> m_inj_tables;
/**
* Helper struct for linear interpolation
@ -161,6 +183,11 @@ private:
const InterpData& gfr_i,
const InterpData& alq_i);
/**
* Initialization routines
*/
void init(const std::map<int, VFPInjTable>& inj_tables);
void init(const std::map<int, VFPProdTable>& prod_tables);
};
}

View File

@ -28,7 +28,7 @@
#include <algorithm>
#include <memory>
#include <vector>
#include <map>
#include <sstream>
#include <boost/test/unit_test.hpp>
@ -136,8 +136,7 @@ struct TrivialFixture {
data);
//Initialize properties that use the table
properties.reset(new Opm::VFPProperties());
properties->init(&table);
properties.reset(new Opm::VFPProperties(NULL, &table));
}
std::shared_ptr<Opm::VFPProperties> properties;
@ -171,10 +170,10 @@ BOOST_AUTO_TEST_CASE(GetTable)
initProperties();
//Table 1 has been initialized
properties->bhp(1, 0.0, 0.0, 0.0, 0.0, 0.0);
properties->prod_bhp(1, 0.0, 0.0, 0.0, 0.0, 0.0);
//Table 2 does not exist.
BOOST_CHECK_THROW(properties->bhp(2, 0.0, 0.0, 0.0, 0.0, 0.0), std::invalid_argument);
BOOST_CHECK_THROW(properties->prod_bhp(2, 0.0, 0.0, 0.0, 0.0, 0.0), std::invalid_argument);
}
/**
@ -201,7 +200,7 @@ BOOST_AUTO_TEST_CASE(InterpolateZero)
const double v = m / static_cast<double>(n-1);
//Note order of arguments!
sum += properties->bhp(1, v, x, y, z, u);
sum += properties->prod_bhp(1, v, x, y, z, u);
}
}
}
@ -236,7 +235,7 @@ BOOST_AUTO_TEST_CASE(InterpolateOne)
const double v = m / static_cast<double>(n-1);
//Note order of arguments!
sum += properties->bhp(1, v, x, y, z, u);
sum += properties->prod_bhp(1, v, x, y, z, u);
}
}
}
@ -277,7 +276,7 @@ BOOST_AUTO_TEST_CASE(InterpolatePlane)
reference_sum += reference;
//Note order of arguments!
double value = properties->bhp(1, v, x, y, z, u);
double value = properties->prod_bhp(1, v, x, y, z, u);
sum += value;
double abs_diff = std::abs(value - reference);
@ -326,7 +325,7 @@ BOOST_AUTO_TEST_CASE(ExtrapolatePlane)
reference_sum += reference;
//Note order of arguments!
double value = properties->bhp(1, v, x, y, z, u);
double value = properties->prod_bhp(1, v, x, y, z, u);
sum += value;
double abs_diff = std::abs(value - reference);
@ -394,7 +393,7 @@ BOOST_AUTO_TEST_CASE(ExtrapolatePlaneADB)
ADB gfr = ADB::constant(zz);
ADB alq = ADB::constant(uu);
ADB bhp_val = properties->bhp(1, flo, thp, wfr, gfr, alq);
ADB bhp_val = properties->prod_bhp(1, flo, thp, wfr, gfr, alq);
double value = 0.0;
double reference = 0.0;
@ -474,7 +473,7 @@ BOOST_AUTO_TEST_CASE(InterpolateADBAndQs)
ADB alq = ADB::constant(alq_vals);
//Call the bhp function
ADB bhp = properties->bhp(1, *wells, qs, thp, alq);
ADB bhp = properties->prod_bhp(1, *wells, qs, thp, alq);
//Calculate reference
//First, find the three phases
@ -722,17 +721,10 @@ BOOST_AUTO_TEST_CASE(ParseInterpolateRealisticVFPPROD)
BOOST_REQUIRE(deck->hasKeyword("VFPPROD"));
BOOST_CHECK_EQUAL(deck->numKeywords("VFPPROD"), 1);
std::vector<Opm::VFPProdTable> tables;
Opm::VFPProdTable table;
table.init(deck->getKeyword("VFPPROD", 1), units);
int num_tables = deck->numKeywords("VFPPROD");
for (int i=0; i<num_tables; ++i) {
Opm::DeckKeywordConstPtr keyword = deck->getKeyword("VFPPROD", i);
tables.push_back(Opm::VFPProdTable());
tables[i].init(keyword, units);
}
Opm::VFPProperties properties;
properties.init(tables);
Opm::VFPProperties properties(NULL, &table);
//Do some rudimentary testing
//Get the BHP as a function of rate, thp, wfr, gfr, alq
@ -771,7 +763,7 @@ BOOST_AUTO_TEST_CASE(ParseInterpolateRealisticVFPPROD)
double a_i = 0.0;
//Value given as pascal, convert to barsa for comparison with reference
double value_i = properties.bhp(32, f_i, t_i, w_i, g_i, a_i) * 10.0e-6;
double value_i = properties.prod_bhp(32, f_i, t_i, w_i, g_i, a_i) * 10.0e-6;
double abs_diff = std::abs(value_i - reference[i]);
sad += abs_diff;
@ -792,8 +784,8 @@ BOOST_AUTO_TEST_CASE(ParseInterpolateRealisticVFPPROD)
std::cout << "];" << std::endl;
#endif
BOOST_CHECK_SMALL(max_d, 1.0e-12);
BOOST_CHECK_SMALL(sad, 1.0e-9);
BOOST_CHECK_SMALL(max_d, max_d_tol);
BOOST_CHECK_SMALL(sad, sad_tol);
}
/**