commit
b05680f76b
@ -460,7 +460,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
tests/msim/MSIM_PYACTION.DATA
|
||||
tests/msim/action1.py
|
||||
tests/msim/action2.py
|
||||
)
|
||||
tests/VFP_CASE.DATA)
|
||||
endif()
|
||||
|
||||
list (APPEND EXAMPLE_SOURCE_FILES
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <opm/parser/eclipse/Units/Dimension.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@ -83,6 +84,7 @@ public:
|
||||
const std::vector<double>& gfr_data,
|
||||
const std::vector<double>& alq_data,
|
||||
const array_type& data);
|
||||
static Dimension ALQDimension(const ALQ_TYPE& alq_type, const UnitSystem& unit_system);
|
||||
|
||||
static VFPProdTable serializeObject();
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellTracerProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellPolymerProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellEconProductionLimits.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
|
||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||
|
||||
#include <opm/common/utility/ActiveGridCells.hpp>
|
||||
@ -386,8 +387,8 @@ public:
|
||||
|
||||
// this is used to check whether the specified control mode is an effective history matching production mode
|
||||
static bool effectiveHistoryProductionControl(ProducerCMode cmode);
|
||||
void handleWCONPROD( const std::string& well, const DeckRecord& record);
|
||||
void handleWCONHIST( const DeckRecord& record);
|
||||
void handleWCONPROD( const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system, const std::string& well, const DeckRecord& record);
|
||||
void handleWCONHIST( const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system, const DeckRecord& record);
|
||||
void handleWELTARG( WELTARGCMode cmode, const UDAValue& new_arg, double SiFactorP);
|
||||
void resetDefaultBHPLimit();
|
||||
void clearControls();
|
||||
@ -425,6 +426,7 @@ public:
|
||||
void init_rates( const DeckRecord& record );
|
||||
|
||||
void init_history(const DeckRecord& record);
|
||||
void init_vfp(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system, const DeckRecord& record);
|
||||
|
||||
WellProductionProperties(const DeckRecord& record);
|
||||
|
||||
|
@ -469,20 +469,20 @@ double efac( const std::vector<std::pair<std::string,double>>& eff_factors, cons
|
||||
return (it != eff_factors.end()) ? it->second : 1;
|
||||
}
|
||||
|
||||
inline quantity alqrate( const fn_args& args ) {
|
||||
inline quantity glir( const fn_args& args ) {
|
||||
const quantity zero = { 0.0, measure::gas_surface_rate };
|
||||
|
||||
if (args.schedule_wells.empty()) {
|
||||
// No wells. Before simulation starts?
|
||||
if (args.schedule_wells.empty())
|
||||
return zero;
|
||||
}
|
||||
|
||||
const auto& well = args.schedule_wells.front();
|
||||
auto xwPos = args.wells.find(well.name());
|
||||
if (xwPos == args.wells.end()) {
|
||||
if (xwPos == args.wells.end())
|
||||
return zero;
|
||||
}
|
||||
|
||||
// This is bit dangerous, exactly how the ALQ value should be interpreted
|
||||
// varies between the different VFP tables. The code here assumes - without
|
||||
// checking - that it represents gas lift rate.
|
||||
return { xwPos->second.rates.get(rt::alq, 0.0), measure::gas_surface_rate };
|
||||
}
|
||||
|
||||
@ -1037,7 +1037,7 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "WOPR", rate< rt::oil, producer > },
|
||||
{ "WGPR", rate< rt::gas, producer > },
|
||||
{ "WEPR", rate< rt::energy, producer > },
|
||||
{ "WGLIR", alqrate },
|
||||
{ "WGLIR", glir},
|
||||
{ "WNPR", rate< rt::solvent, producer > },
|
||||
{ "WCPR", rate< rt::polymer, producer > },
|
||||
{ "WSPR", rate< rt::brine, producer > },
|
||||
@ -1119,7 +1119,7 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "GWPR", rate< rt::wat, producer > },
|
||||
{ "GOPR", rate< rt::oil, producer > },
|
||||
{ "GGPR", rate< rt::gas, producer > },
|
||||
{ "GGLIR", alqrate },
|
||||
{ "GGLIR", glir },
|
||||
{ "GNPR", rate< rt::solvent, producer > },
|
||||
{ "GCPR", rate< rt::polymer, producer > },
|
||||
{ "GSPR", rate< rt::brine, producer > },
|
||||
@ -1273,7 +1273,7 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "FWPR", rate< rt::wat, producer > },
|
||||
{ "FOPR", rate< rt::oil, producer > },
|
||||
{ "FGPR", rate< rt::gas, producer > },
|
||||
{ "FGLIR", alqrate },
|
||||
{ "FGLIR", glir },
|
||||
{ "FNPR", rate< rt::solvent, producer > },
|
||||
{ "FCPR", rate< rt::polymer, producer > },
|
||||
{ "FSPR", rate< rt::brine, producer > },
|
||||
|
@ -819,6 +819,7 @@ namespace {
|
||||
}
|
||||
|
||||
void Schedule::handleWCONHIST(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||
const auto& unit_system = handlerContext.section.unitSystem();
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
|
||||
const auto well_names = this->wellNames(wellNamePattern, handlerContext.currentStep);
|
||||
@ -830,12 +831,17 @@ namespace {
|
||||
for (const auto& well_name : well_names) {
|
||||
updateWellStatus( well_name , handlerContext.currentStep , status, false );
|
||||
|
||||
const auto table_nr = record.getItem("VFP_TABLE").get< int >(0);
|
||||
std::optional<VFPProdTable::ALQ_TYPE> alq_type;
|
||||
auto& dynamic_state = this->wells_static.at(well_name);
|
||||
auto well2 = std::make_shared<Well>(*dynamic_state[handlerContext.currentStep]);
|
||||
const bool switching_from_injector = !well2->isProducer();
|
||||
auto properties = std::make_shared<Well::WellProductionProperties>(well2->getProductionProperties());
|
||||
bool update_well = false;
|
||||
properties->handleWCONHIST(record);
|
||||
|
||||
if (table_nr != 0)
|
||||
alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType();
|
||||
properties->handleWCONHIST(alq_type, unit_system, record);
|
||||
|
||||
if (switching_from_injector) {
|
||||
properties->resetDefaultBHPLimit();
|
||||
@ -880,6 +886,7 @@ namespace {
|
||||
}
|
||||
|
||||
void Schedule::handleWCONPROD(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||
const auto& unit_system = handlerContext.section.unitSystem();
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
|
||||
const auto well_names = this->wellNames(wellNamePattern, handlerContext.currentStep);
|
||||
@ -890,7 +897,8 @@ namespace {
|
||||
|
||||
for (const auto& well_name : well_names) {
|
||||
updateWellStatus(well_name, handlerContext.currentStep, status, false);
|
||||
|
||||
const auto table_nr = record.getItem("VFP_TABLE").get< int >(0);
|
||||
std::optional<VFPProdTable::ALQ_TYPE> alq_type;
|
||||
auto& dynamic_state = this->wells_static.at(well_name);
|
||||
auto well2 = std::make_shared<Well>(*dynamic_state[handlerContext.currentStep]);
|
||||
const bool switching_from_injector = !well2->isProducer();
|
||||
@ -900,7 +908,9 @@ namespace {
|
||||
if (well2->isAvailableForGroupControl())
|
||||
properties->addProductionControl(Well::ProducerCMode::GRUP);
|
||||
|
||||
properties->handleWCONPROD(well_name, record);
|
||||
if (table_nr != 0)
|
||||
alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType();
|
||||
properties->handleWCONPROD(alq_type, unit_system, well_name, record);
|
||||
|
||||
if (switching_from_injector)
|
||||
properties->resetDefaultBHPLimit();
|
||||
|
@ -450,13 +450,17 @@ void VFPProdTable::convertFloToSI(const FLO_TYPE& type,
|
||||
std::vector<double>& values,
|
||||
const UnitSystem& unit_system) {
|
||||
double scaling_factor = 1.0;
|
||||
const auto liquid_surface_volume = unit_system.getDimension(UnitSystem::measure::liquid_surface_volume).getSIScaling();
|
||||
const auto gas_surface_volume = unit_system.getDimension(UnitSystem::measure::gas_surface_volume).getSIScaling();
|
||||
const auto time = unit_system.getDimension(UnitSystem::measure::time).getSIScaling();
|
||||
|
||||
switch (type) {
|
||||
case FLO_OIL:
|
||||
case FLO_LIQ:
|
||||
scaling_factor = unit_system.parse("LiquidSurfaceVolume/Time").getSIScaling();
|
||||
scaling_factor = liquid_surface_volume / time;
|
||||
break;
|
||||
case FLO_GAS:
|
||||
scaling_factor = unit_system.parse("GasSurfaceVolume/Time").getSIScaling();
|
||||
scaling_factor = gas_surface_volume / time;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid FLO type");
|
||||
@ -472,7 +476,7 @@ void VFPProdTable::convertFloToSI(const FLO_TYPE& type,
|
||||
|
||||
void VFPProdTable::convertTHPToSI(std::vector<double>& values,
|
||||
const UnitSystem& unit_system) {
|
||||
double scaling_factor = unit_system.parse("Pressure").getSIScaling();
|
||||
const auto scaling_factor = unit_system.getDimension(UnitSystem::measure::pressure).getSIScaling();
|
||||
scaleValues(values, scaling_factor);
|
||||
}
|
||||
|
||||
@ -486,13 +490,14 @@ void VFPProdTable::convertWFRToSI(const WFR_TYPE& type,
|
||||
std::vector<double>& values,
|
||||
const UnitSystem& unit_system) {
|
||||
double scaling_factor = 1.0;
|
||||
const auto liquid_surface_volume = unit_system.getDimension(UnitSystem::measure::liquid_surface_volume).getSIScaling();
|
||||
const auto gas_surface_volume = unit_system.getDimension(UnitSystem::measure::gas_surface_volume).getSIScaling();
|
||||
switch (type) {
|
||||
case WFR_WOR:
|
||||
case WFR_WCT:
|
||||
scaling_factor = unit_system.parse("LiquidSurfaceVolume/LiquidSurfaceVolume").getSIScaling();
|
||||
break;
|
||||
case WFR_WGR:
|
||||
scaling_factor = unit_system.parse("LiquidSurfaceVolume/GasSurfaceVolume").getSIScaling();
|
||||
scaling_factor = liquid_surface_volume / gas_surface_volume;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid FLO type");
|
||||
@ -510,13 +515,15 @@ void VFPProdTable::convertGFRToSI(const GFR_TYPE& type,
|
||||
std::vector<double>& values,
|
||||
const UnitSystem& unit_system) {
|
||||
double scaling_factor = 1.0;
|
||||
const auto liquid_surface_volume = unit_system.getDimension(UnitSystem::measure::liquid_surface_volume).getSIScaling();
|
||||
const auto gas_surface_volume = unit_system.getDimension(UnitSystem::measure::gas_surface_volume).getSIScaling();
|
||||
switch (type) {
|
||||
case GFR_GOR:
|
||||
case GFR_GLR:
|
||||
scaling_factor = unit_system.parse("GasSurfaceVolume/LiquidSurfaceVolume").getSIScaling();
|
||||
scaling_factor = gas_surface_volume / liquid_surface_volume;
|
||||
break;
|
||||
case GFR_OGR:
|
||||
scaling_factor = unit_system.parse("LiquidSurfaceVolume/GasSurfaceVolume").getSIScaling();
|
||||
scaling_factor = liquid_surface_volume / gas_surface_volume;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid FLO type");
|
||||
@ -525,32 +532,43 @@ void VFPProdTable::convertGFRToSI(const GFR_TYPE& type,
|
||||
}
|
||||
|
||||
|
||||
Dimension VFPProdTable::ALQDimension(const ALQ_TYPE& alq_type, const UnitSystem& unit_system) {
|
||||
double scaling_factor = 1.0;
|
||||
const auto liquid_surface_volume = unit_system.getDimension(UnitSystem::measure::liquid_surface_volume).getSIScaling();
|
||||
const auto gas_surface_volume = unit_system.getDimension(UnitSystem::measure::gas_surface_volume).getSIScaling();
|
||||
const auto time = unit_system.getDimension(UnitSystem::measure::time).getSIScaling();
|
||||
|
||||
switch (alq_type) {
|
||||
case ALQ_IGLR:
|
||||
scaling_factor = gas_surface_volume / (liquid_surface_volume * time);
|
||||
break;
|
||||
case ALQ_TGLR:
|
||||
scaling_factor = gas_surface_volume / liquid_surface_volume;
|
||||
break;
|
||||
case ALQ_GRAT:
|
||||
scaling_factor = gas_surface_volume / time;
|
||||
break;
|
||||
case ALQ_UNDEF:
|
||||
break;
|
||||
case ALQ_PUMP:
|
||||
case ALQ_COMP:
|
||||
case ALQ_INVALID:
|
||||
case ALQ_BEAN:
|
||||
std::logic_error("scaling of the given ALQ type, not implemented ");
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid ALQ type");
|
||||
}
|
||||
|
||||
return Dimension(scaling_factor);
|
||||
}
|
||||
|
||||
|
||||
void VFPProdTable::convertAlqToSI(const ALQ_TYPE& type,
|
||||
std::vector<double>& values,
|
||||
const UnitSystem& unit_system) {
|
||||
double scaling_factor = 1.0;
|
||||
switch (type) {
|
||||
case ALQ_IGLR:
|
||||
scaling_factor = unit_system.parse("GasSurfaceVolume/LiquidSurfaceVolume*Time").getSIScaling();
|
||||
break;
|
||||
case ALQ_TGLR:
|
||||
scaling_factor = unit_system.parse("GasSurfaceVolume/LiquidSurfaceVolume").getSIScaling();
|
||||
break;
|
||||
case ALQ_GRAT:
|
||||
scaling_factor = unit_system.parse("GasSurfaceVolume/Time").getSIScaling();
|
||||
break;
|
||||
case ALQ_UNDEF:
|
||||
break;
|
||||
case ALQ_PUMP:
|
||||
case ALQ_COMP:
|
||||
case ALQ_INVALID:
|
||||
case ALQ_BEAN:
|
||||
std::logic_error("scaling of the given ALQ type, not implemented ");
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid ALQ type");
|
||||
}
|
||||
scaleValues(values, scaling_factor);
|
||||
const auto& dim = VFPProdTable::ALQDimension(type, unit_system);
|
||||
scaleValues(values, dim.getSIScaling());
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
|
||||
|
||||
#include "../eval_uda.hpp"
|
||||
|
||||
@ -89,6 +90,20 @@ namespace Opm {
|
||||
}
|
||||
|
||||
|
||||
void Well::WellProductionProperties::init_vfp(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system, const DeckRecord& record) {
|
||||
if (alq_type) {
|
||||
this->VFPTableNumber = record.getItem("VFP_TABLE").get<int>(0);
|
||||
double alq_input = record.getItem("ALQ").get<double>(0);
|
||||
const auto alq_dim = VFPProdTable::ALQDimension(*alq_type, unit_system);
|
||||
this->ALQValue = alq_dim.convertRawToSi(alq_input);
|
||||
} else {
|
||||
const auto table_nr = record.getItem("VFP_TABLE").get< int >(0);
|
||||
if (table_nr != 0)
|
||||
throw std::logic_error("VFP table inconsistency - BUG");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Well::WellProductionProperties::init_history(const DeckRecord& record)
|
||||
{
|
||||
this->predictionMode = false;
|
||||
@ -135,25 +150,18 @@ namespace Opm {
|
||||
if (cmode == ProducerCMode::BHP)
|
||||
this->setBHPLimit(this->BHPH);
|
||||
|
||||
const auto vfp_table = record.getItem("VFP_TABLE").get< int >(0);
|
||||
if (vfp_table != 0)
|
||||
this->VFPTableNumber = vfp_table;
|
||||
|
||||
auto alq_value = record.getItem("LIFT").get<double>(0); //NOTE: Unit of ALQ is never touched
|
||||
if (alq_value != 0.)
|
||||
this->ALQValue = alq_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Well::WellProductionProperties::handleWCONPROD( const std::string& /* well */, const DeckRecord& record)
|
||||
void Well::WellProductionProperties::handleWCONPROD(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system, const std::string& /* well */, const DeckRecord& record)
|
||||
{
|
||||
this->predictionMode = true;
|
||||
this->init_vfp(alq_type, unit_system, record);
|
||||
this->init_rates(record);
|
||||
|
||||
this->BHPTarget = record.getItem("BHP").get<UDAValue>(0);
|
||||
this->THPTarget = record.getItem("THP").get<UDAValue>(0);
|
||||
this->ALQValue = record.getItem("ALQ").get< double >(0); //NOTE: Unit of ALQ is never touched
|
||||
this->VFPTableNumber = record.getItem("VFP_TABLE").get< int >(0);
|
||||
this->LiquidRate = record.getItem("LRAT").get<UDAValue>(0);
|
||||
this->ResVRate = record.getItem("RESV").get<UDAValue>(0);
|
||||
|
||||
@ -164,8 +172,6 @@ namespace Opm {
|
||||
};
|
||||
|
||||
|
||||
this->init_rates(record);
|
||||
|
||||
for( const auto& cmode : modes ) {
|
||||
if( !record.getItem( cmode.first ).defaultApplied( 0 ) ) {
|
||||
|
||||
@ -197,9 +203,10 @@ namespace Opm {
|
||||
originate from the WCONHIST keyword. Predictions are handled with the
|
||||
default constructor and the handleWCONPROD() method.
|
||||
*/
|
||||
void Well::WellProductionProperties::handleWCONHIST(const DeckRecord& record)
|
||||
void Well::WellProductionProperties::handleWCONHIST(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system, const DeckRecord& record)
|
||||
{
|
||||
this->init_rates(record);
|
||||
this->init_vfp(alq_type, unit_system, record);
|
||||
this->LiquidRate = 0;
|
||||
this->ResVRate = 0;
|
||||
|
||||
@ -250,9 +257,10 @@ namespace Opm {
|
||||
this->THPTarget.update_value( new_arg );
|
||||
this->addProductionControl( ProducerCMode::THP );
|
||||
}
|
||||
else if (cmode == WELTARGCMode::VFP)
|
||||
this->VFPTableNumber = static_cast<int>(new_arg.get<double>());
|
||||
else if (cmode != WELTARGCMode::GUID)
|
||||
else if (cmode == WELTARGCMode::VFP) {
|
||||
OpmLog::warning("When using WELTARG to change VFP table it is assumed that ALQ type is the same for the new and old table");
|
||||
this->VFPTableNumber = static_cast<int>( new_arg.get<double>() );
|
||||
} else if (cmode != WELTARGCMode::GUID)
|
||||
throw std::invalid_argument("Invalid keyword (MODE) supplied");
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
"comment": "The default is a state variable"
|
||||
},
|
||||
{
|
||||
"name": "LIFT",
|
||||
"name": "ALQ",
|
||||
"value_type": "DOUBLE",
|
||||
"default": 0,
|
||||
"comment": "The default is a state variable"
|
||||
|
8057
tests/VFP_CASE.DATA
Normal file
8057
tests/VFP_CASE.DATA
Normal file
File diff suppressed because it is too large
Load Diff
@ -161,8 +161,8 @@ BOOST_AUTO_TEST_CASE(createDeckWithWGRUPCONandWCONPROD) {
|
||||
"/\n"
|
||||
|
||||
"WCONPROD\n"
|
||||
" 'B-37T2' 'OPEN' 'GRUP' 1000 2* 2000.000 2* 1* 10 200000.000 5* / / \n"
|
||||
" 'B-43A' 'OPEN' 'GRUP' 1200 2* 3000.000 2* 1* 11 0.000 5* / / \n"
|
||||
" 'B-37T2' 'OPEN' 'GRUP' 1000 2* 2000.000 2* 1* 0 200000.000 5* / / \n"
|
||||
" 'B-43A' 'OPEN' 'GRUP' 1200 2* 3000.000 2* 1* 0 0.000 5* / / \n"
|
||||
"/\n";
|
||||
|
||||
|
||||
|
@ -955,7 +955,6 @@ BOOST_AUTO_TEST_CASE(createDeckWithWeltArg) {
|
||||
" OP_1 RESV 1801.05 /\n"
|
||||
" OP_1 BHP 1900 /\n"
|
||||
" OP_1 THP 2000 /\n"
|
||||
" OP_1 VFP 2100.09 /\n"
|
||||
" OP_1 GUID 2300.14 /\n"
|
||||
"/\n";
|
||||
|
||||
@ -985,7 +984,6 @@ BOOST_AUTO_TEST_CASE(createDeckWithWeltArg) {
|
||||
BOOST_CHECK_EQUAL(prod_controls.resv_rate, 1801.05 * siFactorL);
|
||||
BOOST_CHECK_EQUAL(prod_controls.bhp_limit, 1900 * siFactorP);
|
||||
BOOST_CHECK_EQUAL(prod_controls.thp_limit, 2000 * siFactorP);
|
||||
BOOST_CHECK_EQUAL(prod_controls.vfp_table_number, 2100);
|
||||
|
||||
BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::ORAT) );
|
||||
BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::RESV) );
|
||||
@ -3799,3 +3797,29 @@ END
|
||||
BOOST_CHECK_MESSAGE(sched.hasWellGroupEvent("P", ScheduleEvents::WELL_PRODUCTIVITY_INDEX, 1),
|
||||
"Must have WELL_PRODUCTIVITY_INDEX event at report step 1");
|
||||
}
|
||||
|
||||
|
||||
void cmp_vector(const std::vector<double>&v1, const std::vector<double>& v2) {
|
||||
BOOST_CHECK_EQUAL(v1.size(), v2.size());
|
||||
for (std::size_t i = 0; i < v1.size(); i++)
|
||||
BOOST_CHECK_CLOSE(v1[i], v2[i], 1e-4);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(VFPPROD_SCALING) {
|
||||
const auto deck = Parser{}.parseFile("VFP_CASE.DATA");
|
||||
const auto es = EclipseState{ deck };
|
||||
const auto sched = Schedule{ deck, es };
|
||||
const auto& vfp_table = sched.getVFPProdTable(1, 0);
|
||||
const std::vector<double> flo = { 0.000578704, 0.001157407, 0.002893519, 0.005787037, 0.008680556, 0.011574074, 0.017361111, 0.023148148, 0.034722222, 0.046296296};
|
||||
const std::vector<double> thp = {1300000.000000000, 2500000.000000000, 5000000.000000000, 7500000.000000000, 10000000.000000000};
|
||||
const std::vector<double> wfr = { 0.000000000, 0.100000000, 0.200000000, 0.300000000, 0.400000000, 0.500000000, 0.600000000, 0.700000000, 0.800000000, 0.990000000};
|
||||
const std::vector<double> gfr = {100.000000000, 200.000000000, 300.000000000, 400.000000000, 500.000000000, 750.000000000, 1000.000000000, 2000.000000000};
|
||||
const std::vector<double> alq = { 0.000000000, 0.000578704, 0.001157407, 0.001736111, 0.002314815};
|
||||
|
||||
cmp_vector(flo, vfp_table.getFloAxis());
|
||||
cmp_vector(thp, vfp_table.getTHPAxis());
|
||||
cmp_vector(wfr, vfp_table.getWFRAxis());
|
||||
cmp_vector(gfr, vfp_table.getGFRAxis());
|
||||
cmp_vector(alq, vfp_table.getALQAxis());
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
|
||||
#define BOOST_TEST_MODULE WellTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@ -493,13 +494,13 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
Opm::Well::WellProductionProperties properties(const std::string& input) {
|
||||
Opm::Well::WellProductionProperties properties(const std::string& input, std::optional<VFPProdTable::ALQ_TYPE> alq_type = {}) {
|
||||
Opm::Parser parser;
|
||||
Opm::UnitSystem unit_system(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC);
|
||||
auto deck = parser.parseString(input);
|
||||
const auto& record = deck.getKeyword("WCONHIST").getRecord(0);
|
||||
Opm::Well::WellProductionProperties hist(unit_system, "W");
|
||||
hist.handleWCONHIST(record);
|
||||
hist.handleWCONHIST(alq_type, unit_system, record);
|
||||
|
||||
|
||||
return hist;
|
||||
@ -545,14 +546,14 @@ namespace {
|
||||
}
|
||||
|
||||
Opm::UnitSystem unit_system(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC);
|
||||
Opm::Well::WellProductionProperties properties(const std::string& input)
|
||||
Opm::Well::WellProductionProperties properties(const std::string& input, std::optional<VFPProdTable::ALQ_TYPE> alq_type = {})
|
||||
{
|
||||
Opm::Parser parser;
|
||||
auto deck = parser.parseString(input);
|
||||
const auto& kwd = deck.getKeyword("WCONPROD");
|
||||
const auto& record = kwd.getRecord(0);
|
||||
Opm::Well::WellProductionProperties pred(unit_system, "W");
|
||||
pred.handleWCONPROD("WELL", record);
|
||||
pred.handleWCONPROD(alq_type, unit_system, "WELL", record);
|
||||
|
||||
return pred;
|
||||
}
|
||||
@ -657,7 +658,7 @@ BOOST_AUTO_TEST_CASE(WCH_Rates_NON_Defaulted_VFP)
|
||||
{
|
||||
Opm::SummaryState st(std::chrono::system_clock::now());
|
||||
const Opm::Well::WellProductionProperties& p =
|
||||
WCONHIST::properties(WCONHIST::all_defaulted_with_bhp_vfp_table());
|
||||
WCONHIST::properties(WCONHIST::all_defaulted_with_bhp_vfp_table(), VFPProdTable::ALQ_UNDEF);
|
||||
|
||||
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
||||
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
||||
@ -715,7 +716,7 @@ BOOST_AUTO_TEST_CASE(WCONPROD_ORAT_CMode)
|
||||
BOOST_AUTO_TEST_CASE(WCONPROD_THP_CMode)
|
||||
{
|
||||
const Opm::Well::WellProductionProperties& p =
|
||||
WCONPROD::properties(WCONPROD::thp_CMODE());
|
||||
WCONPROD::properties(WCONPROD::thp_CMODE(), VFPProdTable::ALQ_UNDEF);
|
||||
|
||||
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
||||
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
||||
@ -737,7 +738,7 @@ BOOST_AUTO_TEST_CASE(WCONPROD_THP_CMode)
|
||||
BOOST_AUTO_TEST_CASE(WCONPROD_BHP_CMode)
|
||||
{
|
||||
const Opm::Well::WellProductionProperties& p =
|
||||
WCONPROD::properties(WCONPROD::bhp_CMODE());
|
||||
WCONPROD::properties(WCONPROD::bhp_CMODE(), VFPProdTable::ALQ_UNDEF);
|
||||
|
||||
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
||||
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
||||
@ -1118,7 +1119,7 @@ DATES -- 2
|
||||
/
|
||||
|
||||
WCONPROD
|
||||
'P' 'OPEN' 'BHP' 1 2 3 2* 20. 10. 8 13 /
|
||||
'P' 'OPEN' 'BHP' 1 2 3 2* 20. 10. 0 13 /
|
||||
/
|
||||
|
||||
WCONINJE
|
||||
|
Loading…
Reference in New Issue
Block a user