Support Outputting Preferred Phase PI to Summary File
This commit adds support for outputting the productivity index of a well's preferred phase at the well and connection levels to the summary file (keywords 'WPI' and 'CPI'). Update unit tests accordingly.
This commit is contained in:
parent
a4e05aee47
commit
a14c4184a9
@ -958,6 +958,69 @@ inline quantity potential_rate( const fn_args& args ) {
|
||||
return { sum, rate_unit< phase >() };
|
||||
}
|
||||
|
||||
inline quantity preferred_phase_productivty_index(const fn_args& args) {
|
||||
if (args.schedule_wells.empty())
|
||||
return potential_rate<rt::productivity_index_oil>(args);
|
||||
|
||||
switch (args.schedule_wells.front().getPreferredPhase()) {
|
||||
case Opm::Phase::OIL:
|
||||
return potential_rate<rt::productivity_index_oil>(args);
|
||||
|
||||
case Opm::Phase::GAS:
|
||||
return potential_rate<rt::productivity_index_gas>(args);
|
||||
|
||||
case Opm::Phase::WATER:
|
||||
return potential_rate<rt::productivity_index_water>(args);
|
||||
}
|
||||
|
||||
throw std::invalid_argument {
|
||||
"Unsupported \"preferred\" phase: " +
|
||||
std::to_string(static_cast<int>(args.schedule_wells.front().getPreferredPhase()))
|
||||
};
|
||||
}
|
||||
|
||||
inline quantity connection_productivity_index(const fn_args& args) {
|
||||
const quantity zero = { 0.0, rate_unit<rt::productivity_index_oil>() };
|
||||
|
||||
if (args.schedule_wells.empty())
|
||||
return zero;
|
||||
|
||||
auto xwPos = args.wells.find(args.schedule_wells.front().name());
|
||||
if (xwPos == args.wells.end())
|
||||
return zero;
|
||||
|
||||
// The args.num value is the literal value which will go to the
|
||||
// NUMS array in the eclipse SMSPEC file; the values in this array
|
||||
// are offset 1 - whereas we need to use this index here to look
|
||||
// up a completion with offset 0.
|
||||
const auto global_index = static_cast<std::size_t>(args.num) - 1;
|
||||
|
||||
const auto& xcon = xwPos->second.connections;
|
||||
const auto& completion =
|
||||
std::find_if(xcon.begin(), xcon.end(),
|
||||
[global_index](const Opm::data::Connection& c)
|
||||
{
|
||||
return c.index == global_index;
|
||||
});
|
||||
|
||||
if (completion == xcon.end())
|
||||
return zero;
|
||||
|
||||
switch (args.schedule_wells.front().getPreferredPhase()) {
|
||||
case Opm::Phase::GAS:
|
||||
return { completion->rates.get(rt::productivity_index_gas, 0.0),
|
||||
rate_unit<rt::productivity_index_gas>() };
|
||||
|
||||
case Opm::Phase::WATER:
|
||||
return { completion->rates.get(rt::productivity_index_water, 0.0),
|
||||
rate_unit<rt::productivity_index_water>() };
|
||||
|
||||
default:
|
||||
return { completion->rates.get(rt::productivity_index_oil, 0.0),
|
||||
rate_unit<rt::productivity_index_oil>() };
|
||||
}
|
||||
}
|
||||
|
||||
template < bool isGroup, bool Producer, bool waterInjector, bool gasInjector>
|
||||
inline quantity group_control( const fn_args& args ) {
|
||||
|
||||
@ -1444,6 +1507,7 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "CSIT", mul( crate< rt::brine, injector >, duration ) },
|
||||
{ "CSPT", mul( crate< rt::brine, producer >, duration ) },
|
||||
{ "CTFAC", trans_factors },
|
||||
{ "CPI", connection_productivity_index },
|
||||
|
||||
{ "FWPR", rate< rt::wat, producer > },
|
||||
{ "FOPR", rate< rt::oil, producer > },
|
||||
@ -1587,10 +1651,12 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "SPRDF", segpress<Opm::data::SegmentPressures::Value::PDropFriction> },
|
||||
{ "SPRDA", segpress<Opm::data::SegmentPressures::Value::PDropAccel> },
|
||||
// Well productivity index
|
||||
{ "WPI", preferred_phase_productivty_index },
|
||||
{ "WPIW", potential_rate< rt::productivity_index_water >},
|
||||
{ "WPIO", potential_rate< rt::productivity_index_oil >},
|
||||
{ "WPIG", potential_rate< rt::productivity_index_gas >},
|
||||
{ "WPIL", sum( potential_rate< rt::productivity_index_water >, potential_rate< rt::productivity_index_oil>)},
|
||||
{ "WPIL", sum( potential_rate< rt::productivity_index_water, true, false >,
|
||||
potential_rate< rt::productivity_index_oil, true, false >)},
|
||||
// Well potential
|
||||
{ "WWPP", potential_rate< rt::well_potential_water , true, false>},
|
||||
{ "WOPP", potential_rate< rt::well_potential_oil , true, false>},
|
||||
|
@ -621,6 +621,14 @@ WTHPH
|
||||
/
|
||||
WPI
|
||||
/
|
||||
WPIO
|
||||
/
|
||||
WPIG
|
||||
/
|
||||
WPIW
|
||||
/
|
||||
WPIL
|
||||
/
|
||||
WBP
|
||||
/
|
||||
WBP4
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
#include <opm/io/eclipse/ESmry.hpp>
|
||||
|
||||
@ -92,6 +93,15 @@ namespace {
|
||||
*/
|
||||
static const int day = 24 * 60 * 60;
|
||||
|
||||
double liquid_PI_unit()
|
||||
{
|
||||
return UnitSystem::newMETRIC().to_si(UnitSystem::measure::liquid_productivity_index, 1.0);
|
||||
}
|
||||
|
||||
double gas_PI_unit()
|
||||
{
|
||||
return UnitSystem::newMETRIC().to_si(UnitSystem::measure::gas_productivity_index, 1.0);
|
||||
}
|
||||
|
||||
/*
|
||||
This is quite misleading, because the values prepared in the test
|
||||
@ -125,9 +135,9 @@ data::Wells result_wells(const bool w3_injector = true)
|
||||
rates1.set( rt::reservoir_water, -10.6 / day );
|
||||
rates1.set( rt::reservoir_oil, -10.7 / day );
|
||||
rates1.set( rt::reservoir_gas, -10.8 / day );
|
||||
rates1.set( rt::productivity_index_water, -10.9 / day );
|
||||
rates1.set( rt::productivity_index_oil, -10.11 / day );
|
||||
rates1.set( rt::productivity_index_gas, -10.12 / day );
|
||||
rates1.set( rt::productivity_index_water, 10.9*liquid_PI_unit());
|
||||
rates1.set( rt::productivity_index_oil, 10.11*liquid_PI_unit());
|
||||
rates1.set( rt::productivity_index_gas, 10.12*gas_PI_unit());
|
||||
rates1.set( rt::well_potential_water, -10.13 / day );
|
||||
rates1.set( rt::well_potential_oil, -10.14 / day );
|
||||
rates1.set( rt::well_potential_gas, -10.15 / day );
|
||||
@ -144,9 +154,9 @@ data::Wells result_wells(const bool w3_injector = true)
|
||||
rates2.set( rt::reservoir_water, -20.6 / day );
|
||||
rates2.set( rt::reservoir_oil, -20.7 / day );
|
||||
rates2.set( rt::reservoir_gas, -20.8 / day );
|
||||
rates2.set( rt::productivity_index_water, -20.9 / day );
|
||||
rates2.set( rt::productivity_index_oil, -20.11 / day );
|
||||
rates2.set( rt::productivity_index_gas, -20.12 / day );
|
||||
rates2.set( rt::productivity_index_water, 20.9*liquid_PI_unit());
|
||||
rates2.set( rt::productivity_index_oil, 20.11*liquid_PI_unit());
|
||||
rates2.set( rt::productivity_index_gas, 20.12*gas_PI_unit());
|
||||
rates2.set( rt::well_potential_water, -20.13 / day );
|
||||
rates2.set( rt::well_potential_oil, -20.14 / day );
|
||||
rates2.set( rt::well_potential_gas, -20.15 / day );
|
||||
@ -163,16 +173,15 @@ data::Wells result_wells(const bool w3_injector = true)
|
||||
rates3.set( rt::reservoir_water, 30.6 / day );
|
||||
rates3.set( rt::reservoir_oil, 30.7 / day );
|
||||
rates3.set( rt::reservoir_gas, 30.8 / day );
|
||||
rates3.set( rt::productivity_index_water, -30.9 / day );
|
||||
rates3.set( rt::productivity_index_oil, -30.11 / day );
|
||||
rates3.set( rt::productivity_index_gas, -30.12 / day );
|
||||
rates3.set( rt::productivity_index_water, 30.9*liquid_PI_unit());
|
||||
rates3.set( rt::productivity_index_oil, 30.11*liquid_PI_unit());
|
||||
rates3.set( rt::productivity_index_gas, 30.12*gas_PI_unit());
|
||||
rates3.set( rt::well_potential_water, 30.13 / day );
|
||||
rates3.set( rt::well_potential_oil, 30.14 / day );
|
||||
rates3.set( rt::well_potential_gas, 30.15 / day );
|
||||
rates3.set( rt::polymer, 30.16 / day );
|
||||
rates3.set( rt::brine, 30.17 / day );
|
||||
|
||||
|
||||
data::Rates rates6;
|
||||
rates6.set( rt::wat, 60.0 / day );
|
||||
rates6.set( rt::oil, 60.1 / day );
|
||||
@ -183,14 +192,15 @@ data::Wells result_wells(const bool w3_injector = true)
|
||||
rates6.set( rt::reservoir_water, 60.6 / day );
|
||||
rates6.set( rt::reservoir_oil, 60.7 / day );
|
||||
rates6.set( rt::reservoir_gas, 60.8 / day );
|
||||
rates6.set( rt::productivity_index_water, -60.9 / day );
|
||||
rates6.set( rt::productivity_index_oil, -60.11 / day );
|
||||
rates6.set( rt::productivity_index_gas, -60.12 / day );
|
||||
rates6.set( rt::productivity_index_water, 60.9*liquid_PI_unit());
|
||||
rates6.set( rt::productivity_index_oil, 60.11*liquid_PI_unit());
|
||||
rates6.set( rt::productivity_index_gas, 60.12*gas_PI_unit());
|
||||
rates6.set( rt::well_potential_water, 60.13 / day );
|
||||
rates6.set( rt::well_potential_oil, 60.14 / day );
|
||||
rates6.set( rt::well_potential_gas, 60.15 / day );
|
||||
rates6.set( rt::polymer, 60.16 / day );
|
||||
rates6.set( rt::brine, 60.17 / day );
|
||||
|
||||
/* completion rates */
|
||||
data::Rates crates1;
|
||||
crates1.set( rt::wat, -100.0 / day );
|
||||
@ -388,12 +398,14 @@ double ecl_sum_get_general_var(const EclIO::ESmry* smry,
|
||||
return smry->get(var)[timeIdx];
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool ecl_sum_has_well_var( const EclIO::ESmry* smry,
|
||||
const std::string& wellname,
|
||||
const std::string& variable )
|
||||
{
|
||||
return smry->hasKey(variable + ':' + wellname);
|
||||
}
|
||||
#endif
|
||||
|
||||
double ecl_sum_get_well_var( const EclIO::ESmry* smry,
|
||||
const int timeIdx,
|
||||
@ -526,6 +538,28 @@ BOOST_AUTO_TEST_CASE(well_keywords) {
|
||||
BOOST_CHECK_CLOSE( 30.13, ecl_sum_get_well_var( resp, 1, "W_3", "WWPI" ), 1e-5 );
|
||||
BOOST_CHECK_CLOSE( 60.15, ecl_sum_get_well_var( resp, 1, "W_6", "WGPI" ), 1e-5 );
|
||||
|
||||
BOOST_CHECK_CLOSE( 10.9 , ecl_sum_get_well_var( resp, 1, "W_1", "WPIW" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 10.11, ecl_sum_get_well_var( resp, 1, "W_1", "WPIO" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 10.12, ecl_sum_get_well_var( resp, 1, "W_1", "WPIG" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 10.11, ecl_sum_get_well_var( resp, 1, "W_1", "WPI" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 21.01, ecl_sum_get_well_var( resp, 1, "W_1", "WPIL" ), 1.0e-5 );
|
||||
|
||||
BOOST_CHECK_CLOSE( 20.9 , ecl_sum_get_well_var( resp, 1, "W_2", "WPIW" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 20.11, ecl_sum_get_well_var( resp, 1, "W_2", "WPIO" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 20.12, ecl_sum_get_well_var( resp, 1, "W_2", "WPIG" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 20.11, ecl_sum_get_well_var( resp, 1, "W_2", "WPI" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 41.01, ecl_sum_get_well_var( resp, 1, "W_2", "WPIL" ), 1.0e-5 );
|
||||
|
||||
BOOST_CHECK_CLOSE( 30.9 , ecl_sum_get_well_var( resp, 1, "W_3", "WPIW" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 30.11, ecl_sum_get_well_var( resp, 1, "W_3", "WPIO" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 30.12, ecl_sum_get_well_var( resp, 1, "W_3", "WPIG" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 30.9 , ecl_sum_get_well_var( resp, 1, "W_3", "WPI" ), 1.0e-5 );
|
||||
|
||||
BOOST_CHECK_CLOSE( 60.9 , ecl_sum_get_well_var( resp, 1, "W_6", "WPIW" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 60.11, ecl_sum_get_well_var( resp, 1, "W_6", "WPIO" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 60.12, ecl_sum_get_well_var( resp, 1, "W_6", "WPIG" ), 1.0e-5 );
|
||||
BOOST_CHECK_CLOSE( 60.12, ecl_sum_get_well_var( resp, 1, "W_6", "WPI" ), 1.0e-5 );
|
||||
|
||||
BOOST_CHECK_CLOSE( 123.456, ecl_sum_get_well_var(resp, 1, "W_1", "WOPGR"), 1.0e-5);
|
||||
BOOST_CHECK_CLOSE(2345.67 , ecl_sum_get_well_var(resp, 1, "W_1", "WGPGR"), 1.0e-5);
|
||||
BOOST_CHECK_CLOSE( 654.321, ecl_sum_get_well_var(resp, 1, "W_2", "WWPGR"), 1.0e-5);
|
||||
@ -1218,7 +1252,6 @@ BOOST_AUTO_TEST_CASE(skip_unknown_var) {
|
||||
const auto* resp = res.get();
|
||||
|
||||
/* verify that some non-supported keywords aren't written to the file */
|
||||
BOOST_CHECK( !ecl_sum_has_well_var( resp, "W_1", "WPI" ) );
|
||||
BOOST_CHECK( !ecl_sum_has_field_var( resp, "FGST" ) );
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user