implement support for FBHPDEF
This commit is contained in:
parent
33c529652b
commit
3875736795
@ -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&);
|
||||||
|
@ -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()");
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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 },
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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() );
|
||||||
|
@ -427,9 +427,12 @@ 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);
|
||||||
|
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
if (record.getItem("BHP").defaultApplied(0)) {
|
||||||
|
this->BHPTarget.update(bhp_def);
|
||||||
|
} else {
|
||||||
this->BHPTarget = record.getItem("BHP").get<UDAValue>(0);
|
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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
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->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 );
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user