Use UDAValue for rates and pressure limits in WCONPROD & WCONINJE

This commit is contained in:
Joakim Hove
2019-06-24 09:34:11 +02:00
parent a4eeb57a58
commit 6eea66a332
14 changed files with 321 additions and 223 deletions

View File

@@ -722,13 +722,19 @@ namespace Opm {
this->addWellEvent( well2->name(), ScheduleEvents::PRODUCTION_UPDATE, currentStep);
this->updateWell(well2, currentStep);
}
if ( !well2->getAllowCrossFlow() && (properties->OilRate + properties->WaterRate + properties->GasRate) == 0 ) {
std::string msg =
"Well " + well2->name() + " is a history matched well with zero rate where crossflow is banned. " +
"This well will be closed at " + std::to_string ( m_timeMap.getTimePassedUntil(currentStep) / (60*60*24) ) + " days";
OpmLog::note(msg);
updateWellStatus( well_name, currentStep, WellCommon::StatusEnum::SHUT );
if ( !well2->getAllowCrossFlow()) {
// The numerical content of the rate UDAValues is accessed unconditionally;
// since this is in history mode use of UDA values is not allowed anyway.
const auto& oil_rate = properties->OilRate;
const auto& water_rate = properties->WaterRate;
const auto& gas_rate = properties->GasRate;
if ((oil_rate.get<double>() + water_rate.get<double>() + gas_rate.get<double>()) == 0) {
std::string msg =
"Well " + well2->name() + " is a history matched well with zero rate where crossflow is banned. " +
"This well will be closed at " + std::to_string ( m_timeMap.getTimePassedUntil(currentStep) / (60*60*24) ) + " days";
OpmLog::note(msg);
updateWellStatus( well_name, currentStep, WellCommon::StatusEnum::SHUT );
}
}
}
}
@@ -866,14 +872,24 @@ namespace Opm {
// if the well has zero surface rate limit or reservior rate limit, while does not allow crossflow,
// it should be turned off.
if ( ! well2->getAllowCrossFlow()
&& ( (injection->hasInjectionControl(WellInjector::RATE) && injection->surfaceInjectionRate == 0)
|| (injection->hasInjectionControl(WellInjector::RESV) && injection->reservoirInjectionRate == 0) ) ) {
std::string msg =
"Well " + well_name + " is an injector with zero rate where crossflow is banned. " +
"This well will be closed at " + std::to_string ( m_timeMap.getTimePassedUntil(currentStep) / (60*60*24) ) + " days";
OpmLog::note(msg);
updateWellStatus( well_name, currentStep, WellCommon::StatusEnum::SHUT );
if ( ! well2->getAllowCrossFlow() ) {
std::string msg =
"Well " + well_name + " is an injector with zero rate where crossflow is banned. " +
"This well will be closed at " + std::to_string ( m_timeMap.getTimePassedUntil(currentStep) / (60*60*24) ) + " days";
if (injection->surfaceInjectionRate.is<double>()) {
if (injection->hasInjectionControl(WellInjector::RATE) && injection->surfaceInjectionRate.get<double>() == 0) {
OpmLog::note(msg);
updateWellStatus( well_name, currentStep, WellCommon::StatusEnum::SHUT );
}
}
if (injection->reservoirInjectionRate.is<double>()) {
if (injection->hasInjectionControl(WellInjector::RESV) && injection->reservoirInjectionRate.get<double>() == 0) {
OpmLog::note(msg);
updateWellStatus( well_name, currentStep, WellCommon::StatusEnum::SHUT );
}
}
}
}
}
@@ -913,7 +929,7 @@ namespace Opm {
this->addWellEvent( well_name, ScheduleEvents::INJECTION_UPDATE, currentStep);
}
if ( ! well2->getAllowCrossFlow() && (injection->surfaceInjectionRate == 0)) {
if ( ! well2->getAllowCrossFlow() && (injection->surfaceInjectionRate.get<double>() == 0)) {
std::string msg =
"Well " + well_name + " is an injector with zero rate where crossflow is banned. " +
"This well will be closed at " + std::to_string ( m_timeMap.getTimePassedUntil(currentStep) / (60*60*24) ) + " days";

View File

@@ -157,7 +157,7 @@ bool Well2::updateEconLimits(std::shared_ptr<WellEconProductionLimits> econ_limi
void Well2::switchToProducer() {
auto p = std::make_shared<WellInjectionProperties>(this->getInjectionProperties());
p->BHPLimit = 0;
p->BHPLimit.reset( 0 );
p->dropInjectionControl( Opm::WellInjector::BHP );
this->updateInjection( p );
this->updateProducer(true);
@@ -167,7 +167,8 @@ void Well2::switchToProducer() {
void Well2::switchToInjector() {
auto p = std::make_shared<WellProductionProperties>(getProductionProperties());
p->BHPLimit = 0;
p->BHPLimit.assert_numeric();
p->BHPLimit.reset(0);
p->dropProductionControl( Opm::WellProducer::BHP );
this->updateProduction( p );
this->updateProducer( false );
@@ -618,12 +619,27 @@ bool Well2::canOpen() const {
if (this->allow_cross_flow)
return true;
/*
If the UDAValue is in string mode we return true unconditionally, without
evaluating the internal UDA value.
*/
if (this->producer) {
const auto& prod = *this->production;
return (prod.WaterRate + prod.OilRate + prod.GasRate) != 0;
if (prod.OilRate.is<std::string>())
return true;
if (prod.GasRate.is<std::string>())
return true;
if (prod.WaterRate.is<std::string>())
return true;
return ((prod.OilRate.get<double>() + prod.GasRate.get<double>() + prod.WaterRate.get<double>()) != 0);
} else {
const auto& inj = *this->injection;
return inj.surfaceInjectionRate != 0;
if (inj.surfaceInjectionRate.is<std::string>())
return true;
return inj.surfaceInjectionRate.get<double>() != 0;
}
}
@@ -647,15 +663,15 @@ WellCompletion::CompletionOrderEnum Well2::getWellConnectionOrdering() const {
return this->ordering;
}
double Well2::production_rate(const SummaryState& st, Phase phase_arg) const {
double Well2::production_rate(const SummaryState& st, Phase phase) const {
if( !this->isProducer() ) return 0.0;
const auto& p = this->getProductionProperties();
const auto controls = this->productionControls(st);
switch( phase_arg ) {
case Phase::WATER: return p.WaterRate;
case Phase::OIL: return p.OilRate;
case Phase::GAS: return p.GasRate;
switch( phase ) {
case Phase::WATER: return controls.water_rate;
case Phase::OIL: return controls.oil_rate;
case Phase::GAS: return controls.gas_rate;
case Phase::SOLVENT:
throw std::invalid_argument( "Production of 'SOLVENT' requested." );
case Phase::POLYMER:
@@ -672,15 +688,15 @@ double Well2::production_rate(const SummaryState& st, Phase phase_arg) const {
double Well2::injection_rate(const SummaryState& st, Phase phase_arg) const {
if( !this->isInjector() ) return 0.0;
const auto controls = this->injectionControls(st);
const auto& i = this->getInjectionProperties();
const auto type = i.injectorType;
const auto type = controls.injector_type;
if( phase_arg == Phase::WATER && type != WellInjector::WATER ) return 0.0;
if( phase_arg == Phase::OIL && type != WellInjector::OIL ) return 0.0;
if( phase_arg == Phase::GAS && type != WellInjector::GAS ) return 0.0;
return i.surfaceInjectionRate;
return controls.surface_rate;
}

View File

@@ -33,17 +33,15 @@
namespace Opm {
WellInjectionProperties::WellInjectionProperties(const std::string& wname)
: name(wname),
injectorType(WellInjector::WATER),
controlMode(WellInjector::CMODE_UNDEFINED) {
surfaceInjectionRate=0.0;
reservoirInjectionRate=0.0;
WellInjectionProperties::WellInjectionProperties(const std::string& name)
: name(name),
injectorType(WellInjector::WATER),
controlMode(WellInjector::CMODE_UNDEFINED)
{
temperature=
Metric::TemperatureOffset
+ ParserKeywords::STCOND::TEMPERATURE::defaultValue;
BHPLimit=0.0;
THPLimit=0.0;
BHPH=0.0;
THPH=0.0;
VFPTableNumber=0;
@@ -57,21 +55,21 @@ namespace Opm {
this->predictionMode = true;
if (!record.getItem("RATE").defaultApplied(0)) {
this->surfaceInjectionRate = injection::rateToSI(record.getItem("RATE").get< double >(0) , this->injectorType, unit_system);
this->surfaceInjectionRate = record.getItem("RATE").get<UDAValue>(0);
this->addInjectionControl(WellInjector::RATE);
} else
this->dropInjectionControl(WellInjector::RATE);
if (!record.getItem("RESV").defaultApplied(0)) {
this->reservoirInjectionRate = record.getItem("RESV").getSIDouble(0);
this->reservoirInjectionRate = record.getItem("RESV").get<UDAValue>(0);
this->addInjectionControl(WellInjector::RESV);
} else
this->dropInjectionControl(WellInjector::RESV);
if (!record.getItem("THP").defaultApplied(0)) {
this->THPLimit = record.getItem("THP").getSIDouble(0);
this->THPLimit = record.getItem("THP").get<UDAValue>(0);
this->addInjectionControl(WellInjector::THP);
} else
this->dropInjectionControl(WellInjector::THP);
@@ -85,7 +83,7 @@ namespace Opm {
current behavoir agrees with the behovir of Eclipse when BHPLimit is not
specified while employed during group control.
*/
this->setBHPLimit(record.getItem("BHP").getSIDouble(0));
this->setBHPLimit(record.getItem("BHP").get<UDAValue>(0).get<double>());
// BHP control should always be there.
this->addInjectionControl(WellInjector::BHP);
@@ -108,37 +106,36 @@ namespace Opm {
void WellInjectionProperties::handleWELTARG(WellTarget::ControlModeEnum cmode, double newValue, double siFactorG, double siFactorL, double siFactorP) {
if (cmode == WellTarget::BHP){
this->BHPLimit = newValue * siFactorP;
this->BHPLimit.reset( newValue * siFactorP );
}
else if (cmode == WellTarget::ORAT){
if(this->injectorType == WellInjector::TypeEnum::OIL){
this->surfaceInjectionRate = newValue * siFactorL;
this->surfaceInjectionRate.reset( newValue * siFactorL );
}else{
std::invalid_argument("Well type must be OIL to set the oil rate");
}
}
else if (cmode == WellTarget::WRAT){
if(this->injectorType == WellInjector::TypeEnum::WATER){
this->surfaceInjectionRate = newValue * siFactorL;
}else{
if(this->injectorType == WellInjector::TypeEnum::WATER)
this->surfaceInjectionRate.reset( newValue * siFactorL );
else
std::invalid_argument("Well type must be WATER to set the water rate");
}
}
else if (cmode == WellTarget::GRAT){
if(this->injectorType == WellInjector::TypeEnum::GAS){
this->surfaceInjectionRate = newValue * siFactorG;
this->surfaceInjectionRate.reset( newValue * siFactorG );
}else{
std::invalid_argument("Well type must be GAS to set the gas rate");
}
}
else if (cmode == WellTarget::THP){
this->THPLimit = newValue * siFactorP;
this->THPLimit.reset( newValue * siFactorP );
}
else if (cmode == WellTarget::VFP){
this->VFPTableNumber = static_cast<int> (newValue);
}
else if (cmode == WellTarget::RESV){
this->reservoirInjectionRate = newValue * siFactorL;
this->reservoirInjectionRate.reset( newValue * siFactorL );
}
else if (cmode != WellTarget::GUID){
throw std::invalid_argument("Invalid keyword (MODE) supplied");
@@ -154,11 +151,11 @@ namespace Opm {
throw std::invalid_argument(msg);
}
this->injectorType = WellInjector::TypeFromString( typeItem.getTrimmedString(0));
double injectionRate = record.getItem("RATE").get< double >(0);
injectionRate = injection::rateToSI(injectionRate, this->injectorType, unit_system);
if (!record.getItem("RATE").defaultApplied(0))
this->surfaceInjectionRate = injectionRate;
if (!record.getItem("RATE").defaultApplied(0)) {
double injectionRate = record.getItem("RATE").get<double>(0);
this->surfaceInjectionRate.reset( injectionRate );
}
if ( record.getItem( "BHP" ).hasValue(0) )
this->BHPH = record.getItem("BHP").getSIDouble(0);
if ( record.getItem( "THP" ).hasValue(0) )
@@ -223,11 +220,11 @@ namespace Opm {
void WellInjectionProperties::resetDefaultHistoricalBHPLimit() {
// this default BHP value is from simulation result,
// without finding any related document
BHPLimit = 6891.2 * unit::barsa;
BHPLimit.reset( 6891.2 * unit::barsa );
}
void WellInjectionProperties::setBHPLimit(const double limit) {
BHPLimit = limit;
BHPLimit.reset( limit );
}
std::ostream& operator<<( std::ostream& stream,
@@ -252,10 +249,11 @@ namespace Opm {
InjectionControls WellInjectionProperties::controls(const UnitSystem& unit_system, const SummaryState& st, double udq_default) const {
InjectionControls controls(this->injectionControls);
controls.surface_rate = this->surfaceInjectionRate;
controls.reservoir_rate = this->reservoirInjectionRate;
controls.bhp_limit = this->BHPLimit;
controls.thp_limit = this->THPLimit;
controls.surface_rate = UDA::eval_well_uda_rate(this->surfaceInjectionRate, this->name, st, udq_default, this->injectorType, unit_system);
controls.reservoir_rate = UDA::eval_well_uda(this->reservoirInjectionRate, this->name, st, udq_default);
controls.bhp_limit = UDA::eval_well_uda(this->BHPLimit, this->name, st, udq_default);
controls.thp_limit = UDA::eval_well_uda(this->THPLimit, this->name, st, udq_default);
controls.temperature = this->temperature;
controls.injector_type = this->injectorType;
controls.cmode = this->controlMode;

View File

@@ -22,6 +22,7 @@
#include <iosfwd>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/InjectionControls.hpp>
@@ -33,11 +34,11 @@ namespace Opm {
struct WellInjectionProperties {
std::string name;
double surfaceInjectionRate;
double reservoirInjectionRate;
UDAValue surfaceInjectionRate;
UDAValue reservoirInjectionRate;
UDAValue BHPLimit;
UDAValue THPLimit;
double temperature;
double BHPLimit;
double THPLimit;
double BHPH;
double THPH;
int VFPTableNumber;

View File

@@ -40,9 +40,9 @@ namespace Opm {
void WellProductionProperties::init_rates( const DeckRecord& record ) {
this->OilRate = record.getItem("ORAT").getSIDouble(0);
this->WaterRate = record.getItem("WRAT").getSIDouble(0);
this->GasRate = record.getItem("GRAT").getSIDouble(0);
this->OilRate = record.getItem("ORAT").get<UDAValue>(0);
this->WaterRate = record.getItem("WRAT").get<UDAValue>(0);
this->GasRate = record.getItem("GRAT").get<UDAValue>(0);
}
@@ -50,12 +50,12 @@ namespace Opm {
{
this->predictionMode = false;
// update LiquidRate
this->LiquidRate = this->WaterRate + this->OilRate;
this->LiquidRate = UDAValue(this->WaterRate.get<double>() + this->OilRate.get<double>());
if ( record.getItem( "BHP" ).hasValue(0) )
this->BHPH = record.getItem("BHP").getSIDouble(0);
this->BHPH = record.getItem("BHP").get<UDAValue>(0).get<double>();
if ( record.getItem( "THP" ).hasValue(0) )
this->THPH = record.getItem("THP").getSIDouble(0);
this->THPH = record.getItem("THP").get<UDAValue>(0).get<double>();
const auto& cmodeItem = record.getItem("CMODE");
if ( cmodeItem.defaultApplied(0) ) {
@@ -106,11 +106,11 @@ namespace Opm {
{
this->predictionMode = true;
this->BHPLimit = record.getItem("BHP" ).getSIDouble(0);
this->THPLimit = record.getItem("THP" ).getSIDouble(0);
this->ALQValue = record.getItem("ALQ" ).get< double >(0); //NOTE: Unit of ALQ is never touched
this->BHPLimit = record.getItem("BHP").get<UDAValue>(0);
this->THPLimit = 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").getSIDouble(0);
this->LiquidRate = record.getItem("LRAT").get<UDAValue>(0);
this->ResVRate = record.getItem("RESV").get<UDAValue>(0);
namespace wp = WellProducer;
@@ -127,7 +127,7 @@ namespace Opm {
if( !record.getItem( cmode.first ).defaultApplied( 0 ) ) {
// a zero value THP limit will not be handled as a THP limit
if (cmode.first == "THP" && this->THPLimit == 0.)
if (cmode.first == "THP" && this->THPLimit.get<double>() == 0.)
continue;
this->addProductionControl( cmode.second );
@@ -157,7 +157,7 @@ namespace Opm {
void WellProductionProperties::handleWCONHIST(const DeckRecord& record)
{
this->init_rates(record);
this->LiquidRate = 0;
this->LiquidRate.reset(0);
this->ResVRate.reset(0);
// when the well is switching to history matching producer from prediction mode
@@ -177,33 +177,37 @@ namespace Opm {
void WellProductionProperties::handleWELTARG(WellTarget::ControlModeEnum cmode, double newValue, double siFactorG, double siFactorL, double siFactorP) {
if (cmode == WellTarget::ORAT){
this->OilRate = newValue * siFactorL;
this->OilRate.assert_numeric("Can not combine UDA and WELTARG");
this->OilRate.reset( newValue * siFactorL );
}
else if (cmode == WellTarget::WRAT){
this->WaterRate = newValue * siFactorL;
this->WaterRate.assert_numeric("Can not combine UDA and WELTARG");
this->WaterRate.reset( newValue * siFactorL );
}
else if (cmode == WellTarget::GRAT){
this->GasRate = newValue * siFactorG;
this->GasRate.assert_numeric("Can not combine UDA and WELTARG");
this->GasRate.reset( newValue * siFactorG );
}
else if (cmode == WellTarget::LRAT){
this->LiquidRate = newValue * siFactorL;
this->LiquidRate.assert_numeric("Can not combine UDA and WELTARG");
this->LiquidRate.reset( newValue * siFactorL );
}
else if (cmode == WellTarget::RESV){
this->ResVRate.assert_numeric("Can not combine UDA and WELTARG");
this->ResVRate.reset( newValue * siFactorL );
}
else if (cmode == WellTarget::BHP){
this->BHPLimit = newValue * siFactorP;
this->BHPLimit.assert_numeric("Can not combine UDA and WELTARG");
this->BHPLimit.reset( newValue * siFactorP );
}
else if (cmode == WellTarget::THP){
this->THPLimit = newValue * siFactorP;
this->THPLimit.assert_numeric("Can not combine UDA and WELTARG");
this->THPLimit.reset(newValue * siFactorP);
}
else if (cmode == WellTarget::VFP){
else if (cmode == WellTarget::VFP)
this->VFPTableNumber = static_cast<int> (newValue);
}
else if (cmode != WellTarget::GUID){
else if (cmode != WellTarget::GUID)
throw std::invalid_argument("Invalid keyword (MODE) supplied");
}
}
@@ -257,7 +261,7 @@ namespace Opm {
}
void WellProductionProperties::resetDefaultBHPLimit() {
BHPLimit = 1. * unit::atm;
BHPLimit = UDAValue( 1. * unit::atm );
}
void WellProductionProperties::clearControls() {
@@ -265,24 +269,25 @@ namespace Opm {
}
void WellProductionProperties::setBHPLimit(const double limit) {
BHPLimit = limit;
BHPLimit = UDAValue( limit );
}
double WellProductionProperties::getBHPLimit() const {
return BHPLimit;
return BHPLimit.get<double>();
}
ProductionControls WellProductionProperties::controls(const SummaryState& st, double udq_undefined) const {
ProductionControls controls(this->m_productionControls);
controls.oil_rate = this->OilRate;
controls.water_rate = this->WaterRate;
controls.gas_rate = this->GasRate;
controls.liquid_rate = this->LiquidRate;
controls.bhp_limit = this->BHPLimit;
controls.thp_limit= this->THPLimit;
controls.oil_rate = UDA::eval_well_uda(this->OilRate, this->name, st, udq_undefined);
controls.water_rate = UDA::eval_well_uda(this->WaterRate, this->name, st, udq_undefined);
controls.gas_rate = UDA::eval_well_uda(this->GasRate, this->name, st, udq_undefined);
controls.liquid_rate = UDA::eval_well_uda(this->LiquidRate, this->name, st, udq_undefined);
controls.resv_rate = UDA::eval_well_uda(this->ResVRate, this->name, st, udq_undefined);
controls.bhp_limit = UDA::eval_well_uda(this->BHPLimit, this->name, st, udq_undefined);
controls.thp_limit= UDA::eval_well_uda(this->THPLimit, this->name, st, udq_undefined);
controls.bhp_history = this->BHPH;
controls.thp_history = this->THPH;
controls.vfp_table_number = this->VFPTableNumber;

View File

@@ -38,14 +38,14 @@ namespace Opm {
// the rates serve as limits under prediction mode
// while they are observed rates under historical mode
std::string name;
double OilRate = 0.0;
double WaterRate = 0.0;
double GasRate = 0.0;
double LiquidRate = 0.0;
UDAValue OilRate;
UDAValue WaterRate;
UDAValue GasRate;
UDAValue LiquidRate;
UDAValue ResVRate;
// BHP and THP limit
double BHPLimit = 0.0;
double THPLimit = 0.0;
UDAValue BHPLimit;
UDAValue THPLimit;
// historical BHP and THP under historical mode
double BHPH = 0.0;
double THPH = 0.0;

View File

@@ -2,11 +2,11 @@
[{"name" : "WELL" , "value_type" : "STRING"},
{"name" : "STATUS" , "value_type" : "STRING" , "default" : "OPEN"},
{"name" : "CMODE" , "value_type" : "STRING"},
{"name" : "ORAT" , "value_type" : "DOUBLE", "default" : 0.0, "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "WRAT" , "value_type" : "DOUBLE" , "default" : 0.0, "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "GRAT" , "value_type" : "DOUBLE" , "default" : 0.0, "dimension" : "GasSurfaceVolume/Time"},
{"name" : "ORAT" , "value_type" : "UDA", "default" : 0.0, "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "WRAT" , "value_type" : "UDA" , "default" : 0.0, "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "GRAT" , "value_type" : "UDA" , "default" : 0.0, "dimension" : "GasSurfaceVolume/Time"},
{"name" : "VFPTable" , "value_type" : "INT" , "default" : 0, "comment":"The default is a state variable"},
{"name" : "Lift" , "value_type" : "DOUBLE" , "default" : 0.0 , "comment":"The default is a state variable"},
{"name" : "THP" , "value_type" : "DOUBLE" , "default" : 0.0 , "dimension" : "Pressure"},
{"name" : "BHP" , "value_type" : "DOUBLE" , "default" : 0.0 ,"dimension" : "Pressure"},
{"name" : "THP" , "value_type" : "UDA" , "default" : 0.0 , "dimension" : "Pressure"},
{"name" : "BHP" , "value_type" : "UDA" , "default" : 0.0 ,"dimension" : "Pressure"},
{"name" : "NGLRAT" , "value_type" : "DOUBLE" , "default" : 0.0 ,"dimension" : "LiquidSurfaceVolume/Time"}]}

View File

@@ -3,10 +3,10 @@
{"name" : "TYPE" , "value_type" : "STRING" },
{"name" : "STATUS" , "value_type" : "STRING" , "default" : "OPEN"},
{"name" : "CMODE" , "value_type" : "STRING" },
{"name" : "RATE" , "value_type" : "DOUBLE" , "dimension" : "ContextDependent"},
{"name" : "RESV" , "value_type" : "DOUBLE" , "dimension" : "ReservoirVolume/Time"},
{"name" : "BHP" , "value_type" : "DOUBLE" , "dimension" : "Pressure" , "default" : 6895},
{"name" : "THP" , "value_type" : "DOUBLE" , "dimension" : "Pressure"},
{"name" : "RATE" , "value_type" : "UDA"},
{"name" : "RESV" , "value_type" : "UDA" , "dimension" : "ReservoirVolume/Time"},
{"name" : "BHP" , "value_type" : "UDA" , "dimension" : "Pressure" , "default" : 6895},
{"name" : "THP" , "value_type" : "UDA" , "dimension" : "Pressure"},
{"name" : "VFP_TABLE" , "value_type" : "INT" , "default" : 0},
{"name" : "VAPOIL_C" , "value_type" : "DOUBLE" , "default" : 0},
{"name" : "GAS_STEAM_RATIO" , "value_type" : "DOUBLE" , "default" : 0},

View File

@@ -2,13 +2,13 @@
[{"name" : "WELL" , "value_type" : "STRING"},
{"name" : "STATUS" , "value_type" : "STRING" , "default" : "OPEN"},
{"name" : "CMODE" , "value_type" : "STRING"},
{"name" : "ORAT" , "value_type" : "DOUBLE", "default" : 0.0 , "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "WRAT" , "value_type" : "DOUBLE" , "default" : 0.0 , "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "GRAT" , "value_type" : "DOUBLE" , "default" : 0.0 , "dimension" : "GasSurfaceVolume/Time"},
{"name" : "LRAT" , "value_type" : "DOUBLE" , "default" : 0.0 , "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "ORAT" , "value_type" : "UDA", "default" : 0.0 , "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "WRAT" , "value_type" : "UDA" , "default" : 0.0 , "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "GRAT" , "value_type" : "UDA" , "default" : 0.0 , "dimension" : "GasSurfaceVolume/Time"},
{"name" : "LRAT" , "value_type" : "UDA" , "default" : 0.0 , "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "RESV" , "value_type" : "UDA" , "default" : 0.0 , "dimension" : "LiquidSurfaceVolume/Time"},
{"name" : "BHP" , "value_type" : "DOUBLE" , "default" : 1.01325 , "dimension" : "Pressure"},
{"name" : "THP" , "value_type" : "DOUBLE" , "default" : 0.0 , "dimension" : "Pressure"},
{"name" : "BHP" , "value_type" : "UDA" , "default" : 1.01325 , "dimension" : "Pressure"},
{"name" : "THP" , "value_type" : "UDA" , "default" : 0.0 , "dimension" : "Pressure"},
{"name" : "VFP_TABLE" , "value_type" : "INT" , "default" : 0 },
{"name" : "ALQ" , "value_type" : "DOUBLE" , "default" : 0.0 },
{"name" : "E300_ITEM13" , "value_type" : "DOUBLE"},

View File

@@ -108,6 +108,18 @@ double prod_wpr_P4(const EclipseState& es, const Schedule& /* sched */, const S
return -units.to_si(UnitSystem::measure::rate, water_rate);
}
double inj_wir_INJ(const EclipseState& es, const Schedule& sched, const SummaryState& st, const data::Solution& /* sol */, size_t report_step, double /* seconds_elapsed */) {
printf("report_step:%ld Has FUINJ: %d \n", report_step, st.has("FUINJ"));
if (st.has("FUINJ")) {
const auto& well = sched.getWell2("INJ", report_step);
const auto controls = well.injectionControls(st);
printf("st[FUINJ] = %lg \n", st.get("FUINJ"));
return controls.surface_rate;
} else
return -99;
}
/*
The deck tested here has a UDQ DEFINE statement which sorts the wells after
oil production rate, and then subsequently closes the well with lowest OPR
@@ -295,3 +307,40 @@ BOOST_AUTO_TEST_CASE(UDQ_WUWCT) {
test_work_area_free(work_area);
}
}
BOOST_AUTO_TEST_CASE(UDA) {
#include "uda.include"
test_data td( uda_deck );
msim sim(td.state);
EclipseIO io(td.state, td.state.getInputGrid(), td.schedule, td.summary_config);
sim.well_rate("P1", data::Rates::opt::wat, prod_wpr_P1);
sim.well_rate("P2", data::Rates::opt::wat, prod_wpr_P2);
sim.well_rate("P3", data::Rates::opt::wat, prod_wpr_P3);
sim.well_rate("P4", data::Rates::opt::wat, prod_wpr_P4);
sim.well_rate("INJ", data::Rates::opt::wat, inj_wir_INJ);
{
ecl::util::TestArea ta("uda_sim");
sim.run(td.schedule, io, true);
const auto& base_name = td.state.getIOConfig().getBaseName();
ecl_sum_type * ecl_sum = ecl_sum_fread_alloc_case( base_name.c_str(), ":");
// Should only get at report steps
for (int report_step = 2; report_step < ecl_sum_get_last_report_step(ecl_sum); report_step++) {
double wwpr_sum = 0;
{
int prev_tstep = ecl_sum_iget_report_end(ecl_sum, report_step - 1);
for (const auto& well : {"P1", "P2", "P3", "P4"}) {
std::string wwpr_key = std::string("WWPR:") + well;
wwpr_sum += ecl_sum_get_general_var(ecl_sum, prev_tstep, wwpr_key.c_str());
}
}
BOOST_CHECK_CLOSE( 0.90 * wwpr_sum, ecl_sum_get_general_var(ecl_sum, ecl_sum_iget_report_end(ecl_sum, report_step), "WWIR:INJ"), 1e-3);
}
ecl_sum_free( ecl_sum );
}
}

View File

@@ -994,17 +994,17 @@ BOOST_AUTO_TEST_CASE(createDeckWithWeltArg) {
const auto& well_1 = schedule.getWell2("OP_1", 1);
const auto wpp_1 = well_1.getProductionProperties();
BOOST_CHECK_EQUAL(wpp_1.WaterRate, 0);
BOOST_CHECK_EQUAL(wpp_1.WaterRate.get<double>(), 0);
const auto& well_2 = schedule.getWell2("OP_1", 2);
const auto wpp_2 = well_2.getProductionProperties();
BOOST_CHECK_EQUAL(wpp_2.OilRate, 1300 * siFactorL);
BOOST_CHECK_EQUAL(wpp_2.WaterRate, 1400 * siFactorL);
BOOST_CHECK_EQUAL(wpp_2.GasRate, 1500.52 * siFactorG);
BOOST_CHECK_EQUAL(wpp_2.LiquidRate, 1600.58 * siFactorL);
BOOST_CHECK_EQUAL(wpp_2.BHPLimit, 1900 * siFactorP);
BOOST_CHECK_EQUAL(wpp_2.THPLimit, 2000 * siFactorP);
BOOST_CHECK_EQUAL(wpp_2.OilRate.get<double>(), 1300 * siFactorL);
BOOST_CHECK_EQUAL(wpp_2.WaterRate.get<double>(), 1400 * siFactorL);
BOOST_CHECK_EQUAL(wpp_2.GasRate.get<double>(), 1500.52 * siFactorG);
BOOST_CHECK_EQUAL(wpp_2.LiquidRate.get<double>(), 1600.58 * siFactorL);
BOOST_CHECK_EQUAL(wpp_2.ResVRate.get<double>(), 1801.05 * siFactorL);
BOOST_CHECK_EQUAL(wpp_2.BHPLimit.get<double>(), 1900 * siFactorP);
BOOST_CHECK_EQUAL(wpp_2.THPLimit.get<double>(), 2000 * siFactorP);
BOOST_CHECK_EQUAL(wpp_2.VFPTableNumber, 2100);
BOOST_CHECK_EQUAL(well_2.getGuideRate(), 2300.14);
}
@@ -1416,21 +1416,21 @@ BOOST_AUTO_TEST_CASE(changeBhpLimitInHistoryModeWithWeltarg) {
Schedule sched(deck, grid , eclipseProperties, runspec);
// The BHP limit should not be effected by WCONHIST
BOOST_CHECK_EQUAL(sched.getWell2("P", 1).getProductionProperties().BHPLimit, 50 * 1e5); // 1
BOOST_CHECK_EQUAL(sched.getWell2("P", 2).getProductionProperties().BHPLimit, 50 * 1e5); // 2
BOOST_CHECK_EQUAL(sched.getWell2("P", 1).getProductionProperties().BHPLimit.get<double>(), 50 * 1e5); // 1
BOOST_CHECK_EQUAL(sched.getWell2("P", 2).getProductionProperties().BHPLimit.get<double>(), 50 * 1e5); // 2
BOOST_CHECK_EQUAL(sched.getWell2("I", 1).getInjectionProperties().BHPLimit, 600 * 1e5); // 1
BOOST_CHECK_EQUAL(sched.getWell2("I", 2).getInjectionProperties().BHPLimit, 600 * 1e5); // 2
BOOST_CHECK_EQUAL(sched.getWell2("I", 1).getInjectionProperties().BHPLimit.get<double>(), 600 * 1e5); // 1
BOOST_CHECK_EQUAL(sched.getWell2("I", 2).getInjectionProperties().BHPLimit.get<double>(), 600 * 1e5); // 2
BOOST_CHECK_EQUAL(sched.getWell2("I", 2).getInjectionProperties().hasInjectionControl(Opm::WellInjector::BHP), true);
// The well is producer for timestep 3 and the injection properties BHPLimit should be set to zero.
BOOST_CHECK(sched.getWell2("I", 3).isProducer());
BOOST_CHECK_EQUAL(sched.getWell2("I", 3).getInjectionProperties().BHPLimit, 0); // 3
BOOST_CHECK_EQUAL(sched.getWell2("I", 3).getInjectionProperties().BHPLimit.get<double>(), 0); // 3
BOOST_CHECK_EQUAL(sched.getWell2("I", 3).getProductionProperties().hasProductionControl(Opm::WellProducer::BHP), true );
BOOST_CHECK_EQUAL(sched.getWell2("I", 4).getInjectionProperties().hasInjectionControl(Opm::WellInjector::BHP), true );
BOOST_CHECK_EQUAL(sched.getWell2("I", 4).getInjectionProperties().BHPLimit, 6891.2 * 1e5); // 4
BOOST_CHECK_EQUAL(sched.getWell2("I", 4).getInjectionProperties().BHPLimit.get<double>(), 6891.2 * 1e5); // 4
}
BOOST_AUTO_TEST_CASE(changeModeWithWHISTCTL) {

View File

@@ -206,22 +206,21 @@ BOOST_AUTO_TEST_CASE(isProducerCorrectlySet) {
/* Set a surface injection rate => Well becomes an Injector */
auto injectionProps1 = std::make_shared<Opm::WellInjectionProperties>(well.getInjectionProperties());
injectionProps1->surfaceInjectionRate = 100;
injectionProps1->surfaceInjectionRate.reset(100);
well.updateInjection(injectionProps1);
BOOST_CHECK_EQUAL( true , well.isInjector());
BOOST_CHECK_EQUAL( false , well.isProducer());
BOOST_CHECK_EQUAL( 100 , well.getInjectionProperties().surfaceInjectionRate);
BOOST_CHECK_EQUAL( 100 , well.getInjectionProperties().surfaceInjectionRate.get<double>());
{
Opm::Well2 well("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::Phase::OIL, Opm::WellProducer::CMODE_UNDEFINED, WellCompletion::DEPTH, UnitSystem::newMETRIC(), 0);
/* Set a reservoir injection rate => Well becomes an Injector */
auto injectionProps2 = std::make_shared<Opm::WellInjectionProperties>(well.getInjectionProperties());
injectionProps2->reservoirInjectionRate = 200;
injectionProps2->reservoirInjectionRate.reset(200);
well.updateInjection(injectionProps2);
BOOST_CHECK_EQUAL( true , well.isInjector());
BOOST_CHECK_EQUAL( false , well.isProducer());
BOOST_CHECK_EQUAL( 200 , well.getInjectionProperties().reservoirInjectionRate);
BOOST_CHECK_EQUAL( 200 , well.getInjectionProperties().reservoirInjectionRate.get<double>());
}
{
@@ -232,18 +231,18 @@ BOOST_AUTO_TEST_CASE(isProducerCorrectlySet) {
well.updateInjection(injectionProps3);
auto properties = std::make_shared<Opm::WellProductionProperties>( well.getProductionProperties() );
properties->OilRate = 100;
properties->GasRate = 200;
properties->WaterRate = 300;
properties->OilRate.reset(100);
properties->GasRate.reset(200);
properties->WaterRate.reset(300);
well.updateProduction(properties);
BOOST_CHECK_EQUAL( false , well.isInjector());
BOOST_CHECK_EQUAL( true , well.isProducer());
BOOST_CHECK_EQUAL( 0 , well.getInjectionProperties().surfaceInjectionRate);
BOOST_CHECK_EQUAL( 0 , well.getInjectionProperties().reservoirInjectionRate);
BOOST_CHECK_EQUAL( 100 , well.getProductionProperties().OilRate);
BOOST_CHECK_EQUAL( 200 , well.getProductionProperties().GasRate);
BOOST_CHECK_EQUAL( 300 , well.getProductionProperties().WaterRate);
BOOST_CHECK_EQUAL( 0 , well.getInjectionProperties().surfaceInjectionRate.get<double>());
BOOST_CHECK_EQUAL( 0 , well.getInjectionProperties().reservoirInjectionRate.get<double>());
BOOST_CHECK_EQUAL( 100 , well.getProductionProperties().OilRate.get<double>());
BOOST_CHECK_EQUAL( 200 , well.getProductionProperties().GasRate.get<double>());
BOOST_CHECK_EQUAL( 300 , well.getProductionProperties().WaterRate.get<double>());
}
}
@@ -271,16 +270,16 @@ BOOST_AUTO_TEST_CASE(XHPLimitDefault) {
auto productionProps = std::make_shared<Opm::WellProductionProperties>(well.getProductionProperties());
productionProps->BHPLimit = 100;
productionProps->BHPLimit.reset(100);
productionProps->addProductionControl(Opm::WellProducer::BHP);
well.updateProduction(productionProps);
BOOST_CHECK_EQUAL( 100 , well.getProductionProperties().BHPLimit);
BOOST_CHECK_EQUAL( 100 , well.getProductionProperties().BHPLimit.get<double>());
BOOST_CHECK_EQUAL( true, well.getProductionProperties().hasProductionControl( Opm::WellProducer::BHP ));
auto injProps = std::make_shared<Opm::WellInjectionProperties>(well.getInjectionProperties());
injProps->THPLimit = 200;
injProps->THPLimit.reset(200);
well.updateInjection(injProps);
BOOST_CHECK_EQUAL( 200 , well.getInjectionProperties().THPLimit);
BOOST_CHECK_EQUAL( 200 , well.getInjectionProperties().THPLimit.get<double>());
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::WellInjector::THP ));
}
@@ -292,7 +291,7 @@ BOOST_AUTO_TEST_CASE(InjectorType) {
auto injectionProps = std::make_shared<Opm::WellInjectionProperties>(well.getInjectionProperties());
injectionProps->injectorType = Opm::WellInjector::WATER;
well.updateInjection(injectionProps);
// TODO: Should we test for something other than water here, as long as
// TODO: Should we test for something other than wate here, as long as
// the default value for InjectorType is WellInjector::WATER?
BOOST_CHECK_EQUAL( Opm::WellInjector::WATER , well.getInjectionProperties().injectorType);
}
@@ -310,7 +309,7 @@ BOOST_AUTO_TEST_CASE(WellHaveProductionControlLimit) {
BOOST_CHECK( !well.getProductionProperties().hasProductionControl( Opm::WellProducer::RESV ));
auto properties1 = std::make_shared<Opm::WellProductionProperties>(well.getProductionProperties());
properties1->OilRate = 100;
properties1->OilRate.reset(100);
properties1->addProductionControl(Opm::WellProducer::ORAT);
well.updateProduction(properties1);
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::WellProducer::ORAT ));
@@ -323,13 +322,13 @@ BOOST_AUTO_TEST_CASE(WellHaveProductionControlLimit) {
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::WellProducer::RESV ));
auto properties3 = std::make_shared<Opm::WellProductionProperties>(well.getProductionProperties());
properties3->OilRate = 100;
properties3->WaterRate = 100;
properties3->GasRate = 100;
properties3->LiquidRate = 100;
properties3->BHPLimit = 100;
properties3->THPLimit = 100;
properties3->OilRate.reset(100);
properties3->WaterRate.reset(100);
properties3->GasRate.reset(100);
properties3->LiquidRate.reset(100);
properties3->ResVRate.reset(100);
properties3->BHPLimit.reset(100);
properties3->THPLimit.reset(100);
properties3->addProductionControl(Opm::WellProducer::ORAT);
properties3->addProductionControl(Opm::WellProducer::LRAT);
properties3->addProductionControl(Opm::WellProducer::BHP);
@@ -356,22 +355,22 @@ BOOST_AUTO_TEST_CASE(WellHaveInjectionControlLimit) {
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::WellInjector::RESV ));
auto injProps1 = std::make_shared<Opm::WellInjectionProperties>(well.getInjectionProperties());
injProps1->surfaceInjectionRate = 100;
injProps1->surfaceInjectionRate.reset(100);
injProps1->addInjectionControl(Opm::WellInjector::RATE);
well.updateInjection(injProps1);
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::WellInjector::RATE ));
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::WellInjector::RESV ));
auto injProps2 = std::make_shared<Opm::WellInjectionProperties>(well.getInjectionProperties());
injProps2->reservoirInjectionRate = 100;
injProps2->reservoirInjectionRate.reset(100);
injProps2->addInjectionControl(Opm::WellInjector::RESV);
well.updateInjection(injProps2);
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::WellInjector::RESV ));
auto injProps3 = std::make_shared<Opm::WellInjectionProperties>(well.getInjectionProperties());
injProps3->BHPLimit = 100;
injProps3->BHPLimit.reset(100);
injProps3->addInjectionControl(Opm::WellInjector::BHP);
injProps3->THPLimit = 100;
injProps3->THPLimit.reset(100);
injProps3->addInjectionControl(Opm::WellInjector::THP);
well.updateInjection(injProps3);
@@ -535,8 +534,7 @@ namespace {
}
Opm::WellProductionProperties
properties(const std::string& input)
Opm::WellProductionProperties properties(const std::string& input)
{
Opm::Parser parser;
auto deck = parser.parseString(input);
@@ -565,7 +563,7 @@ BOOST_AUTO_TEST_CASE(WCH_All_Specified_BHP_Defaulted)
BOOST_CHECK_EQUAL(p.controlMode , Opm::WellProducer::ORAT);
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_ORAT_Defaulted_BHP_Defaulted)
@@ -581,7 +579,7 @@ BOOST_AUTO_TEST_CASE(WCH_ORAT_Defaulted_BHP_Defaulted)
BOOST_CHECK_EQUAL(p.controlMode , Opm::WellProducer::WRAT);
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_OWRAT_Defaulted_BHP_Defaulted)
@@ -597,7 +595,7 @@ BOOST_AUTO_TEST_CASE(WCH_OWRAT_Defaulted_BHP_Defaulted)
BOOST_CHECK_EQUAL(p.controlMode , Opm::WellProducer::GRAT);
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Defaulted)
@@ -613,7 +611,7 @@ BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Defaulted)
BOOST_CHECK_EQUAL(p.controlMode , Opm::WellProducer::LRAT);
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Specified)
@@ -630,7 +628,7 @@ BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Specified)
BOOST_CHECK_EQUAL(p.controlMode , Opm::WellProducer::RESV);
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_Rates_NON_Defaulted_VFP)
@@ -649,7 +647,7 @@ BOOST_AUTO_TEST_CASE(WCH_Rates_NON_Defaulted_VFP)
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.VFPTableNumber, 3);
BOOST_CHECK_EQUAL(p.ALQValue, 10.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_BHP_Specified)
@@ -667,7 +665,7 @@ BOOST_AUTO_TEST_CASE(WCH_BHP_Specified)
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.BHPLimit, 5.e7); // 500 barsa
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 5.e7); // 500 barsa
}
BOOST_AUTO_TEST_CASE(WCONPROD_ORAT_CMode)
@@ -707,8 +705,8 @@ BOOST_AUTO_TEST_CASE(WCONPROD_THP_CMode)
BOOST_CHECK_EQUAL(p.VFPTableNumber, 8);
BOOST_CHECK_EQUAL(p.ALQValue, 13.);
BOOST_CHECK_EQUAL(p.THPLimit, 1000000.); // 10 barsa
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.); // 1 atm.
BOOST_CHECK_EQUAL(p.THPLimit.get<double>(), 1000000.); // 10 barsa
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 101325.); // 1 atm.
}
BOOST_AUTO_TEST_CASE(WCONPROD_BHP_CMode)
@@ -729,8 +727,8 @@ BOOST_AUTO_TEST_CASE(WCONPROD_BHP_CMode)
BOOST_CHECK_EQUAL(p.VFPTableNumber, 8);
BOOST_CHECK_EQUAL(p.ALQValue, 13.);
BOOST_CHECK_EQUAL(p.THPLimit, 1000000.); // 10 barsa
BOOST_CHECK_EQUAL(p.BHPLimit, 2000000.); // 20 barsa
BOOST_CHECK_EQUAL(p.THPLimit.get<double>(), 1000000.); // 10 barsa
BOOST_CHECK_EQUAL(p.BHPLimit.get<double>(), 2000000.); // 20 barsa
}
@@ -756,8 +754,22 @@ BOOST_AUTO_TEST_CASE(CMODE_DEFAULT) {
BOOST_AUTO_TEST_CASE(WELL_CONTROLS) {
Opm::Well2 well("WELL", "GROUP", 0, 0, 0, 0, 1000, Opm::Phase::OIL, Opm::WellProducer::CMODE_UNDEFINED, Opm::WellCompletion::DEPTH, UnitSystem::newMETRIC(), 0);
Opm::WellProductionProperties prod("OP1");
Opm::SummaryState st;
well.productionControls(st);
// Use a scalar FIELD variable - that should work; although it is a bit weird.
st.update("FUX", 1);
prod.OilRate = UDAValue("FUX");
BOOST_CHECK_EQUAL(1, prod.controls(st, 0).oil_rate);
// Use the wellrate WUX for well OP1; the well is now added with
// SummaryState::update_well_var() and we should automatically fetch the
// correct well value.
prod.OilRate = UDAValue("WUX");
st.update_well_var("OP1", "WUX", 10);
BOOST_CHECK_EQUAL(10, prod.controls(st, 0).oil_rate);
}

View File

@@ -1367,22 +1367,22 @@ BOOST_AUTO_TEST_CASE( WCONPROD ) {
{
const auto& well0 = sched.getWell2("PROD2", 0 );
const auto& well1 = sched.getWell2("PROD2", 1 );
BOOST_CHECK_CLOSE(1000/Metric::Time, well0.getProductionProperties().OilRate, 0.001);
BOOST_CHECK_CLOSE(1500/Metric::Time, well1.getProductionProperties().OilRate, 0.001);
BOOST_CHECK_CLOSE(1000/Metric::Time, well0.getProductionProperties().OilRate.get<double>(), 0.001);
BOOST_CHECK_CLOSE(1500/Metric::Time, well1.getProductionProperties().OilRate.get<double>(), 0.001);
}
{
const auto& well0 = sched.getWell2("PROD3", 0 );
const auto& well1 = sched.getWell2("PROD3", 1 );
BOOST_CHECK_CLOSE(0/Metric::Time, well0.getProductionProperties().OilRate, 0.001);
BOOST_CHECK_CLOSE(1500/Metric::Time, well1.getProductionProperties().OilRate, 0.001);
BOOST_CHECK_CLOSE(0/Metric::Time, well0.getProductionProperties().OilRate.get<double>(), 0.001);
BOOST_CHECK_CLOSE(1500/Metric::Time, well1.getProductionProperties().OilRate.get<double>(), 0.001);
}
{
const auto& well0 = sched.getWell2("PROX5", 0);
const auto& well1 = sched.getWell2("PROX5", 1);
BOOST_CHECK_CLOSE(2000/Metric::Time, well0.getProductionProperties().OilRate, 0.001);
BOOST_CHECK_CLOSE(2000/Metric::Time, well1.getProductionProperties().OilRate, 0.001);
BOOST_CHECK_CLOSE(2000/Metric::Time, well0.getProductionProperties().OilRate.get<double>(), 0.001);
BOOST_CHECK_CLOSE(2000/Metric::Time, well1.getProductionProperties().OilRate.get<double>(), 0.001);
}
}
@@ -1396,6 +1396,7 @@ BOOST_AUTO_TEST_CASE( WCONINJE ) {
Eclipse3DProperties eclipseProperties( deck , table, grid );
Runspec runspec (deck);
Schedule sched( deck, grid, eclipseProperties, runspec);
SummaryState st;
BOOST_CHECK_EQUAL(5U, sched.numWells());
BOOST_CHECK(sched.hasWell("PROD1"));
@@ -1407,22 +1408,25 @@ BOOST_AUTO_TEST_CASE( WCONINJE ) {
{
const auto& well0 = sched.getWell2("INJE2", 0);
const auto& well1 = sched.getWell2("INJE2", 1);
BOOST_CHECK_CLOSE(1000/Metric::Time, well0.getInjectionProperties().surfaceInjectionRate, 0.001);
BOOST_CHECK_CLOSE(1500/Metric::Time, well1.getInjectionProperties().surfaceInjectionRate, 0.001);
const auto controls0 = well0.injectionControls(st);
const auto controls1 = well1.injectionControls(st);
BOOST_CHECK_CLOSE(1000/Metric::Time, controls0.surface_rate, 0.001);
BOOST_CHECK_CLOSE(1500/Metric::Time, controls1.surface_rate, 0.001);
}
{
const auto& well0 = sched.getWell2("INJE3", 0);
const auto& well1 = sched.getWell2("INJE3", 1);
BOOST_CHECK_CLOSE(0000/Metric::Time, well0.getInjectionProperties().surfaceInjectionRate, 0.001);
BOOST_CHECK_CLOSE(1500/Metric::Time, well1.getInjectionProperties().surfaceInjectionRate, 0.001);
const auto controls1 = well1.injectionControls(st);
BOOST_CHECK_CLOSE(1500/Metric::Time, controls1.surface_rate, 0.001);
}
{
const auto& well0 = sched.getWell2("INJX5", 0);
const auto& well1 = sched.getWell2("INJX5", 1);
BOOST_CHECK_CLOSE(2000/Metric::Time, well0.getInjectionProperties().surfaceInjectionRate, 0.001);
BOOST_CHECK_CLOSE(2000/Metric::Time, well1.getInjectionProperties().surfaceInjectionRate, 0.001);
const auto controls0 = well0.injectionControls(st);
const auto controls1 = well1.injectionControls(st);
BOOST_CHECK_CLOSE(2000/Metric::Time, controls0.surface_rate, 0.001);
BOOST_CHECK_CLOSE(2000/Metric::Time, controls1.surface_rate, 0.001);
}
}

View File

@@ -170,62 +170,57 @@ BOOST_AUTO_TEST_CASE(WellTesting) {
BOOST_CHECK_EQUAL( WellCommon::AUTO, sched.getWell2("W_3", 3).getStatus());
{
const WellProductionProperties& prop7 = sched.getWell2("W_3", 7).getProductionProperties();
BOOST_CHECK_CLOSE( 999/Metric::Time , prop7.LiquidRate , 0.001);
BOOST_CHECK_CLOSE( 999/Metric::Time , prop7.LiquidRate.get<double>() , 0.001);
BOOST_CHECK_EQUAL( WellProducer::RESV, prop7.controlMode);
}
BOOST_CHECK_CLOSE( 8000./Metric::Time , sched.getWell2("W_3", 3).getProductionProperties().LiquidRate, 1.e-12);
BOOST_CHECK_CLOSE( 18000./Metric::Time, sched.getWell2("W_3", 8).getProductionProperties().LiquidRate, 1.e-12);
BOOST_CHECK_CLOSE( 8000./Metric::Time , sched.getWell2("W_3", 3).getProductionProperties().LiquidRate.get<double>(), 1.e-12);
BOOST_CHECK_CLOSE( 18000./Metric::Time, sched.getWell2("W_3", 8).getProductionProperties().LiquidRate.get<double>(), 1.e-12);
{
BOOST_CHECK_EQUAL(sched.getWell2("W_1", 3).getProductionProperties().predictionMode, false);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 3).getProductionProperties().WaterRate , 4/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 3).getProductionProperties().GasRate , 12345/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 3).getProductionProperties().OilRate , 4000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 3).getProductionProperties().WaterRate.get<double>() , 4/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 3).getProductionProperties().GasRate.get<double>() , 12345/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 3).getProductionProperties().OilRate.get<double>() , 4000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 4).getProductionProperties().OilRate , 4000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 4).getProductionProperties().WaterRate , 4/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 4).getProductionProperties().GasRate , 12345/Metric::Time,0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 4).getProductionProperties().OilRate.get<double>() , 4000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 4).getProductionProperties().WaterRate.get<double>() , 4/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 4).getProductionProperties().GasRate.get<double>() , 12345/Metric::Time,0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 5).getProductionProperties().WaterRate, 4/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 5).getProductionProperties().GasRate , 12345/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 5).getProductionProperties().OilRate , 4000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 5).getProductionProperties().WaterRate.get<double>(), 4/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 5).getProductionProperties().GasRate.get<double>() , 12345/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 5).getProductionProperties().OilRate.get<double>() , 4000/Metric::Time, 0.001);
BOOST_CHECK_EQUAL(sched.getWell2("W_1", 6).getProductionProperties().predictionMode, false);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 6).getProductionProperties().OilRate , 14000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 6).getProductionProperties().OilRate.get<double>() , 14000/Metric::Time, 0.001);
BOOST_CHECK_EQUAL(sched.getWell2("W_1", 7).getProductionProperties().predictionMode, true);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 7).getProductionProperties().OilRate , 11000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 7).getProductionProperties().WaterRate , 44/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 7).getProductionProperties().OilRate.get<double>() , 11000/Metric::Time, 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 7).getProductionProperties().WaterRate.get<double>() , 44/Metric::Time, 0.001);
BOOST_CHECK_EQUAL(sched.getWell2("W_1", 8).getProductionProperties().predictionMode, false);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 8).getProductionProperties().OilRate , 13000/Metric::Time , 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 8).getProductionProperties().OilRate.get<double>() , 13000/Metric::Time , 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 10).getInjectionProperties().BHPLimit, 123.00 * Metric::Pressure , 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 10).getInjectionProperties().THPLimit, 678.00 * Metric::Pressure , 0.001);
{
const WellInjectionProperties& prop11 = sched.getWell2("W_1", 11).getInjectionProperties();
BOOST_CHECK_CLOSE(5000/Metric::Time , prop11.surfaceInjectionRate, 0.001);
BOOST_CHECK_EQUAL( WellInjector::RATE , prop11.controlMode);
}
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 10).getInjectionProperties().BHPLimit.get<double>(), 123.00 * Metric::Pressure , 0.001);
BOOST_CHECK_CLOSE(sched.getWell2("W_1", 10).getInjectionProperties().THPLimit.get<double>(), 678.00 * Metric::Pressure , 0.001);
BOOST_CHECK( sched.getWell2("W_1", 9).isInjector());
{
const WellInjectionProperties& prop9 = sched.getWell2("W_1", 9).getInjectionProperties();
BOOST_CHECK_CLOSE(20000/Metric::Time , prop9.surfaceInjectionRate , 0.001);
BOOST_CHECK_CLOSE(200000/Metric::Time , prop9.reservoirInjectionRate, 0.001);
BOOST_CHECK_CLOSE(6895 * Metric::Pressure , prop9.BHPLimit, 0.001);
BOOST_CHECK_CLOSE(0 , prop9.THPLimit , 0.001);
BOOST_CHECK_EQUAL( WellInjector::RESV , prop9.controlMode);
BOOST_CHECK( prop9.hasInjectionControl(WellInjector::RATE ));
BOOST_CHECK( prop9.hasInjectionControl(WellInjector::RESV ));
BOOST_CHECK( !prop9.hasInjectionControl(WellInjector::THP));
BOOST_CHECK( prop9.hasInjectionControl(WellInjector::BHP));
SummaryState st;
const auto controls = sched.getWell2("W_1", 9).injectionControls(st);
BOOST_CHECK_CLOSE(20000/Metric::Time , controls.surface_rate , 0.001);
BOOST_CHECK_CLOSE(200000/Metric::Time , controls.reservoir_rate, 0.001);
BOOST_CHECK_CLOSE(6895 * Metric::Pressure , controls.bhp_limit, 0.001);
BOOST_CHECK_CLOSE(0 , controls.thp_limit , 0.001);
BOOST_CHECK_EQUAL( WellInjector::RESV , controls.cmode);
BOOST_CHECK( controls.hasControl(WellInjector::RATE ));
BOOST_CHECK( controls.hasControl(WellInjector::RESV ));
BOOST_CHECK( !controls.hasControl(WellInjector::THP));
BOOST_CHECK( controls.hasControl(WellInjector::BHP));
}
@@ -234,10 +229,12 @@ BOOST_AUTO_TEST_CASE(WellTesting) {
BOOST_CHECK_EQUAL( WellCommon::SHUT, sched.getWell2("W_1", 13).getStatus( ));
BOOST_CHECK_EQUAL( WellCommon::OPEN, sched.getWell2("W_1", 14).getStatus( ));
{
BOOST_CHECK( sched.getWell2("W_1", 12).getInjectionProperties().hasInjectionControl(WellInjector::RATE ));
BOOST_CHECK( !sched.getWell2("W_1", 12).getInjectionProperties().hasInjectionControl(WellInjector::RESV));
BOOST_CHECK( sched.getWell2("W_1", 12).getInjectionProperties().hasInjectionControl(WellInjector::THP ));
BOOST_CHECK( sched.getWell2("W_1", 12).getInjectionProperties().hasInjectionControl(WellInjector::BHP ));
SummaryState st;
const auto controls = sched.getWell2("W_1", 12).injectionControls(st);
BOOST_CHECK( controls.hasControl(WellInjector::RATE ));
BOOST_CHECK( !controls.hasControl(WellInjector::RESV));
BOOST_CHECK( controls.hasControl(WellInjector::THP ));
BOOST_CHECK( controls.hasControl(WellInjector::BHP ));
}
}
}
@@ -270,7 +267,7 @@ BOOST_AUTO_TEST_CASE(WellTestCOMPDAT) {
BOOST_CHECK(sched.hasWell("W_2"));
BOOST_CHECK(sched.hasWell("W_3"));
{
BOOST_CHECK_CLOSE(13000/Metric::Time , sched.getWell2("W_1", 8).getProductionProperties().OilRate , 0.0001);
BOOST_CHECK_CLOSE(13000/Metric::Time , sched.getWell2("W_1", 8).getProductionProperties().OilRate.get<double>() , 0.0001);
{
const auto& connections = sched.getWell2("W_1", 3).getConnections();
BOOST_CHECK_EQUAL(4U, connections.size());