mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Minor refactoring of VFPProperties to prepare for support for VFPINJ tables
This commit is contained in:
parent
15d3171ae1
commit
3260e978da
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user