mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4819 from hakonhagland/gecon3
Implement support for GECON keyword
This commit is contained in:
commit
80cbfe7fda
@ -100,6 +100,7 @@ list (APPEND MAIN_SOURCE_FILES
|
|||||||
opm/simulators/wells/GasLiftSingleWellGeneric.cpp
|
opm/simulators/wells/GasLiftSingleWellGeneric.cpp
|
||||||
opm/simulators/wells/GasLiftStage2.cpp
|
opm/simulators/wells/GasLiftStage2.cpp
|
||||||
opm/simulators/wells/GlobalWellInfo.cpp
|
opm/simulators/wells/GlobalWellInfo.cpp
|
||||||
|
opm/simulators/wells/GroupEconomicLimitsChecker.cpp
|
||||||
opm/simulators/wells/GroupState.cpp
|
opm/simulators/wells/GroupState.cpp
|
||||||
opm/simulators/wells/MSWellHelpers.cpp
|
opm/simulators/wells/MSWellHelpers.cpp
|
||||||
opm/simulators/wells/MultisegmentWellAssemble.cpp
|
opm/simulators/wells/MultisegmentWellAssemble.cpp
|
||||||
@ -537,6 +538,7 @@ list (APPEND PUBLIC_HEADER_FILES
|
|||||||
opm/simulators/wells/GasLiftStage2.hpp
|
opm/simulators/wells/GasLiftStage2.hpp
|
||||||
opm/simulators/wells/GasLiftWellState.hpp
|
opm/simulators/wells/GasLiftWellState.hpp
|
||||||
opm/simulators/wells/GlobalWellInfo.hpp
|
opm/simulators/wells/GlobalWellInfo.hpp
|
||||||
|
opm/simulators/wells/GroupEconomicLimitsChecker.hpp
|
||||||
opm/simulators/wells/GroupState.hpp
|
opm/simulators/wells/GroupState.hpp
|
||||||
opm/simulators/wells/MSWellHelpers.hpp
|
opm/simulators/wells/MSWellHelpers.hpp
|
||||||
opm/simulators/wells/MultisegmentWell.hpp
|
opm/simulators/wells/MultisegmentWell.hpp
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Action/State.hpp>
|
#include <opm/input/eclipse/Schedule/Action/State.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>
|
||||||
|
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Network/Balance.hpp>
|
#include <opm/input/eclipse/Schedule/Network/Balance.hpp>
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Action/Actions.hpp>
|
#include <opm/input/eclipse/Schedule/Action/Actions.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Action/ASTNode.hpp>
|
#include <opm/input/eclipse/Schedule/Action/ASTNode.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Action/State.hpp>
|
#include <opm/input/eclipse/Schedule/Action/State.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||||
|
@ -104,6 +104,13 @@ partiallySupported()
|
|||||||
{21,{true, allow_values<std::string> {"NONE"}, "GCONPROD(COMBPROC): linearly combined procedure is not used and should be defaulted (1*)"}}, // LIN_TARGET_EXCEED_PROCEDURE
|
{21,{true, allow_values<std::string> {"NONE"}, "GCONPROD(COMBPROC): linearly combined procedure is not used and should be defaulted (1*)"}}, // LIN_TARGET_EXCEED_PROCEDURE
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"GECON",
|
||||||
|
{
|
||||||
|
{7,{true, allow_values<std::string> {"NONE"}, "GECON(WORKOVER): Workover procedures not implemented"}},
|
||||||
|
{8,{true, allow_values<std::string> {"NO"}, "GECON(ENDRUN): End run not implemented"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"GEFAC",
|
"GEFAC",
|
||||||
{
|
{
|
||||||
|
@ -226,7 +226,6 @@ const KeywordValidation::UnsupportedKeywords& unsupportedKeywords()
|
|||||||
{"GDIMS", {true, std::nullopt}},
|
{"GDIMS", {true, std::nullopt}},
|
||||||
{"GDORIENT", {false, std::nullopt}},
|
{"GDORIENT", {false, std::nullopt}},
|
||||||
{"GDRILPOT", {true, std::nullopt}},
|
{"GDRILPOT", {true, std::nullopt}},
|
||||||
{"GECON", {true, std::nullopt}},
|
|
||||||
{"GECONT", {true, std::nullopt}},
|
{"GECONT", {true, std::nullopt}},
|
||||||
{"GETGLOB", {true, std::nullopt}},
|
{"GETGLOB", {true, std::nullopt}},
|
||||||
{"GI", {true, std::nullopt}},
|
{"GI", {true, std::nullopt}},
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||||
@ -49,6 +50,7 @@
|
|||||||
#include <opm/simulators/wells/BlackoilWellModelGuideRates.hpp>
|
#include <opm/simulators/wells/BlackoilWellModelGuideRates.hpp>
|
||||||
#include <opm/simulators/wells/BlackoilWellModelRestart.hpp>
|
#include <opm/simulators/wells/BlackoilWellModelRestart.hpp>
|
||||||
#include <opm/simulators/wells/GasLiftStage2.hpp>
|
#include <opm/simulators/wells/GasLiftStage2.hpp>
|
||||||
|
#include <opm/simulators/wells/GroupEconomicLimitsChecker.hpp>
|
||||||
#include <opm/simulators/wells/ParallelWBPCalculation.hpp>
|
#include <opm/simulators/wells/ParallelWBPCalculation.hpp>
|
||||||
#include <opm/simulators/wells/VFPProperties.hpp>
|
#include <opm/simulators/wells/VFPProperties.hpp>
|
||||||
#include <opm/simulators/wells/WellFilterCake.hpp>
|
#include <opm/simulators/wells/WellFilterCake.hpp>
|
||||||
@ -376,6 +378,41 @@ initializeWellPerfData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BlackoilWellModelGeneric::
|
||||||
|
checkGEconLimits(
|
||||||
|
const Group& group,
|
||||||
|
const double simulation_time,
|
||||||
|
const int report_step_idx,
|
||||||
|
DeferredLogger& deferred_logger)
|
||||||
|
{
|
||||||
|
// call recursively down the group hiearchy
|
||||||
|
for (const std::string& group_name : group.groups()) {
|
||||||
|
checkGEconLimits( schedule().getGroup(group_name, report_step_idx),
|
||||||
|
simulation_time, report_step_idx, deferred_logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if gecon is used for this group
|
||||||
|
if (!schedule()[report_step_idx].gecon().has_group(group.name())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupEconomicLimitsChecker checker {
|
||||||
|
*this, wellTestState(), group, simulation_time, report_step_idx, deferred_logger
|
||||||
|
};
|
||||||
|
if (checker.minOilRate() || checker.minGasRate()) {
|
||||||
|
checker.closeWells();
|
||||||
|
}
|
||||||
|
else if (checker.waterCut() || checker.GOR() || checker.WGR()) {
|
||||||
|
checker.doWorkOver();
|
||||||
|
}
|
||||||
|
if (checker.endRun() && (checker.numProducersOpenInitially() >= 1)
|
||||||
|
&& (checker.numProducersOpen() == 0))
|
||||||
|
{
|
||||||
|
checker.activateEndRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BlackoilWellModelGeneric::
|
BlackoilWellModelGeneric::
|
||||||
checkGconsaleLimits(const Group& group,
|
checkGconsaleLimits(const Group& group,
|
||||||
|
@ -191,6 +191,10 @@ public:
|
|||||||
bool shouldBalanceNetwork(const int reportStepIndex,
|
bool shouldBalanceNetwork(const int reportStepIndex,
|
||||||
const int iterationIdx) const;
|
const int iterationIdx) const;
|
||||||
|
|
||||||
|
void updateClosedWellsThisStep(const std::string& well_name) const {
|
||||||
|
this->closed_this_step_.insert(well_name);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Serializer>
|
template<class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
{
|
{
|
||||||
@ -345,6 +349,11 @@ protected:
|
|||||||
const int reportStepIdx,
|
const int reportStepIdx,
|
||||||
DeferredLogger& deferred_logger);
|
DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
|
void checkGEconLimits(const Group& group,
|
||||||
|
const double simulation_time,
|
||||||
|
const int report_step_idx,
|
||||||
|
DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
bool checkGroupHigherConstraints(const Group& group,
|
bool checkGroupHigherConstraints(const Group& group,
|
||||||
DeferredLogger& deferred_logger,
|
DeferredLogger& deferred_logger,
|
||||||
const int reportStepIdx);
|
const int reportStepIdx);
|
||||||
|
@ -657,6 +657,8 @@ namespace Opm {
|
|||||||
|
|
||||||
// check group sales limits at the end of the timestep
|
// check group sales limits at the end of the timestep
|
||||||
const Group& fieldGroup = schedule_.getGroup("FIELD", reportStepIdx);
|
const Group& fieldGroup = schedule_.getGroup("FIELD", reportStepIdx);
|
||||||
|
checkGEconLimits(
|
||||||
|
fieldGroup, simulationTime, ebosSimulator_.episodeIndex(), local_deferredLogger);
|
||||||
checkGconsaleLimits(fieldGroup, this->wellState(),
|
checkGconsaleLimits(fieldGroup, this->wellState(),
|
||||||
ebosSimulator_.episodeIndex(), local_deferredLogger);
|
ebosSimulator_.episodeIndex(), local_deferredLogger);
|
||||||
|
|
||||||
|
324
opm/simulators/wells/GroupEconomicLimitsChecker.cpp
Normal file
324
opm/simulators/wells/GroupEconomicLimitsChecker.cpp
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2023 Equinor ASA.
|
||||||
|
|
||||||
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
|
OPM is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OPM is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||||
|
#include <opm/simulators/wells/GroupEconomicLimitsChecker.hpp>
|
||||||
|
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
namespace Opm {
|
||||||
|
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
GroupEconomicLimitsChecker(
|
||||||
|
const BlackoilWellModelGeneric &well_model,
|
||||||
|
WellTestState &well_test_state,
|
||||||
|
const Group &group,
|
||||||
|
const double simulation_time,
|
||||||
|
const int report_step_idx,
|
||||||
|
DeferredLogger &deferred_logger
|
||||||
|
) :
|
||||||
|
well_model_{well_model}
|
||||||
|
, group_{group}
|
||||||
|
, simulation_time_{simulation_time}
|
||||||
|
, report_step_idx_{report_step_idx}
|
||||||
|
, deferred_logger_{deferred_logger}
|
||||||
|
, well_state_{well_model.wellState()}
|
||||||
|
, well_test_state_{well_test_state}
|
||||||
|
, schedule_{well_model.schedule()}
|
||||||
|
, gecon_props_{schedule_[report_step_idx_].gecon().get_group_prop(
|
||||||
|
schedule_, well_model_.summaryState(), group_.name())}
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < this->phase_idx_map_.size(); i++) {
|
||||||
|
auto phase_idx = this->phase_idx_map_[i];
|
||||||
|
this->phase_idx_reverse_map_[phase_idx] = static_cast<int>(i);
|
||||||
|
auto phase_pos = this->well_model_.phaseUsage().phase_pos[phase_idx];
|
||||||
|
double production_rate = WellGroupHelpers::sumWellSurfaceRates(
|
||||||
|
this->group_, this->schedule_, this->well_state_,
|
||||||
|
this->report_step_idx_, phase_pos, /*isInjector*/false);
|
||||||
|
this->production_rates_[i] = this->well_model_.comm().sum(production_rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************
|
||||||
|
* Public methods in alphabetical order
|
||||||
|
****************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
activateEndRun()
|
||||||
|
{
|
||||||
|
displayDebugMessage("activate end run");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
closeWells()
|
||||||
|
{
|
||||||
|
closeWellsRecursive(this->group_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
doWorkOver()
|
||||||
|
{
|
||||||
|
if (this->gecon_props_.workover() != GroupEconProductionLimits::EconWorkover::NONE) {
|
||||||
|
throwNotImplementedError("workover procedure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
endRun()
|
||||||
|
{
|
||||||
|
if (this->gecon_props_.endRun()) {
|
||||||
|
throwNotImplementedError("end run flag YES");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
GOR()
|
||||||
|
{
|
||||||
|
auto oil_phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Liquid];
|
||||||
|
auto gas_phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Vapour];
|
||||||
|
auto oil_rate = this->production_rates_[oil_phase_idx];
|
||||||
|
auto gas_rate = this->production_rates_[gas_phase_idx];
|
||||||
|
double gor;
|
||||||
|
if (gas_rate <= 0.0) {
|
||||||
|
gor = 0.0;
|
||||||
|
}
|
||||||
|
else if (oil_rate <= 0.0) {
|
||||||
|
gor = 1e100;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gor = gas_rate / oil_rate;
|
||||||
|
}
|
||||||
|
if (auto max_gor = this->gecon_props_.maxGasOilRatio(); max_gor) {
|
||||||
|
if (gor > *max_gor) {
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"GOR={} is greater than maximum: {}",
|
||||||
|
gor, *max_gor);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
minGasRate()
|
||||||
|
{
|
||||||
|
auto phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Vapour];
|
||||||
|
auto gas_production_rate = this->production_rates_[phase_idx];
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"gecon: group: {}, gas_rate={}", this->group_.name(), gas_production_rate);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
if (auto min_gas_rate = this->gecon_props_.minGasRate(); min_gas_rate) {
|
||||||
|
if (gas_production_rate < *min_gas_rate) {
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"gas_rate={} is less than minimum: {}",
|
||||||
|
gas_production_rate, *min_gas_rate);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
minOilRate()
|
||||||
|
{
|
||||||
|
auto phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Liquid];
|
||||||
|
auto oil_production_rate = this->production_rates_[phase_idx];
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"oil_rate={}", oil_production_rate);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
if (auto min_oil_rate = this->gecon_props_.minOilRate(); min_oil_rate) {
|
||||||
|
if (oil_production_rate < *min_oil_rate) {
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"oil_rate={} is less than minimum: {}",
|
||||||
|
oil_production_rate, *min_oil_rate);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
numProducersOpen()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
numProducersOpenInitially()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
waterCut()
|
||||||
|
{
|
||||||
|
auto oil_phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Liquid];
|
||||||
|
auto water_phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Aqua];
|
||||||
|
auto oil_rate = this->production_rates_[oil_phase_idx];
|
||||||
|
auto water_rate = this->production_rates_[water_phase_idx];
|
||||||
|
auto liquid_rate = oil_rate + water_rate;
|
||||||
|
double water_cut;
|
||||||
|
if (liquid_rate == 0.0) {
|
||||||
|
water_cut = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (water_rate < 0.0) {
|
||||||
|
water_cut = 0.0;
|
||||||
|
}
|
||||||
|
else if (oil_rate < 0.0) {
|
||||||
|
water_cut = 1.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
water_cut = water_rate / liquid_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (auto max_water_cut = this->gecon_props_.maxWaterCut(); max_water_cut) {
|
||||||
|
if (water_cut > *max_water_cut) {
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"water_cut={} is greater than maximum: {}",
|
||||||
|
water_cut, *max_water_cut);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
WGR()
|
||||||
|
{
|
||||||
|
auto water_phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Aqua];
|
||||||
|
auto gas_phase_idx = this->phase_idx_reverse_map_[BlackoilPhases::Vapour];
|
||||||
|
auto water_rate = this->production_rates_[water_phase_idx];
|
||||||
|
auto gas_rate = this->production_rates_[gas_phase_idx];
|
||||||
|
double wgr;
|
||||||
|
if (water_rate <= 0.0) {
|
||||||
|
wgr = 0.0;
|
||||||
|
}
|
||||||
|
else if (gas_rate <= 0.0) {
|
||||||
|
wgr = 1e100;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wgr = water_rate / gas_rate;
|
||||||
|
}
|
||||||
|
if (auto max_wgr = this->gecon_props_.maxWaterGasRatio(); max_wgr) {
|
||||||
|
if (wgr > *max_wgr) {
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"WGR={} is greater than maximum: {}",
|
||||||
|
wgr, *max_wgr);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************
|
||||||
|
* Private methods in alphabetical order
|
||||||
|
****************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
displayDebugMessage(const std::string &msg) const
|
||||||
|
{
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg2 = fmt::format(
|
||||||
|
"GECON: group: {} : {}", this->group_.name(), msg);
|
||||||
|
this->deferred_logger_.debug(msg2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
closeWellsRecursive(Group group)
|
||||||
|
{
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format("closing wells recursive : group {} ", group.name());
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
for (const std::string& group_name : group.groups()) {
|
||||||
|
auto next_group = this->schedule_.getGroup(group_name, this->report_step_idx_);
|
||||||
|
closeWellsRecursive(next_group);
|
||||||
|
}
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format("closing wells recursive : group {} has {} wells",
|
||||||
|
group.name(), group.wells().size());
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const std::string& well_name : group.wells()) {
|
||||||
|
if (this->well_test_state_.well_is_closed(well_name)) {
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"well {} is already closed", well_name);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this->debug_) {
|
||||||
|
const std::string msg = fmt::format(
|
||||||
|
"closing well {}", well_name);
|
||||||
|
displayDebugMessage(msg);
|
||||||
|
}
|
||||||
|
this->well_test_state_.close_well(
|
||||||
|
well_name, WellTestConfig::Reason::ECONOMIC, this->simulation_time_);
|
||||||
|
this->well_model_.updateClosedWellsThisStep(well_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupEconomicLimitsChecker::
|
||||||
|
throwNotImplementedError(const std::string &error) const
|
||||||
|
{
|
||||||
|
const std::string msg = fmt::format("Group: {} : GECON : {} not implemented", this->group_.name(), error);
|
||||||
|
OPM_DEFLOG_THROW(std::runtime_error, msg, this->deferred_logger_);
|
||||||
|
}
|
||||||
|
} // namespace Opm
|
81
opm/simulators/wells/GroupEconomicLimitsChecker.hpp
Normal file
81
opm/simulators/wells/GroupEconomicLimitsChecker.hpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2023 Equinor ASA.
|
||||||
|
|
||||||
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
|
OPM is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OPM is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPM_GROUP_ECONOMIC_LIMITS_CHECKER_HEADER_INCLUDED
|
||||||
|
#define OPM_GROUP_ECONOMIC_LIMITS_CHECKER_HEADER_INCLUDED
|
||||||
|
|
||||||
|
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
|
||||||
|
#include <opm/simulators/utils/DeferredLogger.hpp>
|
||||||
|
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||||
|
#include <opm/simulators/wells/WellState.hpp>
|
||||||
|
#include <opm/core/props/BlackoilPhases.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
|
namespace Opm
|
||||||
|
{
|
||||||
|
class GroupEconomicLimitsChecker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GroupEconomicLimitsChecker(
|
||||||
|
const BlackoilWellModelGeneric &well_model,
|
||||||
|
WellTestState &well_test_state,
|
||||||
|
const Group &group,
|
||||||
|
const double simulation_time,
|
||||||
|
const int report_step_idx,
|
||||||
|
DeferredLogger &deferred_logger
|
||||||
|
);
|
||||||
|
void closeWells();
|
||||||
|
bool minGasRate();
|
||||||
|
bool minOilRate();
|
||||||
|
bool waterCut();
|
||||||
|
bool GOR();
|
||||||
|
bool WGR();
|
||||||
|
void doWorkOver();
|
||||||
|
bool endRun();
|
||||||
|
int numProducersOpenInitially();
|
||||||
|
int numProducersOpen();
|
||||||
|
void activateEndRun();
|
||||||
|
|
||||||
|
static constexpr int NUM_PHASES = 3;
|
||||||
|
private:
|
||||||
|
void displayDebugMessage(const std::string &msg) const;
|
||||||
|
void closeWellsRecursive(Group group);
|
||||||
|
void throwNotImplementedError(const std::string &error) const;
|
||||||
|
const BlackoilWellModelGeneric &well_model_;
|
||||||
|
const Group &group_;
|
||||||
|
const double simulation_time_;
|
||||||
|
const int report_step_idx_;
|
||||||
|
DeferredLogger &deferred_logger_;
|
||||||
|
const WellState &well_state_;
|
||||||
|
WellTestState &well_test_state_;
|
||||||
|
const Schedule &schedule_;
|
||||||
|
GroupEconProductionLimits::GEconGroupProp gecon_props_;
|
||||||
|
bool debug_ = true;
|
||||||
|
double production_rates_[NUM_PHASES];
|
||||||
|
std::map<int, BlackoilPhases::PhaseIndex> phase_idx_map_ = {
|
||||||
|
{0, BlackoilPhases::Liquid},
|
||||||
|
{1, BlackoilPhases::Vapour},
|
||||||
|
{2, BlackoilPhases::Aqua}};
|
||||||
|
std::map<BlackoilPhases::PhaseIndex, int> phase_idx_reverse_map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Opm
|
||||||
|
|
||||||
|
#endif // OPM_GROUP_ECONOMIC_LIMITS_CHECKER_HEADER_INCLUDED
|
@ -63,6 +63,7 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Action/Condition.hpp>
|
#include <opm/input/eclipse/Schedule/Action/Condition.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Events.hpp>
|
#include <opm/input/eclipse/Schedule/Events.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
|
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
||||||
|
Loading…
Reference in New Issue
Block a user