implement support for FBHPDEF

This commit is contained in:
Arne Morten Kvarving 2023-11-02 14:41:14 +01:00
parent 33c529652b
commit 3875736795
11 changed files with 286 additions and 27 deletions

View File

@ -367,6 +367,7 @@ namespace Opm
this->template pack_unpack<GasLiftOpt>(serializer); this->template pack_unpack<GasLiftOpt>(serializer);
this->template pack_unpack<RFTConfig>(serializer); this->template pack_unpack<RFTConfig>(serializer);
this->template pack_unpack<RSTConfig>(serializer); this->template pack_unpack<RSTConfig>(serializer);
this->template pack_unpack<ScheduleState::BHPDefaults>(serializer);
this->template pack_unpack_map<int, VFPProdTable>(serializer); this->template pack_unpack_map<int, VFPProdTable>(serializer);
this->template pack_unpack_map<int, VFPInjTable>(serializer); this->template pack_unpack_map<int, VFPInjTable>(serializer);
@ -712,6 +713,7 @@ namespace Opm
void handleDRVDT (HandlerContext&); void handleDRVDT (HandlerContext&);
void handleDRVDTR (HandlerContext&); void handleDRVDTR (HandlerContext&);
void handleEXIT (HandlerContext&); void handleEXIT (HandlerContext&);
void handleFBHPDEF (HandlerContext&);
void handleGCONINJE (HandlerContext&); void handleGCONINJE (HandlerContext&);
void handleGCONPROD (HandlerContext&); void handleGCONPROD (HandlerContext&);
void handleGCONSALE (HandlerContext&); void handleGCONSALE (HandlerContext&);

View File

@ -279,7 +279,28 @@ namespace Opm {
std::unordered_map<K, std::shared_ptr<T>> m_data; std::unordered_map<K, std::shared_ptr<T>> m_data;
}; };
struct BHPDefaults {
std::optional<double> prod_target;
std::optional<double> inj_limit;
static BHPDefaults serializationTestObject()
{
return BHPDefaults{1.0, 2.0};
}
bool operator==(const BHPDefaults& rhs) const
{
return this->prod_target == rhs.prod_target
&& this->inj_limit == rhs.inj_limit;
}
template<class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(prod_target);
serializer(inj_limit);
}
};
ScheduleState() = default; ScheduleState() = default;
explicit ScheduleState(const time_point& start_time); explicit ScheduleState(const time_point& start_time);
@ -382,6 +403,8 @@ namespace Opm {
ptr_member<RFTConfig> rft_config; ptr_member<RFTConfig> rft_config;
ptr_member<RSTConfig> rst_config; ptr_member<RSTConfig> rst_config;
ptr_member<BHPDefaults> bhp_defaults;
template <typename T> template <typename T>
ptr_member<T>& get() { ptr_member<T>& get() {
return const_cast<ptr_member<T>&>(std::as_const(*this).template get<T>()); return const_cast<ptr_member<T>&>(std::as_const(*this).template get<T>());
@ -428,6 +451,8 @@ namespace Opm {
return this->rft_config; return this->rft_config;
else if constexpr ( std::is_same_v<T, RSTConfig> ) else if constexpr ( std::is_same_v<T, RSTConfig> )
return this->rst_config; return this->rst_config;
else if constexpr ( std::is_same_v<T, BHPDefaults> )
return this->bhp_defaults;
else else
static_assert(always_false1::value, "Template type <T> not supported in get()"); static_assert(always_false1::value, "Template type <T> not supported in get()");
} }

View File

@ -168,8 +168,29 @@ public:
static WellInjectionProperties serializationTestObject(); static WellInjectionProperties serializationTestObject();
void handleWELTARG(WELTARGCMode cmode, const UDAValue& new_arg, double SIFactorP); void handleWELTARG(WELTARGCMode cmode, const UDAValue& new_arg, double SIFactorP);
void handleWCONINJE(const DeckRecord& record, bool availableForGroupControl, const std::string& well_name);
void handleWCONINJH(const DeckRecord& record, const bool is_producer, const std::string& well_name, const KeywordLocation& loc); //! \brief Handle a WCONINJE keyword.
//! \param record The deck record to use
//! \param bhp_def The default BHP target in input units
//! \param availableForGroupControl True if available for group control
//! \param well_name Name of well
void handleWCONINJE(const DeckRecord& record,
const double bhp_def,
bool availableForGroupControl,
const std::string& well_name);
//! \brief Handle a WCONINJH keyword.
//! \param record The deck record to use
//! \param bhp_def The default BHP limit in SI units
//! \param is_producer True if well is a producer
//! \param well_name Name of well
//! \param loc Location of keyword for logging purpuses
void handleWCONINJH(const DeckRecord& record,
const double bhp_def,
const bool is_producer,
const std::string& well_name,
const KeywordLocation& loc);
bool hasInjectionControl(InjectorCMode controlModeArg) const { bool hasInjectionControl(InjectorCMode controlModeArg) const {
if (injectionControls & static_cast<int>(controlModeArg)) if (injectionControls & static_cast<int>(controlModeArg))
return true; return true;
@ -240,6 +261,7 @@ public:
// BHP and THP limit // BHP and THP limit
double bhp_hist_limit = 0.0; double bhp_hist_limit = 0.0;
double thp_hist_limit = 0.0; double thp_hist_limit = 0.0;
bool bhp_hist_limit_defaulted = true; // Tracks whether value was defaulted or not
// historical BHP and THP under historical mode // historical BHP and THP under historical mode
double BHPH = 0.0; double BHPH = 0.0;
@ -273,8 +295,28 @@ public:
// this is used to check whether the specified control mode is an effective history matching production mode // this is used to check whether the specified control mode is an effective history matching production mode
static bool effectiveHistoryProductionControl(ProducerCMode cmode); static bool effectiveHistoryProductionControl(ProducerCMode cmode);
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); //! \brief Handle WCONPROD keyword.
//! \param alq_type ALQ type
//! \param bhp_def Default BHP target in SI units
//! \param unit_system Unit system to use
//! \param well Well name
//! \param record Deck record to use
void handleWCONPROD(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type,
const double bhp_def,
const UnitSystem& unit_system,
const std::string& well,
const DeckRecord& record);
//! \brief Handle WCONHIST keyword.
//! \param alq_type ALQ type
//! \param bhp_def Default BHP limit in SI units
//! \param unit_system Unit system to use
//! \param record Deck record to use
void handleWCONHIST(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type,
const double bhp_def,
const UnitSystem& unit_system,
const DeckRecord& record);
void handleWELTARG( WELTARGCMode cmode, const UDAValue& new_arg, double SiFactorP); void handleWELTARG( WELTARGCMode cmode, const UDAValue& new_arg, double SiFactorP);
void resetDefaultBHPLimit(); void resetDefaultBHPLimit();
void clearControls(); void clearControls();

View File

@ -86,6 +86,7 @@
#include <opm/input/eclipse/Parser/ParserKeywords/B.hpp> #include <opm/input/eclipse/Parser/ParserKeywords/B.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/C.hpp> #include <opm/input/eclipse/Parser/ParserKeywords/C.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/D.hpp> #include <opm/input/eclipse/Parser/ParserKeywords/D.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/F.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/G.hpp> #include <opm/input/eclipse/Parser/ParserKeywords/G.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/L.hpp> #include <opm/input/eclipse/Parser/ParserKeywords/L.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/N.hpp> #include <opm/input/eclipse/Parser/ParserKeywords/N.hpp>
@ -465,6 +466,20 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
this->applyEXIT(handlerContext.keyword, handlerContext.currentStep); this->applyEXIT(handlerContext.keyword, handlerContext.currentStep);
} }
void Schedule::handleFBHPDEF(HandlerContext& handlerContext)
{
using FBHP = ParserKeywords::FBHPDEF;
const auto& record = handlerContext.keyword.getRecord(0);
ScheduleState::BHPDefaults bhp_defaults;
const auto& prod_limit = record.getItem<FBHP::TARGET_BHP>();
const auto& inj_limit = record.getItem<FBHP::LIMIT_BHP>();
if (!(prod_limit.defaultApplied(0) && inj_limit.defaultApplied(0))) {
bhp_defaults.prod_target = prod_limit.getSIDouble(0);
bhp_defaults.inj_limit = inj_limit.getSIDouble(0);
}
this->snapshots.back().bhp_defaults.update(std::move(bhp_defaults));
}
void Schedule::handleGCONINJE(HandlerContext& handlerContext) { void Schedule::handleGCONINJE(HandlerContext& handlerContext) {
using GI = ParserKeywords::GCONINJE; using GI = ParserKeywords::GCONINJE;
auto current_step = handlerContext.currentStep; auto current_step = handlerContext.currentStep;
@ -1300,10 +1315,22 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
throw OpmInputError(reason, handlerContext.keyword.location()); throw OpmInputError(reason, handlerContext.keyword.location());
} }
} }
properties->handleWCONHIST(alq_type, this->m_static.m_unit_system, record); double default_bhp;
if (this->snapshots.back().bhp_defaults.get().prod_target) {
default_bhp = *this->snapshots.back().bhp_defaults.get().prod_target;
} else {
default_bhp = UnitSystem::newMETRIC().to_si(UnitSystem::measure::pressure,
ParserKeywords::FBHPDEF::TARGET_BHP::defaultValue);
}
properties->handleWCONHIST(alq_type,
default_bhp,
this->m_static.m_unit_system, record);
if (switching_from_injector) { if (switching_from_injector) {
properties->resetDefaultBHPLimit(); if (properties->bhp_hist_limit_defaulted) {
properties->setBHPLimit(default_bhp);
}
auto inj_props = std::make_shared<Well::WellInjectionProperties>(well2.getInjectionProperties()); auto inj_props = std::make_shared<Well::WellInjectionProperties>(well2.getInjectionProperties());
inj_props->resetBHPLimit(); inj_props->resetBHPLimit();
@ -1375,10 +1402,23 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
throw OpmInputError(reason, handlerContext.keyword.location()); throw OpmInputError(reason, handlerContext.keyword.location());
} }
} }
properties->handleWCONPROD(alq_type, this->m_static.m_unit_system, well_name, record);
double default_bhp_target;
if (this->snapshots.back().bhp_defaults.get().prod_target) {
default_bhp_target = *this->snapshots.back().bhp_defaults.get().prod_target;
} else {
default_bhp_target = UnitSystem::newMETRIC().to_si(UnitSystem::measure::pressure,
ParserKeywords::WCONPROD::BHP::defaultValue.get<double>());
}
properties->handleWCONPROD(alq_type, default_bhp_target,
this->m_static.m_unit_system,
well_name, record);
if (switching_from_injector) { if (switching_from_injector) {
properties->resetDefaultBHPLimit(); if (properties->bhp_hist_limit_defaulted) {
properties->setBHPLimit(default_bhp_target);
}
update_well = true; update_well = true;
this->snapshots.back().wellgroup_events().addEvent( well2.name(), ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER); this->snapshots.back().wellgroup_events().addEvent( well2.name(), ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER);
} }
@ -1428,7 +1468,21 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
auto injection = std::make_shared<Well::WellInjectionProperties>(well2.getInjectionProperties()); auto injection = std::make_shared<Well::WellInjectionProperties>(well2.getInjectionProperties());
auto previousInjectorType = injection->injectorType; auto previousInjectorType = injection->injectorType;
injection->handleWCONINJE(record, well2.isAvailableForGroupControl(), well_name);
double default_bhp_limit;
if (this->snapshots.back().bhp_defaults.get().inj_limit) {
default_bhp_limit = this->m_static.m_unit_system.from_si(UnitSystem::measure::pressure,
*this->snapshots.back().bhp_defaults.get().inj_limit);
} else {
default_bhp_limit = UnitSystem::newMETRIC().to_si(UnitSystem::measure::pressure,
ParserKeywords::WCONINJE::BHP::defaultValue.get<double>());
default_bhp_limit = this->m_static.m_unit_system.from_si(UnitSystem::measure::pressure,
default_bhp_limit);
}
injection->handleWCONINJE(record, default_bhp_limit,
well2.isAvailableForGroupControl(), well_name);
const bool switching_from_producer = well2.isProducer(); const bool switching_from_producer = well2.isProducer();
if (well2.updateInjection(injection)) if (well2.updateInjection(injection))
update_well = true; update_well = true;
@ -1497,9 +1551,20 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
auto well2 = this->snapshots.back().wells.get( well_name ); auto well2 = this->snapshots.back().wells.get( well_name );
auto injection = std::make_shared<Well::WellInjectionProperties>(well2.getInjectionProperties()); auto injection = std::make_shared<Well::WellInjectionProperties>(well2.getInjectionProperties());
auto previousInjectorType = injection->injectorType; auto previousInjectorType = injection->injectorType;
injection->handleWCONINJH(record, well2.isProducer(), well_name, handlerContext.keyword.location());
const bool switching_from_producer = well2.isProducer();
double default_bhp_limit;
if (this->snapshots.back().bhp_defaults.get().inj_limit) {
default_bhp_limit = *this->snapshots.back().bhp_defaults.get().inj_limit;
} else {
default_bhp_limit = UnitSystem::newMETRIC().to_si(UnitSystem::measure::pressure,
6891.2);
}
injection->handleWCONINJH(record, default_bhp_limit,
well2.isProducer(), well_name,
handlerContext.keyword.location());
const bool switching_from_producer = well2.isProducer();
if (well2.updateInjection(injection)) if (well2.updateInjection(injection))
update_well = true; update_well = true;
@ -2789,6 +2854,7 @@ Well{0} entered with 'FIELD' parent group:
{ "DRVDTR" , &Schedule::handleDRVDTR }, { "DRVDTR" , &Schedule::handleDRVDTR },
{ "ENDBOX" , &Schedule::handleGEOKeyword}, { "ENDBOX" , &Schedule::handleGEOKeyword},
{ "EXIT", &Schedule::handleEXIT }, { "EXIT", &Schedule::handleEXIT },
{ "FBHPDEF", &Schedule::handleFBHPDEF },
{ "GCONINJE", &Schedule::handleGCONINJE }, { "GCONINJE", &Schedule::handleGCONINJE },
{ "GCONPROD", &Schedule::handleGCONPROD }, { "GCONPROD", &Schedule::handleGCONPROD },
{ "GCONSALE", &Schedule::handleGCONSALE }, { "GCONSALE", &Schedule::handleGCONSALE },

View File

@ -2427,6 +2427,7 @@ void Schedule::create_first(const time_point& start_time, const std::optional<ti
sched_state.network_balance.update(Network::Balance{ runspec.networkDimensions().active() }); sched_state.network_balance.update(Network::Balance{ runspec.networkDimensions().active() });
sched_state.update_sumthin(this->m_static.sumthin); sched_state.update_sumthin(this->m_static.sumthin);
sched_state.rptonly(this->m_static.rptonly); sched_state.rptonly(this->m_static.rptonly);
sched_state.bhp_defaults.update( ScheduleState::BHPDefaults() );
//sched_state.update_date( start_time ); //sched_state.update_date( start_time );
this->addGroup("FIELD", 0); this->addGroup("FIELD", 0);
} }

View File

@ -19,6 +19,8 @@
#include <opm/input/eclipse/Schedule/ScheduleState.hpp> #include <opm/input/eclipse/Schedule/ScheduleState.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/F.hpp>
#include <opm/input/eclipse/Schedule/Action/Actions.hpp> #include <opm/input/eclipse/Schedule/Action/Actions.hpp>
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp> #include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp> #include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
@ -307,6 +309,7 @@ bool ScheduleState::operator==(const ScheduleState& other) const {
this->guide_rate.get() == other.guide_rate.get() && this->guide_rate.get() == other.guide_rate.get() &&
this->rft_config.get() == other.rft_config.get() && this->rft_config.get() == other.rft_config.get() &&
this->udq.get() == other.udq.get() && this->udq.get() == other.udq.get() &&
this->bhp_defaults.get() == other.bhp_defaults.get() &&
this->wells == other.wells && this->wells == other.wells &&
this->groups == other.groups && this->groups == other.groups &&
this->vfpprod == other.vfpprod && this->vfpprod == other.vfpprod &&
@ -338,6 +341,7 @@ ScheduleState ScheduleState::serializationTestObject() {
ts.m_sumthin = 12.345; ts.m_sumthin = 12.345;
ts.m_rptonly = true; ts.m_rptonly = true;
ts.bhp_defaults.update( BHPDefaults::serializationTestObject() );
ts.pavg.update( PAvg::serializationTestObject() ); ts.pavg.update( PAvg::serializationTestObject() );
ts.wtest_config.update( WellTestConfig::serializationTestObject() ); ts.wtest_config.update( WellTestConfig::serializationTestObject() );
ts.gconsump.update( GConSump::serializationTestObject() ); ts.gconsump.update( GConSump::serializationTestObject() );

View File

@ -427,8 +427,11 @@ Well::Well(const RestartIO::RstWell& rst_well,
if (! i->predictionMode) { if (! i->predictionMode) {
if (i->controlMode == Well::InjectorCMode::BHP) if (i->controlMode == Well::InjectorCMode::BHP)
i->bhp_hist_limit = rst_well.hist_bhp_target; i->bhp_hist_limit = rst_well.hist_bhp_target;
else else {
// defaults (ie FBHPDEF) are not stored in the restart file.
// we thus use an empirically obtained default value.
i->resetDefaultHistoricalBHPLimit(); i->resetDefaultHistoricalBHPLimit();
}
} }
else if (this->isAvailableForGroupControl()) else if (this->isAvailableForGroupControl())
i->addInjectionControl(Well::InjectorCMode::GRUP); i->addInjectionControl(Well::InjectorCMode::GRUP);

View File

@ -85,7 +85,11 @@ namespace Opm {
return result; return result;
} }
void Well::WellInjectionProperties::handleWCONINJE(const DeckRecord& record, bool availableForGroupControl, const std::string& well_name) { void Well::WellInjectionProperties::handleWCONINJE(const DeckRecord& record,
const double bhp_def,
bool availableForGroupControl,
const std::string& well_name)
{
this->injectorType = InjectorTypeFromString( record.getItem("TYPE").getTrimmedString(0) ); this->injectorType = InjectorTypeFromString( record.getItem("TYPE").getTrimmedString(0) );
this->predictionMode = true; this->predictionMode = true;
@ -118,7 +122,11 @@ namespace Opm {
current behavoir agrees with the behavior of Eclipse when BHPLimit is not current behavoir agrees with the behavior of Eclipse when BHPLimit is not
specified while employed during group control. specified while employed during group control.
*/ */
this->BHPTarget = record.getItem("BHP").get<UDAValue>(0); if (record.getItem("BHP").defaultApplied(0)) {
this->BHPTarget.update(bhp_def);
} else {
this->BHPTarget = record.getItem("BHP").get<UDAValue>(0);
}
this->addInjectionControl(InjectorCMode::BHP); this->addInjectionControl(InjectorCMode::BHP);
if (availableForGroupControl) if (availableForGroupControl)
@ -182,6 +190,7 @@ namespace Opm {
void void
Well::WellInjectionProperties::handleWCONINJH(const DeckRecord& record, Well::WellInjectionProperties::handleWCONINJH(const DeckRecord& record,
const double bhp_def,
const bool is_producer, const bool is_producer,
const std::string& well_name, const std::string& well_name,
const KeywordLocation& loc) const KeywordLocation& loc)
@ -232,7 +241,7 @@ namespace Opm {
if (switching_from_prediction || if (switching_from_prediction ||
switching_from_BHP_control || switching_from_BHP_control ||
switching_from_producer) { switching_from_producer) {
this->resetDefaultHistoricalBHPLimit(); this->bhp_hist_limit = bhp_def;
} }
// otherwise, we keep its previous BHP limit // otherwise, we keep its previous BHP limit
} }

View File

@ -160,13 +160,22 @@ namespace Opm {
void Well::WellProductionProperties::handleWCONPROD(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system_arg, const std::string& /* well */, const DeckRecord& record) void Well::WellProductionProperties::handleWCONPROD(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type,
const double bhp_def,
const UnitSystem& unit_system_arg,
const std::string& /* well */,
const DeckRecord& record)
{ {
this->predictionMode = true; this->predictionMode = true;
this->init_vfp(alq_type, unit_system_arg, record); this->init_vfp(alq_type, unit_system_arg, record);
this->init_rates(record); this->init_rates(record);
this->BHPTarget = record.getItem("BHP").get<UDAValue>(0); if (record.getItem("BHP").defaultApplied(0)) {
this->BHPTarget.update(unit_system_arg.from_si(UnitSystem::measure::pressure,
bhp_def));
} else {
this->BHPTarget = record.getItem("BHP").get<UDAValue>(0);
}
this->THPTarget = record.getItem("THP").get<UDAValue>(0); this->THPTarget = record.getItem("THP").get<UDAValue>(0);
this->LiquidRate = record.getItem("LRAT").get<UDAValue>(0); this->LiquidRate = record.getItem("LRAT").get<UDAValue>(0);
this->ResVRate = record.getItem("RESV").get<UDAValue>(0); this->ResVRate = record.getItem("RESV").get<UDAValue>(0);
@ -209,7 +218,10 @@ namespace Opm {
originate from the WCONHIST keyword. Predictions are handled with the originate from the WCONHIST keyword. Predictions are handled with the
default constructor and the handleWCONPROD() method. default constructor and the handleWCONPROD() method.
*/ */
void Well::WellProductionProperties::handleWCONHIST(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type, const UnitSystem& unit_system_arg, const DeckRecord& record) void Well::WellProductionProperties::handleWCONHIST(const std::optional<VFPProdTable::ALQ_TYPE>& alq_type,
const double bhp_def,
const UnitSystem& unit_system_arg,
const DeckRecord& record)
{ {
this->init_rates(record); this->init_rates(record);
this->init_vfp(alq_type, unit_system_arg, record); this->init_vfp(alq_type, unit_system_arg, record);
@ -220,11 +232,9 @@ void Well::WellProductionProperties::handleWCONHIST(const std::optional<VFPProdT
// or switching from injector to producer // or switching from injector to producer
// or switching from BHP control to RATE control (under history matching mode) // 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 // we use the defaulted BHP limit, otherwise, we use the previous BHP limit
if (this->predictionMode) if (this->predictionMode || this->controlMode == ProducerCMode::BHP) {
this->resetDefaultBHPLimit(); this->setBHPLimit(bhp_def);
}
if (this->controlMode == ProducerCMode::BHP)
this->resetDefaultBHPLimit();
this->init_history(record); this->init_history(record);
} }
@ -258,6 +268,7 @@ void Well::WellProductionProperties::handleWCONHIST(const std::optional<VFPProdT
else else
this->bhp_hist_limit = new_arg.get<double>() * SiFactorP; this->bhp_hist_limit = new_arg.get<double>() * SiFactorP;
this->addProductionControl( ProducerCMode::BHP ); this->addProductionControl( ProducerCMode::BHP );
this->bhp_hist_limit_defaulted = false;
} }
else if (cmode == WELTARGCMode::THP){ else if (cmode == WELTARGCMode::THP){
this->THPTarget.update_value( new_arg ); this->THPTarget.update_value( new_arg );

View File

@ -8,12 +8,14 @@
{ {
"name": "TARGET_BHP", "name": "TARGET_BHP",
"value_type": "DOUBLE", "value_type": "DOUBLE",
"dimension": "Length" "dimension": "Pressure",
"default": 1.01325
}, },
{ {
"name": "LIMIT_BHP", "name": "LIMIT_BHP",
"value_type": "DOUBLE", "value_type": "DOUBLE",
"dimension": "Pressure" "dimension": "Pressure",
"default": 6895
} }
] ]
} }

View File

@ -47,6 +47,8 @@
#include <opm/input/eclipse/Parser/Parser.hpp> #include <opm/input/eclipse/Parser/Parser.hpp>
#include <opm/common/utility/TimeService.hpp> #include <opm/common/utility/TimeService.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/F.hpp>
using namespace Opm; using namespace Opm;
namespace { namespace {
@ -589,7 +591,9 @@ namespace {
auto deck = parser.parseString(input); auto deck = parser.parseString(input);
const auto& record = deck["WCONHIST"].back().getRecord(0); const auto& record = deck["WCONHIST"].back().getRecord(0);
Opm::Well::WellProductionProperties hist(unit_system, "W"); Opm::Well::WellProductionProperties hist(unit_system, "W");
hist.handleWCONHIST(alq_type, unit_system, record); hist.handleWCONHIST(alq_type,
Opm::ParserKeywords::FBHPDEF::TARGET_BHP::defaultValue * unit::barsa,
unit_system, record);
return hist; return hist;
@ -642,7 +646,9 @@ namespace {
const auto& kwd = deck["WCONPROD"].back(); const auto& kwd = deck["WCONPROD"].back();
const auto& record = kwd.getRecord(0); const auto& record = kwd.getRecord(0);
Opm::Well::WellProductionProperties pred(unit_system, "W"); Opm::Well::WellProductionProperties pred(unit_system, "W");
pred.handleWCONPROD(alq_type, unit_system, "WELL", record); pred.handleWCONPROD(alq_type,
Opm::ParserKeywords::FBHPDEF::TARGET_BHP::defaultValue * unit::barsa,
unit_system, "WELL", record);
return pred; return pred;
} }
@ -1870,3 +1876,91 @@ END
} }
} }
} }
BOOST_AUTO_TEST_CASE(FBHPDEF_Basic)
{
const auto deck = Parser{}.parseString(R"(RUNSPEC
DIMENS
10 10 3 /
GRID
DXV
10*100.0 /
DYV
10*100.0 /
DZV
3*5.0 /
DEPTHZ
121*2000 /
PERMX
300*100.0 /
COPY
PERMX PERMY /
PERMX PERMZ /
/
MULTIPLY
PERMZ 0.1 /
/
PORO
300*0.3 /
SCHEDULE
WELSPECS
'P' 'G' 10 10 1* 'OIL' /
'I' 'G' 1 1 1* 'GAS' /
'I2' 'W' 1 1 1* 'WATER' /
'I3' 'W' 1 1 1* 'WATER' /
/
COMPDAT
'P' 10 10 1 3 'OPEN' /
'I' 1 1 1 1 'OPEN' /
'I2' 1 1 1 1 'OPEN' /
'I3' 1 1 1 1 'OPEN' /
/
WCONINJH
I3 WATER OPEN 116281 1* 0 /
/
FBHPDEF
5.0 20.0 /
WCONPROD
'P' 'OPEN' 'LRAT' 1* 1* 1* 1234.567 1* 1* /
/
WCONINJH
I2 WATER OPEN 116281 1* 0 /
/
FBHPDEF
2.0 30.0 /
WCONINJE
'I' 'GAS' 'OPEN' 'RATE' 20.0E3 /
/
TSTEP
30.0 /
WELSPECS
'P' 'G1' /
/
TSTEP
30.0 /
END
)");
const auto es = EclipseState { deck };
const auto sched = Schedule { deck, es };
const auto& wellP = sched.getWell("P", 0);
BOOST_CHECK_EQUAL(wellP.getProductionProperties().BHPTarget.get<double>(), 5.0);
const auto& wellI = sched.getWell("I", 0);
BOOST_CHECK_CLOSE(wellI.getInjectionProperties().BHPTarget.get<double>(), 30.0, 1e-12);
const auto& wellI2 = sched.getWell("I2", 0);
BOOST_CHECK_EQUAL(wellI2.getInjectionProperties().bhp_hist_limit, 20.0 * unit::barsa);
const auto& wellI3 = sched.getWell("I3", 0);
BOOST_CHECK_CLOSE(wellI3.getInjectionProperties().bhp_hist_limit, 6891.2 * unit::barsa, 1e-12);
}