Merge pull request #593 from GitPaean/fixing_history_mode_part_2

fixing the BHP limit for the history matching wells
This commit is contained in:
Joakim Hove
2019-01-11 18:04:45 +01:00
committed by GitHub
8 changed files with 136 additions and 68 deletions

View File

@@ -60,6 +60,10 @@ namespace Opm {
if ((injectionControls & controlModeArg) == 0)
injectionControls += controlModeArg;
}
void resetDefaultHistoricalBHPLimit();
void setBHPLimit(const double limit);
};
std::ostream& operator<<( std::ostream&, const WellInjectionProperties& );

View File

@@ -57,7 +57,8 @@ namespace Opm {
static WellProductionProperties history(const WellProductionProperties& prevProperties,
const DeckRecord& record,
const WellProducer::ControlModeEnum controlModeWHISTCL);
const WellProducer::ControlModeEnum controlModeWHISTCL,
const bool switching_from_injector);
static WellProductionProperties prediction( const DeckRecord& record, bool addGroupProductionControl );
@@ -82,6 +83,12 @@ namespace Opm {
int m_productionControls = 0;
WellProductionProperties(const DeckRecord& record);
void resetDefaultBHPLimit();
void setBHPLimit(const double limit);
double getBHPLimit() const;
};
std::ostream& operator<<( std::ostream&, const WellProductionProperties& );

View File

@@ -60,6 +60,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/Units/Dimension.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
namespace Opm {
@@ -649,7 +650,8 @@ namespace Opm {
properties = WellProductionProperties::prediction( record, addGrupProductionControl );
} else {
const WellProductionProperties& prev_properties = well->getProductionProperties(currentStep);
properties = WellProductionProperties::history(prev_properties, record, m_controlModeWHISTCTL);
const bool switching_from_injector = !well->isProducer(currentStep);
properties = WellProductionProperties::history(prev_properties, record, m_controlModeWHISTCTL, switching_from_injector);
}
updateWellStatus( *well , currentStep , status );
@@ -741,7 +743,7 @@ namespace Opm {
current behavoir agrees with the behovir of Eclipse when BHPLimit is not
specified while employed during group control.
*/
properties.BHPLimit = record.getItem("BHP").getSIDouble(0);
properties.setBHPLimit(record.getItem("BHP").getSIDouble(0));
// BHP control should always be there.
properties.addInjectionControl(WellInjector::BHP);
@@ -1006,7 +1008,12 @@ namespace Opm {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
// convert injection rates to SI
WellInjector::TypeEnum injectorType = WellInjector::TypeFromString( record.getItem("TYPE").getTrimmedString(0));
const auto& typeItem = record.getItem("TYPE");
if (typeItem.defaultApplied(0)) {
const std::string msg = "Injection type can not be defaulted for keyword WCONINJH";
throw std::invalid_argument(msg);
}
const WellInjector::TypeEnum injectorType = WellInjector::TypeFromString( typeItem.getTrimmedString(0));
double injectionRate = record.getItem("RATE").get< double >(0);
injectionRate = convertInjectionRateToSI(injectionRate, injectorType, section.unitSystem());
@@ -1023,20 +1030,44 @@ namespace Opm {
properties.injectorType = injectorType;
const std::string& cmodeString = record.getItem("CMODE").getTrimmedString(0);
WellInjector::ControlModeEnum controlMode = WellInjector::ControlModeFromString( cmodeString );
if (!record.getItem("RATE").defaultApplied(0)) {
properties.surfaceInjectionRate = injectionRate;
properties.addInjectionControl(controlMode);
properties.controlMode = controlMode;
}
properties.predictionMode = false;
if ( record.getItem( "BHP" ).hasValue(0) )
properties.BHPH = record.getItem("BHP").getSIDouble(0);
if ( record.getItem( "THP" ).hasValue(0) )
properties.THPH = record.getItem("THP").getSIDouble(0);
const std::string& cmodeString = record.getItem("CMODE").getTrimmedString(0);
const WellInjector::ControlModeEnum controlMode = WellInjector::ControlModeFromString( cmodeString );
if ( !(controlMode == WellInjector::RATE || controlMode == WellInjector::BHP) ) {
const std::string msg = "Only RATE and BHP control are allowed for WCONINJH for well " + well->name();
throw std::invalid_argument(msg);
}
// when well is under BHP control, we use its historical BHP value as BHP limit
if (controlMode == WellInjector::BHP) {
properties.setBHPLimit(properties.BHPH);
} else {
const bool switching_from_producer = well->isProducer(currentStep);
const bool switching_from_prediction = properties.predictionMode;
const bool switching_from_BHP_control = (properties.controlMode == WellInjector::BHP);
if (switching_from_prediction ||
switching_from_BHP_control ||
switching_from_producer) {
properties.resetDefaultHistoricalBHPLimit();
}
// otherwise, we keep its previous BHP limit
}
properties.addInjectionControl(WellInjector::BHP);
properties.addInjectionControl(controlMode);
properties.controlMode = controlMode;
properties.predictionMode = false;
const int VFPTableNumber = record.getItem("VFP_TABLE").get< int >(0);
if (VFPTableNumber > 0) {
properties.VFPTableNumber = VFPTableNumber;
@@ -1169,13 +1200,6 @@ namespace Opm {
}
else if (cMode == "BHP"){
prop.BHPLimit = newValue * siFactorP;
/* For wells controlled by WCONHIST the BHP value given by the
WCHONHIST keyword can not be used to control the well - i.e BHP
control is not natively available - however when BHP has been
specified with WELTARG we can enable BHP control.
*/
if (prop.predictionMode == false)
prop.addProductionControl(WellProducer::BHP);
}
else if (cMode == "THP"){
prop.THPLimit = newValue * siFactorP;
@@ -1195,13 +1219,6 @@ namespace Opm {
WellInjectionProperties prop = well->getInjectionPropertiesCopy(currentStep);
if (cMode == "BHP"){
prop.BHPLimit = newValue * siFactorP;
/* For wells controlled by WCONINJH the BHP value given by the
WCHONINJH keyword can not be used to control the well - i.e BHP
control is not natively available - however when BHP has been
specified with WELTARG we can enable BHP control.
*/
if (prop.predictionMode == false)
prop.addInjectionControl(WellInjector::BHP);
}
else if (cMode == "ORAT"){
if(prop.injectorType == WellInjector::TypeEnum::OIL){

View File

@@ -66,6 +66,16 @@ namespace Opm {
return !(*this == other);
}
void WellInjectionProperties::resetDefaultHistoricalBHPLimit() {
// this default BHP value is from simulation result,
// without finding any related document
BHPLimit = 6891.2 * unit::barsa;
}
void WellInjectionProperties::setBHPLimit(const double limit) {
BHPLimit = limit;
}
std::ostream& operator<<( std::ostream& stream,
const WellInjectionProperties& wp ) {
return stream

View File

@@ -25,6 +25,7 @@
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
namespace Opm {
@@ -43,7 +44,8 @@ namespace Opm {
WellProductionProperties WellProductionProperties::history(const WellProductionProperties& prev_properties,
const DeckRecord& record,
const WellProducer::ControlModeEnum controlModeWHISTCL)
const WellProducer::ControlModeEnum controlModeWHISTCL,
const bool switching_from_injector)
{
WellProductionProperties p(record);
p.predictionMode = false;
@@ -51,42 +53,54 @@ namespace Opm {
// update LiquidRate
p.LiquidRate = p.WaterRate + p.OilRate;
const auto& cmodeItem = record.getItem("CMODE");
if ( !cmodeItem.defaultApplied(0) ) {
namespace wp = WellProducer;
auto cmode = wp::ControlModeFromString( cmodeItem.getTrimmedString( 0 ) );
// when there is an effective control mode specified by WHISTCL, we always use this control mode
if (effectiveHistoryProductionControl(controlModeWHISTCL) ) {
cmode = controlModeWHISTCL;
}
if (effectiveHistoryProductionControl(cmode) ) {
p.addProductionControl( cmode );
p.controlMode = cmode;
} else {
const std::string cmode_string = cmodeItem.getTrimmedString( 0 );
const std::string msg = "unsupported control mode " + cmode_string + " for WCONHIST";
throw std::invalid_argument(msg);
}
// always have a BHP control/limit, while the limit value needs to be determined
// the control mode added above can be a BHP control or a type of RATE control
if ( !p.hasProductionControl( wp::BHP ) )
p.addProductionControl( wp::BHP );
if (cmode == wp::BHP)
p.BHPLimit = record.getItem( "BHP" ).getSIDouble( 0 );
else
p.BHPLimit = prev_properties.BHPLimit;
}
if ( record.getItem( "BHP" ).hasValue(0) )
p.BHPH = record.getItem("BHP").getSIDouble(0);
if ( record.getItem( "THP" ).hasValue(0) )
p.THPH = record.getItem("THP").getSIDouble(0);
const auto& cmodeItem = record.getItem("CMODE");
if ( cmodeItem.defaultApplied(0) ) {
const std::string msg = "control mode can not be defaulted for keyword WCONHIST";
throw std::invalid_argument(msg);
}
namespace wp = WellProducer;
auto cmode = wp::ControlModeFromString( cmodeItem.getTrimmedString( 0 ) );
// when there is an effective control mode specified by WHISTCL, we always use this control mode
if (effectiveHistoryProductionControl(controlModeWHISTCL) ) {
cmode = controlModeWHISTCL;
}
if (effectiveHistoryProductionControl(cmode) ) {
p.addProductionControl( cmode );
p.controlMode = cmode;
} else {
const std::string cmode_string = cmodeItem.getTrimmedString( 0 );
const std::string msg = "unsupported control mode " + cmode_string + " for WCONHIST";
throw std::invalid_argument(msg);
}
// always have a BHP control/limit, while the limit value needs to be determined
// the control mode added above can be a BHP control or a type of RATE control
if ( !p.hasProductionControl( wp::BHP ) )
p.addProductionControl( wp::BHP );
if (cmode == wp::BHP) {
p.setBHPLimit(p.BHPH);
} else {
// when the well is switching to history matching producer from prediction mode
// or switching from injector to producer
// or switching from BHP control to RATE control (under history matching mode)
// we use the defaulted BHP limit, otherwise, we use the previous BHP limit
if ( prev_properties.predictionMode || switching_from_injector
|| prev_properties.controlMode == wp::BHP ) {
p.resetDefaultBHPLimit();
} else {
p.setBHPLimit(prev_properties.getBHPLimit());
}
}
p.VFPTableNumber = record.getItem("VFPTable").get< int >(0);
if (p.VFPTableNumber == 0)
@@ -201,4 +215,16 @@ namespace Opm {
cmode == wp::WRAT || cmode == wp::GRAT || cmode == wp::BHP) );
}
void WellProductionProperties::resetDefaultBHPLimit() {
BHPLimit = 1. * unit::atm;
}
void WellProductionProperties::setBHPLimit(const double limit) {
BHPLimit = limit;
}
double WellProductionProperties::getBHPLimit() const {
return BHPLimit;
}
} // namespace Opm

View File

@@ -1384,7 +1384,7 @@ BOOST_AUTO_TEST_CASE(changeBhpLimitInHistoryModeWithWeltarg) {
"/\n"
"WCONHIST\n"
" 'I' 'OPEN' 'RESV' 6* /\n/\n"
"DATES -- 3\n"
"DATES -- 4\n"
" 20 OKT 2008 / \n"
"/\n"
"WCONINJH\n"
@@ -1412,12 +1412,16 @@ BOOST_AUTO_TEST_CASE(changeBhpLimitInHistoryModeWithWeltarg) {
BOOST_CHECK_EQUAL(well_i->getInjectionProperties(2).BHPLimit, 600 * 1e5); // 2
// Check that the BHP limit is reset when changing between injector and producer.
// well_i is a producer for this report step
BOOST_CHECK_EQUAL(well_i->getInjectionProperties(3).BHPLimit, 0); // 3
BOOST_CHECK_EQUAL(well_i->getInjectionProperties(4).BHPLimit, 0); // 4
// well_i changes from producer to injector
BOOST_CHECK_EQUAL(well_i->getInjectionProperties(4).BHPLimit, 6891.2 * 1e5); // 4
BOOST_CHECK_EQUAL( true , well_i->getInjectionProperties(2).hasInjectionControl(Opm::WellInjector::BHP) );
BOOST_CHECK_EQUAL( true , well_i->getInjectionProperties(2).hasInjectionControl(Opm::WellInjector::BHP) );
// it is a producer
BOOST_CHECK_EQUAL( false , well_i->getInjectionProperties(3).hasInjectionControl(Opm::WellInjector::BHP) );
BOOST_CHECK_EQUAL( false , well_i->getInjectionProperties(4).hasInjectionControl(Opm::WellInjector::BHP) );
BOOST_CHECK_EQUAL( true , well_i->getProductionProperties(3).hasProductionControl(Opm::WellProducer::BHP) );
BOOST_CHECK_EQUAL( true , well_i->getInjectionProperties(4).hasInjectionControl(Opm::WellInjector::BHP) );
}
BOOST_AUTO_TEST_CASE(changeModeWithWHISTCTL) {

View File

@@ -771,7 +771,7 @@ namespace {
const std::string& cmode_string = whistctl_record.getItem("CMODE").getTrimmedString(0);
whistctl_cmode = Opm::WellProducer::ControlModeFromString(cmode_string);
}
Opm::WellProductionProperties hist = Opm::WellProductionProperties::history(prev_p, record, whistctl_cmode);;
Opm::WellProductionProperties hist = Opm::WellProductionProperties::history(prev_p, record, whistctl_cmode, false);;
return hist;
}
@@ -848,7 +848,7 @@ BOOST_AUTO_TEST_CASE(WCH_All_Specified_BHP_Defaulted)
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.VFPTableNumber, 12);
BOOST_CHECK_EQUAL(p.ALQValue, 18.);
BOOST_CHECK_EQUAL(p.BHPLimit, 100.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_ORAT_Defaulted_BHP_Defaulted)
@@ -866,7 +866,7 @@ BOOST_AUTO_TEST_CASE(WCH_ORAT_Defaulted_BHP_Defaulted)
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.VFPTableNumber, 12);
BOOST_CHECK_EQUAL(p.ALQValue, 18.);
BOOST_CHECK_EQUAL(p.BHPLimit, 100.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_OWRAT_Defaulted_BHP_Defaulted)
@@ -884,7 +884,7 @@ BOOST_AUTO_TEST_CASE(WCH_OWRAT_Defaulted_BHP_Defaulted)
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.VFPTableNumber, 12);
BOOST_CHECK_EQUAL(p.ALQValue, 18.);
BOOST_CHECK_EQUAL(p.BHPLimit, 100.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Defaulted)
@@ -902,7 +902,7 @@ BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Defaulted)
BOOST_CHECK(p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.VFPTableNumber, 12);
BOOST_CHECK_EQUAL(p.ALQValue, 18.);
BOOST_CHECK_EQUAL(p.BHPLimit, 100.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Specified)
@@ -921,7 +921,7 @@ BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Specified)
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::WellProducer::BHP));
BOOST_CHECK_EQUAL(p.VFPTableNumber, 12);
BOOST_CHECK_EQUAL(p.ALQValue, 18.);
BOOST_CHECK_EQUAL(p.BHPLimit, 100.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_Rates_NON_Defaulted_VFP)
@@ -940,7 +940,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, 100.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_Whistctl)
@@ -961,7 +961,7 @@ BOOST_AUTO_TEST_CASE(WCH_Whistctl)
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, 100.);
BOOST_CHECK_EQUAL(p.BHPLimit, 101325.);
}
BOOST_AUTO_TEST_CASE(WCH_BHP_Specified)

View File

@@ -70,7 +70,7 @@ WELOPEN
/
WCONHIST
'W3' 'SHUT' /
'W3' 'SHUT' 'ORAT'/
/