diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index 94bfc6f90..232a2cde4 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -1044,6 +1044,7 @@ BlackoilWellModelGeneric:: gasLiftOptimizationStage2(DeferredLogger& deferred_logger, GLiftProdWells& prod_wells, GLiftOptWells& glift_wells, + GasLiftGroupInfo& group_info, GLiftWellStateMap& glift_well_state_map, const int episodeIndex) { @@ -1053,8 +1054,10 @@ gasLiftOptimizationStage2(DeferredLogger& deferred_logger, summaryState_, deferred_logger, this->wellState(), + this->groupState(), prod_wells, glift_wells, + group_info, glift_well_state_map, this->glift_debug }; diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index 48fd43362..9f90d9ca9 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -47,6 +47,7 @@ namespace Opm { class EclipseState; class GasLiftSingleWellGeneric; class GasLiftWellState; + class GasLiftGroupInfo; class Group; class GuideRateConfig; class ParallelWellInfo; @@ -305,6 +306,7 @@ protected: void gasLiftOptimizationStage2(DeferredLogger& deferred_logger, GLiftProdWells& prod_wells, GLiftOptWells& glift_wells, + GasLiftGroupInfo& group_info, GLiftWellStateMap& map, const int episodeIndex); diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index ff0fdfaac..2de06057a 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -986,6 +986,7 @@ namespace Opm { phase_usage_, deferred_logger, this->wellState(), + this->groupState(), ebosSimulator_.vanguard().grid().comm(), this->glift_debug }; @@ -993,7 +994,7 @@ namespace Opm { gasLiftOptimizationStage1( deferred_logger, prod_wells, glift_wells, group_info, state_map); gasLiftOptimizationStage2( - deferred_logger, prod_wells, glift_wells, state_map, + deferred_logger, prod_wells, glift_wells, group_info, state_map, ebosSimulator_.episodeIndex()); if (this->glift_debug) gliftDebugShowALQ(deferred_logger); num_wells_changed = glift_wells.size(); diff --git a/opm/simulators/wells/GasLiftCommon.cpp b/opm/simulators/wells/GasLiftCommon.cpp index b9cf16c25..a2298178c 100644 --- a/opm/simulators/wells/GasLiftCommon.cpp +++ b/opm/simulators/wells/GasLiftCommon.cpp @@ -25,11 +25,13 @@ namespace Opm { GasLiftCommon:: GasLiftCommon( WellState &well_state, + const GroupState &group_state, DeferredLogger &deferred_logger, const Parallel::Communication& comm, bool glift_debug ) : well_state_{well_state}, + group_state_{group_state}, deferred_logger_{deferred_logger}, comm_{comm}, debug{glift_debug} diff --git a/opm/simulators/wells/GasLiftCommon.hpp b/opm/simulators/wells/GasLiftCommon.hpp index deb74b8ff..308f7adc4 100644 --- a/opm/simulators/wells/GasLiftCommon.hpp +++ b/opm/simulators/wells/GasLiftCommon.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -36,6 +37,7 @@ public: protected: GasLiftCommon( WellState &well_state, + const GroupState &group_state, DeferredLogger &deferred_logger, const Parallel::Communication& comm, bool debug @@ -51,6 +53,7 @@ protected: MessageType msg_type = MessageType::INFO) const; WellState &well_state_; + const GroupState& group_state_; DeferredLogger &deferred_logger_; const Parallel::Communication& comm_; bool debug; diff --git a/opm/simulators/wells/GasLiftGroupInfo.cpp b/opm/simulators/wells/GasLiftGroupInfo.cpp index 9a50025dd..2c5eb1b70 100644 --- a/opm/simulators/wells/GasLiftGroupInfo.cpp +++ b/opm/simulators/wells/GasLiftGroupInfo.cpp @@ -32,10 +32,11 @@ GasLiftGroupInfo( const PhaseUsage &phase_usage, DeferredLogger &deferred_logger, WellState &well_state, + const GroupState &group_state, const Communication &comm, bool glift_debug ) : - GasLiftCommon(well_state, deferred_logger, comm, glift_debug) + GasLiftCommon(well_state, group_state, deferred_logger, comm, glift_debug) , ecl_wells_{ecl_wells} , schedule_{schedule} , summary_state_{summary_state} @@ -74,6 +75,28 @@ gasRate(const std::string& group_name) const return group_rate.gasRate(); } +double +GasLiftGroupInfo:: +gasPotential(const std::string& group_name) const +{ + auto& group_rate = this->group_rate_map_.at(group_name); + return group_rate.gasPotential(); +} +double +GasLiftGroupInfo:: +waterPotential(const std::string& group_name) const +{ + auto& group_rate = this->group_rate_map_.at(group_name); + return group_rate.waterPotential(); +} +double +GasLiftGroupInfo:: +oilPotential(const std::string& group_name) const +{ + auto& group_rate = this->group_rate_map_.at(group_name); + return group_rate.oilPotential(); +} + std::optional GasLiftGroupInfo:: gasTarget(const std::string& group_name) const @@ -100,6 +123,24 @@ getRate(Rate rate_type, const std::string& group_name) const throw std::runtime_error("This should not happen"); } } +double +GasLiftGroupInfo:: +getPotential(Rate rate_type, const std::string& group_name) const +{ + switch (rate_type) { + case Rate::oil: + return oilPotential(group_name); + case Rate::gas: + return gasPotential(group_name); + case Rate::water: + return waterPotential(group_name); + case Rate::liquid: + return oilPotential(group_name) + waterPotential(group_name); + default: + // Need this to avoid compiler warning : control reaches end of non-void function + throw std::runtime_error("This should not happen"); + } +} std::tuple GasLiftGroupInfo:: @@ -437,36 +478,56 @@ displayDebugMessage_(const std::string &msg, const std::string &well_name) } -std::tuple +std::tuple GasLiftGroupInfo:: -getProducerWellRates_(int well_index) +getProducerWellRates_(const Well* well, int well_index) { const auto& pu = this->phase_usage_; const auto& ws= this->well_state_.well(well_index); const auto& wrate = ws.well_potentials; - const auto oil_rate = pu.phase_used[Oil] + const auto oil_pot = pu.phase_used[Oil] ? wrate[pu.phase_pos[Oil]] : 0.0; - const auto gas_rate = pu.phase_used[Gas] + const auto gas_pot = pu.phase_used[Gas] ? wrate[pu.phase_pos[Gas]] : 0.0; - const auto water_rate = pu.phase_used[Water] + const auto water_pot = pu.phase_used[Water] ? wrate[pu.phase_pos[Water]] : 0.0; - return {oil_rate, gas_rate, water_rate}; + const auto controls = well->productionControls(this->summary_state_); + double oil_rate = oil_pot; + if (controls.hasControl(Well::ProducerCMode::ORAT)) { + oil_rate = std::min(controls.oil_rate, oil_rate); + } + double gas_rate = gas_pot; + if (controls.hasControl(Well::ProducerCMode::GRAT)) { + gas_rate = std::min(controls.gas_rate, gas_rate); + } + double water_rate = water_pot; + if (controls.hasControl(Well::ProducerCMode::WRAT)) { + water_rate = std::min(controls.water_rate, water_rate); + } + if (controls.hasControl(Well::ProducerCMode::LRAT)) { + double liquid_rate = oil_rate + water_rate; + double liquid_rate_lim = std::min(controls.liquid_rate, liquid_rate); + water_rate = water_rate / liquid_rate * liquid_rate_lim; + oil_rate = oil_rate / liquid_rate * liquid_rate_lim; + } + + return {oil_rate, gas_rate, water_rate, oil_pot, gas_pot, water_pot}; } -std::tuple +std::tuple GasLiftGroupInfo:: initializeGroupRatesRecursive_(const Group &group) { - std::array rates{}; + std::array rates{}; if (this->debug) debugStartInitializeGroup(group.name()); - auto& [oil_rate, water_rate, gas_rate, alq] = rates; + auto& [oil_rate, water_rate, gas_rate, oil_potential, water_potential, gas_potential, alq] = rates; if (group.wellgroup()) { for (const std::string& well_name : group.wells()) { // NOTE: we cannot simply use: @@ -481,17 +542,21 @@ initializeGroupRatesRecursive_(const Group &group) assert(well); // Should never be nullptr const int index = (itr->second).second; if (well->isProducer()) { - auto [sw_oil_rate, sw_gas_rate, sw_water_rate] = getProducerWellRates_(index); + auto [sw_oil_rate, sw_gas_rate, sw_water_rate, sw_oil_pot, sw_gas_pot, sw_water_pot] = getProducerWellRates_(well, index); auto sw_alq = this->well_state_.getALQ(well_name); double factor = well->getEfficiencyFactor(); oil_rate += (factor * sw_oil_rate); gas_rate += (factor * sw_gas_rate); water_rate += (factor * sw_water_rate); + oil_potential += (factor * sw_oil_pot); + gas_potential += (factor * sw_gas_pot); + water_potential += (factor * sw_water_pot); + alq += (factor * sw_alq); if (this->debug) { debugDisplayWellContribution_( group.name(), well_name, factor, - sw_oil_rate, sw_gas_rate, sw_water_rate, sw_alq, + sw_oil_pot, sw_gas_pot, sw_water_pot, sw_alq, oil_rate, gas_rate, water_rate, alq ); } @@ -506,12 +571,16 @@ initializeGroupRatesRecursive_(const Group &group) continue; const Group& sub_group = this->schedule_.getGroup( group_name, this->report_step_idx_); - auto [sg_oil_rate, sg_gas_rate, sg_water_rate, sg_alq] + auto [sg_oil_rate, sg_gas_rate, sg_water_rate, + sg_oil_pot, sg_gas_pot, sg_water_pot, sg_alq] = initializeGroupRatesRecursive_(sub_group); const auto gefac = sub_group.getGroupEfficiencyFactor(); oil_rate += (gefac * sg_oil_rate); gas_rate += (gefac * sg_gas_rate); water_rate += (gefac * sg_water_rate); + oil_potential += (gefac * sg_oil_pot); + gas_potential += (gefac * sg_gas_pot); + water_potential += (gefac * sg_water_pot); alq += (gefac * sg_alq); } } @@ -537,14 +606,29 @@ initializeGroupRatesRecursive_(const Group &group) } if (oil_target || liquid_target || water_target || gas_target || max_total_gas || max_alq) { updateGroupIdxMap_(group.name()); + if(oil_target) + oil_rate = std::min(oil_rate, *oil_target); + if(gas_target) + gas_rate = std::min(gas_rate, *gas_target); + if(water_target) + water_rate = std::min(water_rate, *water_target); + if(liquid_target) { + double liquid_rate = oil_rate + water_rate; + double liquid_rate_limited = std::min(liquid_rate, *liquid_target); + oil_rate = oil_rate / liquid_rate * liquid_rate_limited; + water_rate = water_rate / liquid_rate * liquid_rate_limited; + } + this->group_rate_map_.try_emplace(group.name(), - oil_rate, gas_rate, water_rate, alq, oil_target, gas_target, water_target, liquid_target, max_total_gas, max_alq); + oil_rate, gas_rate, water_rate, alq, + oil_potential, gas_potential, water_potential, + oil_target, gas_target, water_target, liquid_target, max_total_gas, max_alq); if (this->debug) { debugDisplayUpdatedGroupRates( group.name(), oil_rate, gas_rate, water_rate, alq); } } - return std::make_tuple(oil_rate, gas_rate, water_rate, alq); + return std::make_tuple(oil_rate, gas_rate, water_rate, oil_potential, gas_potential, water_potential, alq); } void diff --git a/opm/simulators/wells/GasLiftGroupInfo.hpp b/opm/simulators/wells/GasLiftGroupInfo.hpp index 910108c8f..d4322ec5b 100644 --- a/opm/simulators/wells/GasLiftGroupInfo.hpp +++ b/opm/simulators/wells/GasLiftGroupInfo.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,7 @@ public: const PhaseUsage& phase_usage, DeferredLogger& deferred_logger, WellState& well_state, + const GroupState& group_state, const Parallel::Communication& comm, bool glift_debug ); @@ -89,8 +91,12 @@ public: double alqRate(const std::string& group_name); double gasRate(const std::string& group_name) const; + double gasPotential(const std::string& group_name) const; + double waterPotential(const std::string& group_name) const; + double oilPotential(const std::string& group_name) const; int getGroupIdx(const std::string& group_name); double getRate(Rate rate_type, const std::string& group_name) const; + double getPotential(Rate rate_type, const std::string& group_name) const; std::tuple getRates(const int group_idx) const; std::optional gasTarget(const std::string& group_name) const; std::optional getTarget( @@ -128,8 +134,9 @@ protected: void debugStartInitializeGroup(const std::string& name) const; void displayDebugMessage_(const std::string& msg) const override; void displayDebugMessage_(const std::string& msg, const std::string& well_name); - std::tuple getProducerWellRates_(const int index); - std::tuple + std::tuple + getProducerWellRates_(const Well* well, const int index); + std::tuple initializeGroupRatesRecursive_(const Group &group); void initializeWell2GroupMapRecursive_( const Group& group, std::vector& group_names, @@ -140,6 +147,7 @@ protected: class GroupRates { public: GroupRates( double oil_rate, double gas_rate, double water_rate, double alq, + double oil_potential, double gas_potential, double water_potential, std::optional oil_target, std::optional gas_target, std::optional water_target, @@ -151,6 +159,9 @@ protected: gas_rate_{gas_rate}, water_rate_{water_rate}, alq_{alq}, + oil_potential_{oil_potential}, + gas_potential_{gas_potential}, + water_potential_{water_potential}, oil_target_{oil_target}, gas_target_{gas_target}, water_target_{water_target}, @@ -175,6 +186,9 @@ protected: double oilRate() const { return oil_rate_; } std::optional oilTarget() const { return oil_target_; } std::optional liquidTarget() const { return liquid_target_; } + double oilPotential() const { return oil_potential_; } + double gasPotential() const { return gas_potential_; } + double waterPotential() const { return water_potential_; } void update(double delta_oil, double delta_gas, double delta_water, double delta_alq) { @@ -182,12 +196,17 @@ protected: gas_rate_ += delta_gas; water_rate_ += delta_water; alq_ += delta_alq; + // Note. We don't updata the potentials at this point. They + // are only needed initially. } private: double oil_rate_; double gas_rate_; double water_rate_; double alq_; + double oil_potential_; + double gas_potential_; + double water_potential_; std::optional oil_target_; std::optional gas_target_; std::optional water_target_; diff --git a/opm/simulators/wells/GasLiftSingleWellGeneric.cpp b/opm/simulators/wells/GasLiftSingleWellGeneric.cpp index 65a6607f7..c14ccb9e4 100644 --- a/opm/simulators/wells/GasLiftSingleWellGeneric.cpp +++ b/opm/simulators/wells/GasLiftSingleWellGeneric.cpp @@ -25,8 +25,8 @@ #include #include -#include #include +#include #include @@ -37,29 +37,26 @@ namespace Opm { -GasLiftSingleWellGeneric::GasLiftSingleWellGeneric( - DeferredLogger& deferred_logger, - WellState& well_state, - const GroupState& group_state, - const Well& ecl_well, - const SummaryState& summary_state, - GasLiftGroupInfo& group_info, - const PhaseUsage& phase_usage, - const Schedule& schedule, - const int report_step_idx, - GLiftSyncGroups& sync_groups, - const Parallel::Communication& comm, - bool glift_debug -) : - GasLiftCommon(well_state, deferred_logger, comm, glift_debug) - , group_state_{group_state} - , ecl_well_{ecl_well} - , summary_state_{summary_state} - , group_info_{group_info} - , phase_usage_{phase_usage} - , sync_groups_{sync_groups} - , controls_{ecl_well_.productionControls(summary_state_)} - , debug_limit_increase_decrease_{false} +GasLiftSingleWellGeneric::GasLiftSingleWellGeneric(DeferredLogger& deferred_logger, + WellState& well_state, + const GroupState& group_state, + const Well& ecl_well, + const SummaryState& summary_state, + GasLiftGroupInfo& group_info, + const PhaseUsage& phase_usage, + const Schedule& schedule, + const int report_step_idx, + GLiftSyncGroups& sync_groups, + const Parallel::Communication& comm, + bool glift_debug) + : GasLiftCommon(well_state, group_state, deferred_logger, comm, glift_debug) + , ecl_well_ {ecl_well} + , summary_state_ {summary_state} + , group_info_ {group_info} + , phase_usage_ {phase_usage} + , sync_groups_ {sync_groups} + , controls_ {ecl_well_.productionControls(summary_state_)} + , debug_limit_increase_decrease_ {false} { this->well_name_ = ecl_well_.name(); const GasLiftOpt& glo = schedule.glo(report_step_idx); @@ -71,7 +68,7 @@ GasLiftSingleWellGeneric::GasLiftSingleWellGeneric( // NOTE: This condition was checked in doGasLiftOptimize() in StandardWell // so it can be assumed that increment_ > 0 this->increment_ = glo.gaslift_increment(); - assert( this->increment_ > 0); + assert(this->increment_ > 0); // NOTE: The manual (see LIFTOPT, item 2) does not mention // any default value or restrictions on the economic gradient. // TODO: The value of the gradient would most likely be a positive @@ -88,65 +85,77 @@ GasLiftSingleWellGeneric::GasLiftSingleWellGeneric( ****************************************/ // NOTE: Used from GasLiftStage2 std::optional -GasLiftSingleWellGeneric:: -calcIncOrDecGradient(double oil_rate, double gas_rate, double alq, bool increase) const +GasLiftSingleWellGeneric::calcIncOrDecGradient( + double oil_rate, double gas_rate, double water_rate, double alq, const std::string& gr_name_dont_limit, bool increase) const { auto [new_alq_opt, alq_is_limited] = addOrSubtractAlqIncrement_(alq, increase); // TODO: What to do if ALQ is limited and new_alq != alq? if (!new_alq_opt) return std::nullopt; + double new_alq = *new_alq_opt; + + auto delta_alq = new_alq - alq; + if (checkGroupALQrateExceeded(delta_alq, gr_name_dont_limit)) + return std::nullopt; + if (auto bhp = computeBhpAtThpLimit_(new_alq)) { auto [new_bhp, bhp_is_limited] = getBhpWithLimit_(*bhp); // TODO: What to do if BHP is limited? auto rates = computeWellRates_(new_bhp, bhp_is_limited); - double new_oil_rate, new_gas_rate, new_water_rate; - bool oil_is_limited, gas_is_limited, water_is_limited; - std::tie(new_oil_rate, oil_is_limited) = getOilRateWithLimit_(rates); - std::tie(new_gas_rate, gas_is_limited) = getGasRateWithLimit_(rates); - std::tie(new_water_rate, water_is_limited) = getWaterRateWithLimit_(rates); - if (!increase && new_oil_rate < 0 ) { + // double new_oil_rate, new_gas_rate, new_water_rate; + // bool oil_is_limited, gas_is_limited, water_is_limited; + // std::tie(new_oil_rate, oil_is_limited) = getOilRateWithLimit_(rates); + // std::tie(new_gas_rate, gas_is_limited) = getGasRateWithLimit_(rates); + // std::tie(new_water_rate, water_is_limited) = getWaterRateWithLimit_(rates); + const auto ratesLimited = getLimitedRatesFromRates_(rates); + BasicRates oldrates = {oil_rate, gas_rate, water_rate, false}; + const auto new_rates = updateRatesToGroupLimits_(oldrates, ratesLimited, gr_name_dont_limit); + + if (!increase && new_rates.oil < 0) { return std::nullopt; } - auto grad = calcEcoGradient_( - oil_rate, new_oil_rate, gas_rate, new_gas_rate, increase); - return GradInfo(grad, new_oil_rate, oil_is_limited, - new_gas_rate, gas_is_limited, new_water_rate, water_is_limited, - new_alq, alq_is_limited); - } - else { + auto grad = calcEcoGradient_(oil_rate, new_rates.oil, gas_rate, new_rates.gas, increase); + return GradInfo(grad, + new_rates.oil, + new_rates.oil_is_limited, + new_rates.gas, + new_rates.gas_is_limited, + new_rates.water, + new_rates.water_is_limited, + new_alq, + alq_is_limited); + } else { return std::nullopt; } } std::unique_ptr -GasLiftSingleWellGeneric:: -runOptimize(const int iteration_idx) +GasLiftSingleWellGeneric::runOptimize(const int iteration_idx) { std::unique_ptr state; if (this->optimize_) { if (this->debug_limit_increase_decrease_) { state = runOptimize1_(); - } - else { + } else { state = runOptimize2_(); } if (state) { // NOTE: that state->increase() returns a std::optional, if // this is std::nullopt it means that we was not able to change ALQ // (either increase or decrease) - if (state->increase()) { // ALQ changed.. + if (state->increase()) { // ALQ changed.. double alq = state->alq(); if (this->debug) logSuccess_(alq, iteration_idx); this->well_state_.setALQ(this->well_name_, alq); const auto& pu = this->phase_usage_; std::vector well_pot(pu.num_phases, 0.0); - if(pu.phase_used[BlackoilPhases::PhaseIndex::Liquid]) + if (pu.phase_used[BlackoilPhases::PhaseIndex::Liquid]) well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Liquid]] = state->oilRate(); - if(pu.phase_used[BlackoilPhases::PhaseIndex::Aqua]) + if (pu.phase_used[BlackoilPhases::PhaseIndex::Aqua]) well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Aqua]] = state->waterRate(); - if(pu.phase_used[BlackoilPhases::PhaseIndex::Vapour]) + if (pu.phase_used[BlackoilPhases::PhaseIndex::Vapour]) well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Vapour]] = state->gasRate(); this->well_state_[this->well_name_].well_potentials = well_pot; @@ -161,8 +170,7 @@ runOptimize(const int iteration_idx) ****************************************/ std::pair, bool> -GasLiftSingleWellGeneric:: -addOrSubtractAlqIncrement_(double alq, bool increase) const +GasLiftSingleWellGeneric::addOrSubtractAlqIncrement_(double alq, bool increase) const { bool limited = false; double orig_alq = alq; @@ -175,8 +183,7 @@ addOrSubtractAlqIncrement_(double alq, bool increase) const alq = this->max_alq_; limited = true; } - } - else { // we are decreasing ALQ + } else { // we are decreasing ALQ alq -= this->increment_; if (this->min_alq_ > 0) { // According to WLIFTOPT item 5: If a positive value is @@ -189,8 +196,7 @@ addOrSubtractAlqIncrement_(double alq, bool increase) const alq = this->min_alq_; limited = true; } - } - else { + } else { if (alq < 0) { alq = 0.0; limited = true; @@ -200,16 +206,15 @@ addOrSubtractAlqIncrement_(double alq, bool increase) const std::optional alq_opt {alq}; // If we were not able to change ALQ (to within rounding error), we // return std::nullopt - if (limited && checkALQequal_(orig_alq,alq)) + if (limited && checkALQequal_(orig_alq, alq)) alq_opt = std::nullopt; return {alq_opt, limited}; } double -GasLiftSingleWellGeneric:: -calcEcoGradient_(double oil_rate, double new_oil_rate, double gas_rate, - double new_gas_rate, bool increase) const +GasLiftSingleWellGeneric::calcEcoGradient_( + double oil_rate, double new_oil_rate, double gas_rate, double new_gas_rate, bool increase) const { auto dqo = new_oil_rate - oil_rate; auto dqg = new_gas_rate - gas_rate; @@ -218,41 +223,39 @@ calcEcoGradient_(double oil_rate, double new_oil_rate, double gas_rate, // alpha_g_ * dqg >= 0.0 // // ? - auto gradient = (this->alpha_w_ * dqo) / (this->increment_ + this->alpha_g_*dqg); + auto gradient = (this->alpha_w_ * dqo) / (this->increment_ + this->alpha_g_ * dqg); // TODO: Should we do any error checks on the calculation of the // gradient? - if (!increase) gradient = -gradient; + if (!increase) + gradient = -gradient; return gradient; } bool -GasLiftSingleWellGeneric:: -checkALQequal_(double alq1, double alq2) const +GasLiftSingleWellGeneric::checkALQequal_(double alq1, double alq2) const { - return std::fabs(alq1-alq2) < (this->increment_*ALQ_EPSILON); + return std::fabs(alq1 - alq2) < (this->increment_ * ALQ_EPSILON); } bool -GasLiftSingleWellGeneric:: -checkGroupTargetsViolated( - const BasicRates& rates, const BasicRates& new_rates) const +GasLiftSingleWellGeneric::checkGroupTargetsViolated(const BasicRates& rates, const BasicRates& new_rates) const { - const auto &pairs = - this->group_info_.getWellGroups(this->well_name_); - for (const auto &[group_name, efficiency] : pairs) { + const auto& pairs = this->group_info_.getWellGroups(this->well_name_); + for (const auto& [group_name, efficiency] : pairs) { for (const auto rate_type : {Rate::oil, Rate::gas, Rate::water, Rate::liquid}) { auto target_opt = this->group_info_.getTarget(rate_type, group_name); if (target_opt) { auto delta_rate = new_rates[rate_type] - rates[rate_type]; - auto new_group_rate = this->group_info_.getRate(rate_type, group_name) - + efficiency * delta_rate; + auto new_group_rate = this->group_info_.getPotential(rate_type, group_name) + efficiency * delta_rate; if (new_group_rate > *target_opt) { if (this->debug) { - const std::string msg = fmt::format( - "Group {} : {} rate {} exceeds target {}. Stopping iteration", - group_name, GasLiftGroupInfo::rateToString(rate_type), - new_group_rate, *target_opt); + const std::string msg + = fmt::format("Group {} : {} rate {} exceeds target {}. Stopping iteration", + group_name, + GasLiftGroupInfo::rateToString(rate_type), + new_group_rate, + *target_opt); displayDebugMessage_(msg); } return true; @@ -264,15 +267,15 @@ checkGroupTargetsViolated( } bool -GasLiftSingleWellGeneric:: -checkInitialALQmodified_(double alq, double initial_alq) const +GasLiftSingleWellGeneric::checkInitialALQmodified_(double alq, double initial_alq) const { - if (checkALQequal_(alq,initial_alq)) { + if (checkALQequal_(alq, initial_alq)) { return false; - } - else { + } else { const std::string msg = fmt::format("initial ALQ changed from {} " - "to {} before iteration starts..", initial_alq, alq); + "to {} before iteration starts..", + initial_alq, + alq); displayDebugMessage_(msg); return true; } @@ -295,40 +298,37 @@ computeConvergedBhpAtThpLimitByMaybeIncreasingALQ_() const return {bhp, new_alq}; } -std::pair,double> -GasLiftSingleWellGeneric:: -computeInitialWellRates_() const +std::pair, double> +GasLiftSingleWellGeneric::computeInitialWellRates_() const { std::optional rates; double initial_alq = this->orig_alq_; - //auto alq = initial_alq; - //if (auto bhp = computeBhpAtThpLimit_(this->orig_alq_); bhp) { + // auto alq = initial_alq; + // if (auto bhp = computeBhpAtThpLimit_(this->orig_alq_); bhp) { if (auto [bhp, alq] = computeConvergedBhpAtThpLimitByMaybeIncreasingALQ_(); bhp) { { - const std::string msg = fmt::format( - "computed initial bhp {} given thp limit and given alq {}", *bhp, alq); + const std::string msg = fmt::format("computed initial bhp {} given thp limit and given alq {}", *bhp, alq); displayDebugMessage_(msg); } initial_alq = alq; auto [new_bhp, bhp_is_limited] = getBhpWithLimit_(*bhp); rates = computeWellRates_(new_bhp, bhp_is_limited); if (rates) { - const std::string msg = fmt::format( - "computed initial well potentials given bhp, " - "oil: {}, gas: {}, water: {}", - rates->oil, rates->gas, rates->water); + const std::string msg = fmt::format("computed initial well potentials given bhp, " + "oil: {}, gas: {}, water: {}", + rates->oil, + rates->gas, + rates->water); displayDebugMessage_(msg); } - } - else { + } else { displayDebugMessage_("Aborting optimization."); } return {rates, initial_alq}; } std::optional -GasLiftSingleWellGeneric:: -computeLimitedWellRatesWithALQ_(double alq) const +GasLiftSingleWellGeneric::computeLimitedWellRatesWithALQ_(double alq) const { std::optional limited_rates; if (auto rates = computeWellRatesWithALQ_(alq); rates) { @@ -338,8 +338,7 @@ computeLimitedWellRatesWithALQ_(double alq) const } std::optional -GasLiftSingleWellGeneric:: -computeWellRatesWithALQ_(double alq) const +GasLiftSingleWellGeneric::computeWellRatesWithALQ_(double alq) const { std::optional rates; auto bhp_opt = computeBhpAtThpLimit_(alq); @@ -351,40 +350,50 @@ computeWellRatesWithALQ_(double alq) const } void -GasLiftSingleWellGeneric:: -debugCheckNegativeGradient_(double grad, double alq, double new_alq, - double oil_rate, double new_oil_rate, - double gas_rate, double new_gas_rate, bool increase) const +GasLiftSingleWellGeneric::debugCheckNegativeGradient_(double grad, + double alq, + double new_alq, + double oil_rate, + double new_oil_rate, + double gas_rate, + double new_gas_rate, + bool increase) const { { const std::string msg = fmt::format("calculating gradient: " - "new_oil_rate = {}, oil_rate = {}, grad = {}", new_oil_rate, oil_rate, grad); + "new_oil_rate = {}, oil_rate = {}, grad = {}", + new_oil_rate, + oil_rate, + grad); displayDebugMessage_(msg); } - if (grad < 0 ) { + if (grad < 0) { const std::string msg = fmt::format("negative {} gradient detected ({}) : " - "alq: {}, new_alq: {}, " - "oil_rate: {}, new_oil_rate: {}, gas_rate: {}, new_gas_rate: {}", - (increase ? "incremental" : "decremental"), - grad, alq, new_alq, oil_rate, new_oil_rate, gas_rate, new_gas_rate); + "alq: {}, new_alq: {}, " + "oil_rate: {}, new_oil_rate: {}, gas_rate: {}, new_gas_rate: {}", + (increase ? "incremental" : "decremental"), + grad, + alq, + new_alq, + oil_rate, + new_oil_rate, + gas_rate, + new_gas_rate); displayDebugMessage_(msg); } } void -GasLiftSingleWellGeneric:: -debugShowAlqIncreaseDecreaseCounts_() +GasLiftSingleWellGeneric::debugShowAlqIncreaseDecreaseCounts_() { auto inc_count = this->well_state_.gliftGetAlqIncreaseCount(this->well_name_); auto dec_count = this->well_state_.gliftGetAlqDecreaseCount(this->well_name_); - const std::string msg = - fmt::format("ALQ increase/decrease count : {}/{}", inc_count, dec_count); + const std::string msg = fmt::format("ALQ increase/decrease count : {}/{}", inc_count, dec_count); displayDebugMessage_(msg); } void -GasLiftSingleWellGeneric:: -debugShowBhpAlqTable_() +GasLiftSingleWellGeneric::debugShowBhpAlqTable_() { double alq = 0.0; const std::string fmt_fmt1 {"{:^12s} {:^12s} {:^12s} {:^12s}"}; @@ -393,24 +402,22 @@ debugShowBhpAlqTable_() displayDebugMessage_(header); auto max_it = 50; auto it = 1; - while (alq <= (this->max_alq_+this->increment_)) { + while (alq <= (this->max_alq_ + this->increment_)) { auto bhp_at_thp_limit = computeBhpAtThpLimit_(alq); if (!bhp_at_thp_limit) { const std::string msg = fmt::format("Failed to get converged potentials " - "for ALQ = {}. Skipping.", alq ); + "for ALQ = {}. Skipping.", + alq); displayDebugMessage_(msg); - } - else { + } else { auto [bhp, bhp_is_limited] = getBhpWithLimit_(*bhp_at_thp_limit); auto rates = computeWellRates_(bhp, bhp_is_limited, /*debug_out=*/false); - const std::string msg = fmt::format( - fmt_fmt2, alq, bhp, rates.oil, rates.gas); + const std::string msg = fmt::format(fmt_fmt2, alq, bhp, rates.oil, rates.gas); displayDebugMessage_(msg); } alq += this->increment_; if (it > max_it) { - const std::string msg = fmt::format( - "ALQ table : max iterations {} reached. Stopping iteration.", max_it); + const std::string msg = fmt::format("ALQ table : max iterations {} reached. Stopping iteration.", max_it); displayDebugMessage_(msg); break; } @@ -419,62 +426,49 @@ debugShowBhpAlqTable_() } void -GasLiftSingleWellGeneric:: -debugShowLimitingTargets_(const LimitedRates& rates) const +GasLiftSingleWellGeneric::debugShowLimitingTargets_(const LimitedRates& rates) const { if (rates.limited()) { if (rates.oil_is_limited) { - const std::string msg = fmt::format( - "oil rate {} is limited by {} target", - rates.oil, - GasLiftGroupInfo::rateToString(*(rates.oil_limiting_target))); + const std::string msg = fmt::format("oil rate {} is limited by {} target", + rates.oil, + GasLiftGroupInfo::rateToString(*(rates.oil_limiting_target))); displayDebugMessage_(msg); } if (rates.gas_is_limited) { - const std::string msg = fmt::format( - "gas rate {} is limited by GRAT target", - rates.gas); + const std::string msg = fmt::format("gas rate {} is limited by GRAT target", rates.gas); displayDebugMessage_(msg); } if (rates.water_is_limited) { - const std::string msg = fmt::format( - "water rate {} is limited by {} target", - rates.water, - GasLiftGroupInfo::rateToString(*(rates.water_limiting_target))); + const std::string msg = fmt::format("water rate {} is limited by {} target", + rates.water, + GasLiftGroupInfo::rateToString(*(rates.water_limiting_target))); displayDebugMessage_(msg); } - } - else { + } else { displayDebugMessage_("no rates are currently limited by a target"); } } void -GasLiftSingleWellGeneric:: -debugShowProducerControlMode() const +GasLiftSingleWellGeneric::debugShowProducerControlMode() const { const int well_index = this->well_state_.index(this->well_name_).value(); - const Well::ProducerCMode& control_mode = - this->well_state_.well(well_index).production_cmode; - const std::string msg = fmt::format("Current control mode is: {}", - Well::ProducerCMode2String(control_mode)); + const Well::ProducerCMode& control_mode = this->well_state_.well(well_index).production_cmode; + const std::string msg = fmt::format("Current control mode is: {}", Well::ProducerCMode2String(control_mode)); displayDebugMessage_(msg); } void -GasLiftSingleWellGeneric:: -debugShowStartIteration_(double alq, bool increase, double oil_rate) +GasLiftSingleWellGeneric::debugShowStartIteration_(double alq, bool increase, double oil_rate) { - const std::string msg = - fmt::format("starting {} iteration, ALQ = {}, oilrate = {}", - (increase ? "increase" : "decrease"), - alq, oil_rate); + const std::string msg = fmt::format( + "starting {} iteration, ALQ = {}, oilrate = {}", (increase ? "increase" : "decrease"), alq, oil_rate); displayDebugMessage_(msg); } void -GasLiftSingleWellGeneric:: -debugShowTargets_() +GasLiftSingleWellGeneric::debugShowTargets_() { if (this->controls_.hasControl(Well::ProducerCMode::ORAT)) { auto target = this->controls_.oil_rate; @@ -494,8 +488,7 @@ debugShowTargets_() } void -GasLiftSingleWellGeneric:: -displayDebugMessage_(const std::string& msg) const +GasLiftSingleWellGeneric::displayDebugMessage_(const std::string& msg) const { if (this->debug) { @@ -505,16 +498,14 @@ displayDebugMessage_(const std::string& msg) const } void -GasLiftSingleWellGeneric:: -displayWarning_(const std::string& msg) +GasLiftSingleWellGeneric::displayWarning_(const std::string& msg) { const std::string message = fmt::format("WELL {} : {}", this->well_name_, msg); logMessage_(/*prefix=*/"GLIFT", msg, MessageType::WARNING); } std::pair -GasLiftSingleWellGeneric:: -getBhpWithLimit_(double bhp) const +GasLiftSingleWellGeneric::getBhpWithLimit_(double bhp) const { bool limited = false; if (this->controls_.hasControl(Well::ProducerCMode::BHP)) { @@ -541,8 +532,7 @@ getBhpWithLimit_(double bhp) const // computation of the economic gradient making the gradient // smaller than it should be since the term appears in the denominator. std::pair -GasLiftSingleWellGeneric:: -getGasRateWithLimit_(const BasicRates& rates) const +GasLiftSingleWellGeneric::getGasRateWithLimit_(const BasicRates& rates) const { auto [rate, target_type] = getRateWithLimit_(Rate::gas, rates); bool limited = target_type.has_value(); @@ -559,8 +549,7 @@ getGasRateWithLimit_(const BasicRates& rates) const // also since we also reduced the rate. This might involve // some sort of iteration though.. std::pair -GasLiftSingleWellGeneric:: -getOilRateWithLimit_(const BasicRates& rates) const +GasLiftSingleWellGeneric::getOilRateWithLimit_(const BasicRates& rates) const { auto [rate, target_type] = getRateWithLimit_(Rate::oil, rates); bool limited = target_type.has_value(); @@ -568,15 +557,13 @@ getOilRateWithLimit_(const BasicRates& rates) const } std::pair> -GasLiftSingleWellGeneric:: -getOilRateWithLimit2_(const BasicRates& rates) const +GasLiftSingleWellGeneric::getOilRateWithLimit2_(const BasicRates& rates) const { return getRateWithLimit_(Rate::oil, rates); } std::pair -GasLiftSingleWellGeneric:: -getWaterRateWithLimit_(const BasicRates& rates) const +GasLiftSingleWellGeneric::getWaterRateWithLimit_(const BasicRates& rates) const { auto [rate, target_type] = getRateWithLimit_(Rate::water, rates); bool limited = target_type.has_value(); @@ -584,15 +571,13 @@ getWaterRateWithLimit_(const BasicRates& rates) const } std::pair> -GasLiftSingleWellGeneric:: -getWaterRateWithLimit2_(const BasicRates& rates) const +GasLiftSingleWellGeneric::getWaterRateWithLimit2_(const BasicRates& rates) const { return getRateWithLimit_(Rate::water, rates); } double -GasLiftSingleWellGeneric:: -getRate_(Rate rate, const BasicRates& rates) const +GasLiftSingleWellGeneric::getRate_(Rate rate, const BasicRates& rates) const { switch (rate) { case Rate::oil: @@ -610,8 +595,7 @@ getRate_(Rate rate, const BasicRates& rates) const } double -GasLiftSingleWellGeneric:: -getProductionTarget_(Rate rate) const +GasLiftSingleWellGeneric::getProductionTarget_(Rate rate) const { switch (rate) { case Rate::oil: @@ -629,8 +613,7 @@ getProductionTarget_(Rate rate) const } std::pair> -GasLiftSingleWellGeneric:: -getRateWithLimit_(Rate rate_type, const BasicRates &rates) const +GasLiftSingleWellGeneric::getRateWithLimit_(Rate rate_type, const BasicRates& rates) const { double new_rate = getRate_(rate_type, rates); // If "target_type" is empty at the end of this method, it means the rate @@ -643,20 +626,19 @@ getRateWithLimit_(Rate rate_type, const BasicRates &rates) const if (new_rate > target) { const std::string msg = fmt::format("limiting {} rate to target: " "computed rate: {}, target: {}", - GasLiftGroupInfo::rateToString(rate_type), new_rate, target); + GasLiftGroupInfo::rateToString(rate_type), + new_rate, + target); displayDebugMessage_(msg); new_rate = target; target_type = rate_type; } } - if (((rate_type == Rate::oil) || (rate_type == Rate::water)) - && hasProductionControl_(Rate::liquid)) - { + if (((rate_type == Rate::oil) || (rate_type == Rate::water)) && hasProductionControl_(Rate::liquid)) { double rate2; if (rate_type == Rate::oil) { rate2 = getRate_(Rate::water, rates); - } - else { + } else { rate2 = getRate_(Rate::oil, rates); } // Note: Since "new_rate" was first updated for ORAT or WRAT, see first "if" @@ -677,57 +659,54 @@ getRateWithLimit_(Rate rate_type, const BasicRates &rates) const // limited = true. new_rate = fraction * liq_target; target_type = Rate::liquid; - const std::string msg = fmt::format( - "limiting {} rate to {} due to LRAT target: " - "computed LRAT: {}, target LRAT: {}", - GasLiftGroupInfo::rateToString(rate_type), new_rate, - liq_rate, liq_target); + const std::string msg = fmt::format("limiting {} rate to {} due to LRAT target: " + "computed LRAT: {}, target LRAT: {}", + GasLiftGroupInfo::rateToString(rate_type), + new_rate, + liq_rate, + liq_target); displayDebugMessage_(msg); } } // TODO: Also check RESV target? - return { new_rate, target_type}; + return {new_rate, target_type}; } std::pair -GasLiftSingleWellGeneric:: -getOilRateWithGroupLimit_(double new_oil_rate, double oil_rate) const +GasLiftSingleWellGeneric::getOilRateWithGroupLimit_(double new_oil_rate, double oil_rate, const std::string& gr_name_dont_limit) const { - [[maybe_unused]] auto [rate, gr_name, efficiency] - = getRateWithGroupLimit_(Rate::oil, new_oil_rate, oil_rate); + [[maybe_unused]] auto [rate, gr_name, efficiency] = getRateWithGroupLimit_(Rate::oil, new_oil_rate, oil_rate, gr_name_dont_limit); bool limited = gr_name != nullptr; return {rate, limited}; } std::pair -GasLiftSingleWellGeneric:: -getGasRateWithGroupLimit_(double new_gas_rate, double gas_rate) const +GasLiftSingleWellGeneric::getGasRateWithGroupLimit_(double new_gas_rate, double gas_rate, const std::string& gr_name_dont_limit) const { - [[maybe_unused]] auto [rate, gr_name, efficiency] - = getRateWithGroupLimit_(Rate::gas, new_gas_rate, gas_rate); + [[maybe_unused]] auto [rate, gr_name, efficiency] = getRateWithGroupLimit_(Rate::gas, new_gas_rate, gas_rate, gr_name_dont_limit); bool limited = gr_name != nullptr; return {rate, limited}; } std::pair -GasLiftSingleWellGeneric:: -getWaterRateWithGroupLimit_(double new_water_rate, double water_rate) const +GasLiftSingleWellGeneric::getWaterRateWithGroupLimit_(double new_water_rate, double water_rate, const std::string& gr_name_dont_limit) const { - [[maybe_unused]] auto [rate, gr_name, efficiency] = getRateWithGroupLimit_( - Rate::water, new_water_rate, water_rate); + [[maybe_unused]] auto [rate, gr_name, efficiency] = getRateWithGroupLimit_(Rate::water, new_water_rate, water_rate, gr_name_dont_limit); bool limited = gr_name != nullptr; return {rate, limited}; } std::tuple -GasLiftSingleWellGeneric:: -getLiquidRateWithGroupLimit_(const double new_oil_rate, const double oil_rate, - const double new_water_rate, const double water_rate) const +GasLiftSingleWellGeneric::getLiquidRateWithGroupLimit_(const double new_oil_rate, + const double oil_rate, + const double new_water_rate, + const double water_rate, + const std::string& gr_name_dont_limit) const { auto liquid_rate = oil_rate + water_rate; auto new_liquid_rate = new_oil_rate + new_water_rate; auto [liquid_rate_limited, group_name, efficiency] - = getRateWithGroupLimit_(Rate::liquid, new_liquid_rate, liquid_rate); + = getRateWithGroupLimit_(Rate::liquid, new_liquid_rate, liquid_rate, gr_name_dont_limit); bool limited = group_name != nullptr; if (limited) { // the oil, gas, and water cases can be handled directly by @@ -758,80 +737,80 @@ getLiquidRateWithGroupLimit_(const double new_oil_rate, const double oil_rate, } std::tuple -GasLiftSingleWellGeneric:: -getRateWithGroupLimit_( - Rate rate_type, const double new_rate, const double old_rate) const +GasLiftSingleWellGeneric::getRateWithGroupLimit_(Rate rate_type, const double new_rate, const double old_rate, const std::string& gr_name_dont_limit) const { const double delta_rate = new_rate - old_rate; if (delta_rate > 0) { - // It is required that the production rate for a given group is - // is less than or equal to its target rate, see assert() below. - // Then it only makes sense to check if the group target is exceeded - // if delta_rate > 0 - const auto &pairs = - this->group_info_.getWellGroups(this->well_name_); - double limited_rate = new_rate; - double gr_target, new_gr_rate, efficiency; - const std::string *group_name = nullptr; - for (const auto& [group_name_temp, efficiency_temp] : pairs) { - auto gr_target_opt = this->group_info_.getTarget(rate_type, group_name_temp); - if (gr_target_opt) { - double gr_target_temp = *gr_target_opt; - double gr_rate_temp = - this->group_info_.getRate(rate_type, group_name_temp); - if (gr_rate_temp > gr_target_temp) { - if (this->debug) { - debugInfoGroupRatesExceedTarget( - rate_type, group_name_temp, gr_rate_temp, gr_target_temp); - } - group_name = &group_name_temp; - efficiency = efficiency_temp; - limited_rate = old_rate; - gr_target = gr_target_temp; - new_gr_rate = gr_rate_temp; - break; + // It is required that the production rate for a given group is + // is less than or equal to its target rate. + // Then it only makes sense to check if the group target is exceeded + // if delta_rate > 0 + const auto& pairs = this->group_info_.getWellGroups(this->well_name_); + double limited_rate = new_rate; + double gr_target, new_gr_rate, efficiency; + const std::string* group_name = nullptr; + for (const auto& [group_name_temp, efficiency_temp] : pairs) { + // in stage 2 we don't want to limit the rate to the group + // target we are trying to redistribute the gaslift within + if (gr_name_dont_limit == group_name_temp) { + continue; } - double new_gr_rate_temp = gr_rate_temp + efficiency_temp * delta_rate; - if (new_gr_rate_temp > gr_target_temp) { - double limited_rate_temp = - old_rate + (gr_target_temp - gr_rate_temp) / efficiency_temp; - if (limited_rate_temp < limited_rate) { + + auto gr_target_opt = this->group_info_.getTarget(rate_type, group_name_temp); + if (gr_target_opt) { + double gr_target_temp = *gr_target_opt; + double gr_rate_temp = this->group_info_.getRate(rate_type, group_name_temp); + if (gr_rate_temp > gr_target_temp) { + if (this->debug) { + debugInfoGroupRatesExceedTarget(rate_type, group_name_temp, gr_rate_temp, gr_target_temp); + } group_name = &group_name_temp; efficiency = efficiency_temp; - limited_rate = limited_rate_temp; + limited_rate = old_rate; gr_target = gr_target_temp; - new_gr_rate = new_gr_rate_temp; + new_gr_rate = gr_rate_temp; + break; + } + double new_gr_rate_temp = gr_rate_temp + efficiency_temp * delta_rate; + if (new_gr_rate_temp > gr_target_temp) { + double limited_rate_temp = old_rate + (gr_target_temp - gr_rate_temp) / efficiency_temp; + if (limited_rate_temp < limited_rate) { + group_name = &group_name_temp; + efficiency = efficiency_temp; + limited_rate = limited_rate_temp; + gr_target = gr_target_temp; + new_gr_rate = new_gr_rate_temp; + } } } - } - } - if (group_name) { - if (this->debug) { - const std::string msg = fmt::format( - "limiting {} rate from {} to {} to meet group target {} " - "for group {}. Computed group rate was: {}", - GasLiftGroupInfo::rateToString(rate_type), - new_rate, limited_rate, gr_target, - *group_name, new_gr_rate); - displayDebugMessage_(msg); - } - return { limited_rate, group_name, efficiency }; - } + } + if (group_name) { + if (this->debug) { + const std::string msg = fmt::format("limiting {} rate from {} to {} to meet group target {} " + "for group {}. Computed group rate was: {}", + GasLiftGroupInfo::rateToString(rate_type), + new_rate, + limited_rate, + gr_target, + *group_name, + new_gr_rate); + displayDebugMessage_(msg); + } + return {limited_rate, group_name, efficiency}; + } } - return { new_rate, /*group_name =*/nullptr, /*efficiency dummy value*/0.0 }; + return {new_rate, /*group_name =*/nullptr, /*efficiency dummy value*/ 0.0}; } std::pair, double> -GasLiftSingleWellGeneric:: -getInitialRatesWithLimit_() const +GasLiftSingleWellGeneric::getInitialRatesWithLimit_() const { std::optional limited_rates; double initial_alq = this->orig_alq_; if (auto [rates, alq] = computeInitialWellRates_(); rates) { if (this->debug) { - displayDebugMessage_( - "Maybe limiting initial rates before optimize loop.."); + displayDebugMessage_("Maybe limiting initial rates before optimize loop.."); } auto temp_rates = getLimitedRatesFromRates_(*rates); BasicRates old_rates = getWellStateRates_(); @@ -842,52 +821,51 @@ getInitialRatesWithLimit_() const } GasLiftSingleWellGeneric::LimitedRates -GasLiftSingleWellGeneric:: -getLimitedRatesFromRates_(const BasicRates& rates) const +GasLiftSingleWellGeneric::getLimitedRatesFromRates_(const BasicRates& rates) const { auto [oil_rate, oil_limiting_target] = getOilRateWithLimit2_(rates); auto [gas_rate, gas_is_limited] = getGasRateWithLimit_(rates); auto [water_rate, water_limiting_target] = getWaterRateWithLimit2_(rates); bool oil_is_limited = oil_limiting_target.has_value(); bool water_is_limited = water_limiting_target.has_value(); - return LimitedRates{ - oil_rate, gas_rate, water_rate, - oil_is_limited, gas_is_limited, water_is_limited, rates.bhp_is_limited, - oil_limiting_target, water_limiting_target}; + return LimitedRates {oil_rate, + gas_rate, + water_rate, + oil_is_limited, + gas_is_limited, + water_is_limited, + rates.bhp_is_limited, + oil_limiting_target, + water_limiting_target}; } GasLiftSingleWellGeneric::BasicRates -GasLiftSingleWellGeneric:: -getWellStateRates_() const +GasLiftSingleWellGeneric::getWellStateRates_() const { const int well_index = this->well_state_.index(this->well_name_).value(); const auto& pu = this->phase_usage_; - const auto& ws= this->well_state_.well(well_index); + const auto& ws = this->well_state_.well(well_index); const auto& wrate = ws.well_potentials; - const auto oil_rate = pu.phase_used[Oil] - ? wrate[pu.phase_pos[Oil]] - : 0.0; + const auto oil_rate = pu.phase_used[Oil] ? wrate[pu.phase_pos[Oil]] : 0.0; - const auto gas_rate = pu.phase_used[Gas] - ? wrate[pu.phase_pos[Gas]] - : 0.0; + const auto gas_rate = pu.phase_used[Gas] ? wrate[pu.phase_pos[Gas]] : 0.0; - const auto water_rate = pu.phase_used[Water] - ? wrate[pu.phase_pos[Water]] - : 0.0; + const auto water_rate = pu.phase_used[Water] ? wrate[pu.phase_pos[Water]] : 0.0; if (this->debug) { const std::string msg = fmt::format("Initial surface rates: oil : {}, " - "gas : {}, water : {}", oil_rate, gas_rate, water_rate); + "gas : {}, water : {}", + oil_rate, + gas_rate, + water_rate); displayDebugMessage_(msg); } - return BasicRates{oil_rate, water_rate, gas_rate, /*bhp_is_limited=*/false}; + return BasicRates {oil_rate, water_rate, gas_rate, /*bhp_is_limited=*/false}; } bool -GasLiftSingleWellGeneric:: -hasProductionControl_(Rate rate) const +GasLiftSingleWellGeneric::hasProductionControl_(Rate rate) const { switch (rate) { case Rate::oil: @@ -906,29 +884,30 @@ hasProductionControl_(Rate rate) const std::pair -GasLiftSingleWellGeneric:: -increaseALQtoPositiveOilRate_(double alq, const LimitedRates& orig_rates) const +GasLiftSingleWellGeneric::increaseALQtoPositiveOilRate_(double alq, const LimitedRates& orig_rates) const { bool stop_iteration = false; double temp_alq = alq; // use the copy constructor to only copy the rates BasicRates rates = orig_rates; - while(!stop_iteration) { + while (!stop_iteration) { temp_alq += this->increment_; - if (temp_alq > this->max_alq_) break; + if (temp_alq > this->max_alq_) + break; auto temp_rates = computeWellRatesWithALQ_(temp_alq); - if (!temp_rates) break; + if (!temp_rates) + break; alq = temp_alq; rates = *temp_rates; - if (rates.oil > 0) break; + if (rates.oil > 0) + break; } // TODO: what about group limits? return {getLimitedRatesFromRates_(rates), alq}; } std::pair -GasLiftSingleWellGeneric:: -increaseALQtoMinALQ_(const double orig_alq, const LimitedRates& orig_rates) const +GasLiftSingleWellGeneric::increaseALQtoMinALQ_(const double orig_alq, const LimitedRates& orig_rates) const { auto min_alq = this->min_alq_; assert(min_alq >= 0); @@ -937,35 +916,37 @@ increaseALQtoMinALQ_(const double orig_alq, const LimitedRates& orig_rates) cons bool stop_iteration = false; double alq = orig_alq; LimitedRates rates = orig_rates; - while(!stop_iteration) { + while (!stop_iteration) { double temp_alq = alq + this->increment_; - if (temp_alq >= min_alq) break; + if (temp_alq >= min_alq) + break; auto temp_rates = computeLimitedWellRatesWithALQ_(temp_alq); - if (!temp_rates) break; + if (!temp_rates) + break; alq = temp_alq; rates = *temp_rates; - if (rates.limited()) break; + if (rates.limited()) + break; } return std::make_pair(rates, alq); } void -GasLiftSingleWellGeneric:: -logSuccess_(double alq, const int iteration_idx) +GasLiftSingleWellGeneric::logSuccess_(double alq, const int iteration_idx) { - const std::string message = fmt::format( - "GLIFT, IT={}, WELL {} : {} ALQ from {} to {}", - iteration_idx, - this->well_name_, - ((alq > this->orig_alq_) ? "increased" : "decreased"), - this->orig_alq_, alq); + const std::string message = fmt::format("GLIFT, IT={}, WELL {} : {} ALQ from {} to {}", + iteration_idx, + this->well_name_, + ((alq > this->orig_alq_) ? "increased" : "decreased"), + this->orig_alq_, + alq); this->deferred_logger_.info(message); } std::pair -GasLiftSingleWellGeneric:: -maybeAdjustALQbeforeOptimizeLoop_( - const LimitedRates& orig_rates, const double orig_alq, const bool increase) const +GasLiftSingleWellGeneric::maybeAdjustALQbeforeOptimizeLoop_(const LimitedRates& orig_rates, + const double orig_alq, + const bool increase) const { double alq = orig_alq; LimitedRates rates = orig_rates; @@ -978,7 +959,7 @@ maybeAdjustALQbeforeOptimizeLoop_( // NOTE: Try to decrease ALQ down to a value where the groups // maximum alq target and the total gas + alq target is not violated std::tie(rates, alq) = reduceALQtoGroupAlqLimits_(alq, orig_rates); - if(orig_rates.limited()) { + if (orig_rates.limited()) { // NOTE: Try to decrease ALQ down to a value where the well target is // not exceeded. // NOTE: This may reduce ALQ below the minimum value set in WLIFTOPT @@ -989,8 +970,7 @@ maybeAdjustALQbeforeOptimizeLoop_( if (alq1 < alq2) { alq = alq1; rates = rates1; - } - else { + } else { alq = alq2; rates = rates2; } @@ -1000,7 +980,7 @@ maybeAdjustALQbeforeOptimizeLoop_( // Try to increase ALQ up to a value where oil_rate is positive std::tie(rates, alq) = increaseALQtoPositiveOilRate_(alq, rates); } - if ((this->min_alq_> 0) && (alq < this->min_alq_)) { + if ((this->min_alq_ > 0) && (alq < this->min_alq_)) { // Try to increase ALQ up to the minimum limit without checking // the economic gradient.. std::tie(rates, alq) = increaseALQtoMinALQ_(alq, rates); @@ -1017,7 +997,9 @@ maybeAdjustALQbeforeOptimizeLoop_( return {rates, alq}; } -bool has_control(int controls, Group::InjectionCMode cmode) { +bool +has_control(int controls, Group::InjectionCMode cmode) +{ return ((controls & static_cast(cmode)) != 0); } @@ -1025,19 +1007,21 @@ bool has_control(int controls, Group::InjectionCMode cmode) { // least one rate limited w.r.t. group targets, or reduce ALQ to zero if // such positive ALQ value cannot be found. std::pair -GasLiftSingleWellGeneric:: -reduceALQtoGroupAlqLimits_(const double orig_alq, const LimitedRates& orig_rates) const +GasLiftSingleWellGeneric::reduceALQtoGroupAlqLimits_(const double orig_alq, const LimitedRates& orig_rates) const { bool stop_this_iteration = false; double alq = orig_alq; - BasicRates rates{ orig_rates }; + BasicRates rates {orig_rates}; double temp_alq = orig_alq; - while(!stop_this_iteration) { - if (temp_alq == 0) break; + while (!stop_this_iteration) { + if (temp_alq == 0) + break; temp_alq -= this->increment_; - if (temp_alq < 0) temp_alq = 0; + if (temp_alq < 0) + temp_alq = 0; auto new_rates = computeWellRatesWithALQ_(temp_alq); - if (!new_rates) break; + if (!new_rates) + break; auto delta_alq = temp_alq - orig_alq; auto delta_gas_rate = new_rates->gas - orig_rates.gas; if (!checkGroupTotalRateExceeded(delta_alq, delta_gas_rate)) { @@ -1048,8 +1032,7 @@ reduceALQtoGroupAlqLimits_(const double orig_alq, const LimitedRates& orig_rates } if (alq == orig_alq) { return {orig_rates, orig_alq}; - } - else { + } else { LimitedRates limited_rates = getLimitedRatesFromRates_(rates); return {limited_rates, alq}; } @@ -1058,32 +1041,32 @@ reduceALQtoGroupAlqLimits_(const double orig_alq, const LimitedRates& orig_rates // least one rate limited w.r.t. group targets, or reduce ALQ to zero if // such positive ALQ value cannot be found. std::pair -GasLiftSingleWellGeneric:: -reduceALQtoGroupTarget(const double orig_alq, const LimitedRates& orig_rates) const +GasLiftSingleWellGeneric::reduceALQtoGroupTarget(const double orig_alq, const LimitedRates& orig_rates) const { bool stop_this_iteration = true; - const std::vector>& pairs = - this->group_info_.getWellGroups(this->well_name_); - for (const auto &pair /**/ : pairs) { + const std::vector>& pairs = this->group_info_.getWellGroups(this->well_name_); + for (const auto& pair /**/ : pairs) { const auto& group_name = pair.first; if (!this->group_state_.has_production_control(group_name)) continue; if (this->group_info_.hasAnyTarget(group_name)) { stop_this_iteration = false; - displayDebugMessage_( - "Reducing ALQ to meet group target(s) before iteration starts."); + displayDebugMessage_("Reducing ALQ to meet group target(s) before iteration starts."); break; } } double alq = orig_alq; - BasicRates rates{ orig_rates }; + BasicRates rates {orig_rates}; double temp_alq = orig_alq; - while(!stop_this_iteration) { - if (temp_alq == 0) break; + while (!stop_this_iteration) { + if (temp_alq == 0) + break; temp_alq -= this->increment_; - if (temp_alq < 0) temp_alq = 0; + if (temp_alq < 0) + temp_alq = 0; auto new_rates = computeWellRatesWithALQ_(temp_alq); - if (!new_rates) break; + if (!new_rates) + break; if (!checkGroupTargetsViolated(rates, *new_rates)) { break; } @@ -1092,8 +1075,7 @@ reduceALQtoGroupTarget(const double orig_alq, const LimitedRates& orig_rates) co } if (alq == orig_alq) { return {orig_rates, orig_alq}; - } - else { + } else { LimitedRates limited_rates = getLimitedRatesFromRates_(rates); return {limited_rates, alq}; } @@ -1103,55 +1085,57 @@ reduceALQtoGroupTarget(const double orig_alq, const LimitedRates& orig_rates) co // least one rate limited w.r.t. well targets, or reduce ALQ to zero if // such positive ALQ value cannot be found. std::pair -GasLiftSingleWellGeneric:: -reduceALQtoWellTarget_(const double orig_alq, const LimitedRates& rates) const +GasLiftSingleWellGeneric::reduceALQtoWellTarget_(const double orig_alq, const LimitedRates& rates) const { // this method should only be called if "rates" is limited assert(rates.limited()); if (this->debug) { - displayDebugMessage_( - "Reducing ALQ to meet well targets before iteration starts.."); + displayDebugMessage_("Reducing ALQ to meet well targets before iteration starts.."); debugShowLimitingTargets_(rates); } double alq = orig_alq; double temp_alq = alq; std::optional new_rates; bool stop_iteration = false; - while(!stop_iteration) { - if (temp_alq == 0) break; + while (!stop_iteration) { + if (temp_alq == 0) + break; temp_alq -= this->increment_; - if (temp_alq < 0) temp_alq = 0; + if (temp_alq < 0) + temp_alq = 0; auto temp_rates = computeLimitedWellRatesWithALQ_(temp_alq); - if (!temp_rates) break; // failed to compute BHP given THP limit and ALQ + if (!temp_rates) + break; // failed to compute BHP given THP limit and ALQ // keep iterating until no rate is limited - if (!temp_rates->limited()) break; + if (!temp_rates->limited()) + break; alq = temp_alq; new_rates = temp_rates; } - assert( alq <= orig_alq ); + assert(alq <= orig_alq); if (this->debug) { if (alq < orig_alq) { // NOTE: ALQ may drop below zero before we are able to meet the target - const std::string msg = fmt::format( - "Reduced ALQ from {} to {} to meet rate targets. Rates (new, old) : " - "oil(({}, {}), gas({}, {}), water({}, {})", - orig_alq, alq, - new_rates->oil, rates.oil, - new_rates->gas, rates.gas, - new_rates->water, rates.water); + const std::string msg = fmt::format("Reduced ALQ from {} to {} to meet rate targets. Rates (new, old) : " + "oil(({}, {}), gas({}, {}), water({}, {})", + orig_alq, + alq, + new_rates->oil, + rates.oil, + new_rates->gas, + rates.gas, + new_rates->water, + rates.water); displayDebugMessage_(msg); - } - else if (alq == orig_alq) { + } else if (alq == orig_alq) { // We might not be able to reduce ALQ, for example if ALQ starts out at zero. - const std::string msg = fmt::format( - "Not able to reduce ALQ {} further. ", orig_alq); + const std::string msg = fmt::format("Not able to reduce ALQ {} further. ", orig_alq); displayDebugMessage_(msg); } } if (new_rates) { return {*new_rates, alq}; - } - else { + } else { return {rates, orig_alq}; } } @@ -1166,21 +1150,23 @@ reduceALQtoWellTarget_(const double orig_alq, const LimitedRates& rates) const // - return value: a new GasLiftWellState or nullptr // std::unique_ptr -GasLiftSingleWellGeneric:: -runOptimizeLoop_(bool increase) +GasLiftSingleWellGeneric::runOptimizeLoop_(bool increase) { - if (this->debug) debugShowProducerControlMode(); + if (this->debug) + debugShowProducerControlMode(); std::unique_ptr ret_value; // nullptr initially auto [rates, cur_alq] = getInitialRatesWithLimit_(); - if (!rates) return ret_value; + if (!rates) + return ret_value; // if (this->debug) debugShowBhpAlqTable_(); - if (this->debug) debugShowAlqIncreaseDecreaseCounts_(); - if (this->debug) debugShowTargets_(); - bool success = false; // did we succeed to increase alq? + if (this->debug) + debugShowAlqIncreaseDecreaseCounts_(); + if (this->debug) + debugShowTargets_(); + bool success = false; // did we succeed to increase alq? bool alq_is_limited = false; LimitedRates new_rates = *rates; - auto [temp_rates2, new_alq] = maybeAdjustALQbeforeOptimizeLoop_( - *rates, cur_alq, increase); + auto [temp_rates2, new_alq] = maybeAdjustALQbeforeOptimizeLoop_(*rates, cur_alq, increase); if (checkInitialALQmodified_(new_alq, this->orig_alq_)) { auto delta_alq = new_alq - cur_alq; new_rates = temp_rates2; @@ -1192,9 +1178,9 @@ runOptimizeLoop_(bool increase) OptimizeState state {*this, increase}; auto temp_alq = cur_alq; if (checkThpControl_()) { - if (this->debug) debugShowStartIteration_(temp_alq, increase, new_rates.oil); - } - else { + if (this->debug) + debugShowStartIteration_(temp_alq, increase, new_rates.oil); + } else { // If the well is not under THP control, we can still use the previous // initial adjustment of ALQ by using the well's THP limit to calculate // BHP and then well rates from that. @@ -1204,42 +1190,48 @@ runOptimizeLoop_(bool increase) state.stop_iteration = true; } while (!state.stop_iteration && (++state.it <= this->max_iterations_)) { - if (state.checkRatesViolated(new_rates)) break; - if (state.checkAlqOutsideLimits(temp_alq, new_rates.oil)) break; + if (state.checkRatesViolated(new_rates)) + break; + if (state.checkAlqOutsideLimits(temp_alq, new_rates.oil)) + break; std::optional alq_opt; std::tie(alq_opt, alq_is_limited) = state.addOrSubtractAlqIncrement(temp_alq); - if (!alq_opt) break; + if (!alq_opt) + break; auto delta_alq = *alq_opt - temp_alq; - if (checkGroupALQrateExceeded(delta_alq)) break; + if (checkGroupALQrateExceeded(delta_alq)) + break; temp_alq = *alq_opt; - if (this->debug) state.debugShowIterationInfo(temp_alq); + if (this->debug) + state.debugShowIterationInfo(temp_alq); rates = new_rates; auto temp_rates = computeLimitedWellRatesWithALQ_(temp_alq); - if (!temp_rates) break; + if (!temp_rates) + break; if (temp_rates->bhp_is_limited) state.stop_iteration = true; temp_rates = updateRatesToGroupLimits_(*rates, *temp_rates); auto delta_gas_rate = temp_rates->gas - rates->gas; - if (checkGroupTotalRateExceeded(delta_alq, delta_gas_rate)) break; + if (checkGroupTotalRateExceeded(delta_alq, delta_gas_rate)) + break; -/* if (this->debug_abort_if_increase_and_gas_is_limited_) { - if (gas_is_limited && increase) { - // if gas is limited we do not want to increase - displayDebugMessage_( - "increasing ALQ and gas is limited -> aborting iteration"); - break; - } - } -*/ - auto gradient = state.calcEcoGradient( - rates->oil, temp_rates->oil, rates->gas, temp_rates->gas); + /* if (this->debug_abort_if_increase_and_gas_is_limited_) { + if (gas_is_limited && increase) { + // if gas is limited we do not want to increase + displayDebugMessage_( + "increasing ALQ and gas is limited -> aborting iteration"); + break; + } + } + */ + auto gradient = state.calcEcoGradient(rates->oil, temp_rates->oil, rates->gas, temp_rates->gas); if (this->debug) debugCheckNegativeGradient_( - gradient, cur_alq, temp_alq, rates->oil, temp_rates->oil, - rates->gas, temp_rates->gas, increase); - if (state.checkEcoGradient(gradient)) break; + gradient, cur_alq, temp_alq, rates->oil, temp_rates->oil, rates->gas, temp_rates->gas, increase); + if (state.checkEcoGradient(gradient)) + break; cur_alq = temp_alq; success = true; new_rates = *temp_rates; @@ -1252,20 +1244,23 @@ runOptimizeLoop_(bool increase) if (success) { this->well_state_.gliftUpdateAlqIncreaseCount(this->well_name_, increase); increase_opt = increase; - } - else { + } else { increase_opt = std::nullopt; } - ret_value = std::make_unique( - new_rates.oil, new_rates.oil_is_limited, - new_rates.gas, new_rates.gas_is_limited, - cur_alq, alq_is_limited, new_rates.water, increase_opt); + ret_value = std::make_unique(new_rates.oil, + new_rates.oil_is_limited, + new_rates.gas, + new_rates.gas_is_limited, + cur_alq, + alq_is_limited, + new_rates.water, + new_rates.water_is_limited, + increase_opt); return ret_value; } std::unique_ptr -GasLiftSingleWellGeneric:: -runOptimize1_() +GasLiftSingleWellGeneric::runOptimize1_() { std::unique_ptr state; int inc_count = this->well_state_.gliftGetAlqIncreaseCount(this->well_name_); @@ -1275,12 +1270,10 @@ runOptimize1_() if (!state || !(state->alqChanged())) { state = tryDecreaseLiftGas_(); } - } - else if (dec_count == 0) { + } else if (dec_count == 0) { assert(inc_count > 0); state = tryIncreaseLiftGas_(); - } - else if (inc_count == 0) { + } else if (inc_count == 0) { assert(dec_count > 0); state = tryDecreaseLiftGas_(); } @@ -1288,8 +1281,7 @@ runOptimize1_() } std::unique_ptr -GasLiftSingleWellGeneric:: -runOptimize2_() +GasLiftSingleWellGeneric::runOptimize2_() { std::unique_ptr state; state = tryIncreaseLiftGas_(); @@ -1300,22 +1292,19 @@ runOptimize2_() } std::unique_ptr -GasLiftSingleWellGeneric:: -tryDecreaseLiftGas_() +GasLiftSingleWellGeneric::tryDecreaseLiftGas_() { - return runOptimizeLoop_(/*increase=*/ false); + return runOptimizeLoop_(/*increase=*/false); } std::unique_ptr -GasLiftSingleWellGeneric:: -tryIncreaseLiftGas_() +GasLiftSingleWellGeneric::tryIncreaseLiftGas_() { - return runOptimizeLoop_(/*increase=*/ true); + return runOptimizeLoop_(/*increase=*/true); } void -GasLiftSingleWellGeneric:: -setAlqMinRate_(const GasLiftOpt::Well& well) +GasLiftSingleWellGeneric::setAlqMinRate_(const GasLiftOpt::Well& well) { // NOTE: According to WLIFTOPT item 5 : // if min_rate() is negative, it means: allocate at least enough lift gas @@ -1342,56 +1331,49 @@ setAlqMinRate_(const GasLiftOpt::Well& well) // TODO: Consider other options for resetting the value.. this->min_alq_ = -1; displayWarning_("Minimum ALQ value is larger than maximum ALQ value!" - " Resetting value."); + " Resetting value."); } } } void -GasLiftSingleWellGeneric:: -updateGroupRates_( - const LimitedRates& rates, const LimitedRates& new_rates, double delta_alq) const +GasLiftSingleWellGeneric::updateGroupRates_(const LimitedRates& rates, + const LimitedRates& new_rates, + double delta_alq) const { double delta_oil = new_rates.oil - rates.oil; double delta_gas = new_rates.gas - rates.gas; double delta_water = new_rates.water - rates.water; - const auto &pairs = - this->group_info_.getWellGroups(this->well_name_); - for (const auto &[group_name, efficiency] : pairs) { + const auto& pairs = this->group_info_.getWellGroups(this->well_name_); + for (const auto& [group_name, efficiency] : pairs) { int idx = this->group_info_.getGroupIdx(group_name); // This will notify the optimize loop in BlackoilWellModel, see // gasLiftOptimizationStage1() in BlackoilWellModel_impl.hpp // that this group_info needs to be synchronized to the other MPI ranks this->sync_groups_.insert(idx); this->group_info_.update(group_name, - efficiency * delta_oil, - efficiency * delta_gas, - efficiency * delta_water, - efficiency * delta_alq); + efficiency * delta_oil, + efficiency * delta_gas, + efficiency * delta_water, + efficiency * delta_alq); } } GasLiftSingleWellGeneric::LimitedRates -GasLiftSingleWellGeneric:: -updateRatesToGroupLimits_( - const BasicRates& old_rates, const LimitedRates& rates) const +GasLiftSingleWellGeneric::updateRatesToGroupLimits_(const BasicRates& old_rates, const LimitedRates& rates, const std::string& gr_name) const { LimitedRates new_rates = rates; - auto [new_oil_rate, oil_is_limited] = getOilRateWithGroupLimit_( - new_rates.oil, old_rates.oil); + auto [new_oil_rate, oil_is_limited] = getOilRateWithGroupLimit_(new_rates.oil, old_rates.oil, gr_name); if (oil_is_limited) { new_rates.oil_limiting_target = Rate::oil; } - auto [new_gas_rate, gas_is_limited] = getGasRateWithGroupLimit_( - new_rates.gas, old_rates.gas); - auto [new_water_rate, water_is_limited] = getWaterRateWithGroupLimit_( - new_rates.water, old_rates.water); + auto [new_gas_rate, gas_is_limited] = getGasRateWithGroupLimit_(new_rates.gas, old_rates.gas, gr_name); + auto [new_water_rate, water_is_limited] = getWaterRateWithGroupLimit_(new_rates.water, old_rates.water, gr_name); if (water_is_limited) { new_rates.water_limiting_target = Rate::water; } auto [new_oil_rate2, new_water_rate2, oil_is_limited2, water_is_limited2] - = getLiquidRateWithGroupLimit_( - new_oil_rate, old_rates.oil, new_water_rate, old_rates.water); + = getLiquidRateWithGroupLimit_(new_oil_rate, old_rates.oil, new_water_rate, old_rates.water, gr_name); if (oil_is_limited2) { new_rates.oil_limiting_target = Rate::liquid; } @@ -1403,10 +1385,8 @@ updateRatesToGroupLimits_( new_rates.water = new_water_rate2; new_rates.oil_is_limited = rates.oil_is_limited || oil_is_limited || oil_is_limited2; new_rates.gas_is_limited = rates.gas_is_limited || gas_is_limited; - new_rates.water_is_limited = - rates.water_is_limited || water_is_limited || water_is_limited2; - if (oil_is_limited || oil_is_limited2 || gas_is_limited - || water_is_limited || water_is_limited2) { + new_rates.water_is_limited = rates.water_is_limited || water_is_limited || water_is_limited2; + if (oil_is_limited || oil_is_limited2 || gas_is_limited || water_is_limited || water_is_limited2) { new_rates.limit_type = LimitedRates::LimitType::group; } return new_rates; @@ -1414,8 +1394,7 @@ updateRatesToGroupLimits_( // Called when we should use a fixed ALQ value void -GasLiftSingleWellGeneric:: -updateWellStateAlqFixedValue_(const GasLiftOpt::Well& well) +GasLiftSingleWellGeneric::updateWellStateAlqFixedValue_(const GasLiftOpt::Well& well) { auto& max_alq_optional = well.max_rate(); if (max_alq_optional) { @@ -1429,7 +1408,6 @@ updateWellStateAlqFixedValue_(const GasLiftOpt::Well& well) // // If item 3 is defaulted, the lift gas rate remains // // unchanged at its current value. //} - } // Determine if we should use a fixed ALQ value. @@ -1443,47 +1421,46 @@ updateWellStateAlqFixedValue_(const GasLiftOpt::Well& well) // value that can be set either in Item 3 of this keyword, or in // Item 12 of keyword WCONPROD, or with keyword WELTARG. bool -GasLiftSingleWellGeneric:: -useFixedAlq_(const GasLiftOpt::Well& well) +GasLiftSingleWellGeneric::useFixedAlq_(const GasLiftOpt::Well& well) { auto wliftopt_item2 = well.use_glo(); if (wliftopt_item2) { return false; - } - else { + } else { displayDebugMessage_("WLIFTOPT item2 = NO. Skipping optimization."); // auto& max_alq_optional = well.max_rate(); // if (max_alq_optional) { - // According to WLIFTOPT, item 3: - // If item 2 is NO, then item 3 is regarded as the fixed - // lift gas injection rate for the well. + // According to WLIFTOPT, item 3: + // If item 2 is NO, then item 3 is regarded as the fixed + // lift gas injection rate for the well. // } // else { - // If item 3 is defaulted, the lift gas rate remains - // unchanged at its current value. + // If item 3 is defaulted, the lift gas rate remains + // unchanged at its current value. // } return true; } } void -GasLiftSingleWellGeneric:: -debugInfoGroupRatesExceedTarget( - Rate rate_type, const std::string& gr_name, double rate, double target) const +GasLiftSingleWellGeneric::debugInfoGroupRatesExceedTarget(Rate rate_type, + const std::string& gr_name, + double rate, + double target) const { const std::string msg = fmt::format("{} rate for group {} exceeds target: " - "rate = {}, target = {}, the old rate is kept.", - GasLiftGroupInfo::rateToString(rate_type), - gr_name, rate, target); + "rate = {}, target = {}, the old rate is kept.", + GasLiftGroupInfo::rateToString(rate_type), + gr_name, + rate, + target); displayDebugMessage_(msg); } void -GasLiftSingleWellGeneric:: -warnMaxIterationsExceeded_() +GasLiftSingleWellGeneric::warnMaxIterationsExceeded_() { - const std::string msg = fmt::format( - "Max iterations ({}) exceeded", this->max_iterations_); + const std::string msg = fmt::format("Max iterations ({}) exceeded", this->max_iterations_); displayWarning_(msg); } @@ -1492,26 +1469,25 @@ warnMaxIterationsExceeded_() ****************************************/ std::pair, bool> -GasLiftSingleWellGeneric::OptimizeState:: -addOrSubtractAlqIncrement(double alq) +GasLiftSingleWellGeneric::OptimizeState::addOrSubtractAlqIncrement(double alq) { - auto [alq_opt, limited] - = this->parent.addOrSubtractAlqIncrement_(alq, this->increase); + auto [alq_opt, limited] = this->parent.addOrSubtractAlqIncrement_(alq, this->increase); if (!alq_opt) { - const std::string msg = fmt::format( - "iteration {}, alq = {} : not able to {} ALQ increment", - this->it, alq, (this->increase ? "add" : "subtract")); + const std::string msg = fmt::format("iteration {}, alq = {} : not able to {} ALQ increment", + this->it, + alq, + (this->increase ? "add" : "subtract")); } return {alq_opt, limited}; } double -GasLiftSingleWellGeneric::OptimizeState:: -calcEcoGradient(double oil_rate, double new_oil_rate, - double gas_rate, double new_gas_rate) +GasLiftSingleWellGeneric::OptimizeState::calcEcoGradient(double oil_rate, + double new_oil_rate, + double gas_rate, + double new_gas_rate) { - return this->parent.calcEcoGradient_(oil_rate, new_oil_rate, - gas_rate, new_gas_rate, this->increase); + return this->parent.calcEcoGradient_(oil_rate, new_oil_rate, gas_rate, new_gas_rate, this->increase); } // NOTE: According to WLIFTOPT item 5 : @@ -1521,8 +1497,7 @@ calcEcoGradient(double oil_rate, double new_oil_rate, // in this file): Allocate at least the amount of lift gas needed to // get a positive oil production rate. bool -GasLiftSingleWellGeneric::OptimizeState:: -checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) +GasLiftSingleWellGeneric::OptimizeState::checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) { std::ostringstream ss; bool result = false; @@ -1532,8 +1507,7 @@ checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) ss << "ALQ >= " << this->parent.max_alq_ << " (max limit), " << "stopping iteration"; result = true; - } - else { // checking the minimum limit... + } else { // checking the minimum limit... // NOTE: A negative min_alq_ means: allocate at least enough lift gas // to enable the well to flow, see WLIFTOPT item 5. if (this->parent.min_alq_ < 0) { @@ -1543,23 +1517,20 @@ checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) // - else if oil rate is already positive, there is no minimum // limit for ALQ in this case result = false; - } - else { + } else { // NOTE: checking for a lower limit is not necessary // when increasing alq. If ALQ was smaller than the minimum when // we entered the runOptimizeLoop_() method, // increaseALQtoMinALQ_() will ensure that ALQ >= min_alq - assert(alq >= this->parent.min_alq_ ); + assert(alq >= this->parent.min_alq_); result = false; } } - } - else { // we are decreasing lift gas - if ( alq == 0 ) { + } else { // we are decreasing lift gas + if (alq == 0) { ss << "ALQ is zero, cannot decrease further. Stopping iteration."; result = true; - } - else if ( alq < 0 ) { + } else if (alq < 0) { ss << "Negative ALQ: " << alq << ". Stopping iteration."; result = true; } @@ -1570,9 +1541,8 @@ checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) // already checked in runOptimizeLoop_() by calling checkNegativeOilRate() assert(oil_rate >= 0); result = false; - } - else { - if (alq <= this->parent.min_alq_ ) { + } else { + if (alq <= this->parent.min_alq_) { // According to WLIFTOPT item 5: // "If a positive value is specified, the well is // allocated at least that amount of lift gas, @@ -1586,24 +1556,21 @@ checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) // checkRatesViolated(). // - We also know that the rate limit was not exceeded since that was // checked by checkRatesViolated() - assert( oil_rate >= 0); + assert(oil_rate >= 0); ss << "ALQ <= " << this->parent.min_alq_ << " (min limit), " - << "stopping iteration"; + << "stopping iteration"; result = true; - } - else { + } else { // NOTE: checking for an upper limit should not be necessary // when decreasing alq.. so this is just to catch an // illegal state at an early point. if (this->parent.checkALQequal_(alq, this->parent.max_alq_)) { return false; - } - else if (alq > this->parent.max_alq_) { - warn_( "unexpected: alq above upper limit when trying to " - "decrease lift gas. aborting iteration."); + } else if (alq > this->parent.max_alq_) { + warn_("unexpected: alq above upper limit when trying to " + "decrease lift gas. aborting iteration."); result = true; - } - else { + } else { result = false; } } @@ -1618,21 +1585,21 @@ checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) } bool -GasLiftSingleWellGeneric:: -checkGroupALQrateExceeded(double delta_alq) const +GasLiftSingleWellGeneric::checkGroupALQrateExceeded(double delta_alq, const std::string& gr_name_dont_limit) const { - const auto &pairs = - group_info_.getWellGroups(well_name_); - for (const auto &[group_name, efficiency] : pairs) { + const auto& pairs = group_info_.getWellGroups(well_name_); + for (const auto& [group_name, efficiency] : pairs) { + // in stage 2 we don't want to limit the rate to the group + // target we are trying to redistribute the gaslift within + if (gr_name_dont_limit == group_name) + continue; auto max_alq_opt = group_info_.maxAlq(group_name); if (max_alq_opt) { - double alq = - group_info_.alqRate(group_name) + efficiency * delta_alq; + double alq = group_info_.alqRate(group_name) + efficiency * delta_alq; if (alq > *max_alq_opt) { if (debug) { const std::string msg = fmt::format( - "Group {} : alq {} exceeds max_alq {}. Stopping iteration", - group_name, alq, *max_alq_opt); + "Group {} : alq {} exceeds max_alq {}. Stopping iteration", group_name, alq, *max_alq_opt); displayDebugMessage_(msg); } return true; @@ -1643,24 +1610,22 @@ checkGroupALQrateExceeded(double delta_alq) const } bool -GasLiftSingleWellGeneric:: -checkGroupTotalRateExceeded(double delta_alq, double delta_gas_rate) const +GasLiftSingleWellGeneric::checkGroupTotalRateExceeded(double delta_alq, double delta_gas_rate) const { - const auto &pairs = - group_info_.getWellGroups(well_name_); - for (const auto &[group_name, efficiency] : pairs) { + const auto& pairs = group_info_.getWellGroups(well_name_); + for (const auto& [group_name, efficiency] : pairs) { auto max_total_rate_opt = group_info_.maxTotalGasRate(group_name); if (max_total_rate_opt) { - double alq = - group_info_.alqRate(group_name) + efficiency * delta_alq; - double gas_rate = - group_info_.gasRate(group_name) + efficiency * delta_gas_rate; + double alq = group_info_.alqRate(group_name) + efficiency * delta_alq; + double gas_rate = group_info_.gasRate(group_name) + efficiency * delta_gas_rate; - if ( (alq + gas_rate) > *max_total_rate_opt) { + if ((alq + gas_rate) > *max_total_rate_opt) { if (debug) { - const std::string msg = fmt::format( - "Group {} : total gas rate {} exceeds max_total_gas_rate {}. Stopping iteration", - group_name, alq + gas_rate, *max_total_rate_opt); + const std::string msg + = fmt::format("Group {} : total gas rate {} exceeds max_total_gas_rate {}. Stopping iteration", + group_name, + alq + gas_rate, + *max_total_rate_opt); displayDebugMessage_(msg); } return true; @@ -1683,8 +1648,7 @@ checkGroupTotalRateExceeded(double delta_alq, double delta_gas_rate) const // lift gas until the gradient increases and reaches the economic gradient..) // bool -GasLiftSingleWellGeneric::OptimizeState:: -checkEcoGradient(double gradient) +GasLiftSingleWellGeneric::OptimizeState::checkEcoGradient(double gradient) { std::ostringstream ss; bool result = false; @@ -1693,68 +1657,67 @@ checkEcoGradient(double gradient) ss << "checking gradient: " << gradient; } if (this->increase) { - if (this->parent.debug) ss << " <= " << this->parent.eco_grad_ << " --> "; + if (this->parent.debug) + ss << " <= " << this->parent.eco_grad_ << " --> "; if (gradient <= this->parent.eco_grad_) { - if (this->parent.debug) ss << "yes, stopping"; + if (this->parent.debug) + ss << "yes, stopping"; result = true; + } else { + if (this->parent.debug) + ss << "no, continue"; } - else { - if (this->parent.debug) ss << "no, continue"; - } - } - else { // decreasing lift gas - if (this->parent.debug) ss << " >= " << this->parent.eco_grad_ << " --> "; + } else { // decreasing lift gas + if (this->parent.debug) + ss << " >= " << this->parent.eco_grad_ << " --> "; if (gradient >= this->parent.eco_grad_) { - if (this->parent.debug) ss << "yes, stopping"; + if (this->parent.debug) + ss << "yes, stopping"; result = true; - } - else { - if (this->parent.debug) ss << "no, continue"; + } else { + if (this->parent.debug) + ss << "no, continue"; } } - if (this->parent.debug) this->parent.displayDebugMessage_(ss.str()); + if (this->parent.debug) + this->parent.displayDebugMessage_(ss.str()); return result; } bool -GasLiftSingleWellGeneric::OptimizeState:: -checkRatesViolated(const LimitedRates& rates) const +GasLiftSingleWellGeneric::OptimizeState::checkRatesViolated(const LimitedRates& rates) const { if (!this->increase) { if (rates.oil < 0) { // The well is not flowing, and it will(?) not help to reduce lift // gas further. Note that this assumes that the oil rates drops with // decreasing lift gas. - this->parent.displayDebugMessage_( - "Negative oil rate detected while descreasing " - "lift gas. Stopping iteration."); + this->parent.displayDebugMessage_("Negative oil rate detected while descreasing " + "lift gas. Stopping iteration."); return true; } } if (rates.limited()) { if (this->parent.debug) { - const std::string well_or_group - = rates.limit_type == LimitedRates::LimitType::well ? "well" : "group"; + const std::string well_or_group = rates.limit_type == LimitedRates::LimitType::well ? "well" : "group"; std::string target_type; std::string rate_type; if (rates.oil_is_limited) { - target_type = GasLiftGroupInfo::rateToString( - *(rates.oil_limiting_target)); + target_type = GasLiftGroupInfo::rateToString(*(rates.oil_limiting_target)); rate_type = "oil"; - } - else if (rates.gas_is_limited) { + } else if (rates.gas_is_limited) { target_type = "gas"; rate_type = "gas"; - } - else if (rates.water_is_limited) { - target_type = GasLiftGroupInfo::rateToString( - *(rates.water_limiting_target)); + } else if (rates.water_is_limited) { + target_type = GasLiftGroupInfo::rateToString(*(rates.water_limiting_target)); rate_type = "water"; } - const std::string msg = fmt::format( - "iteration {} : {} rate was limited due to {} {} target. " - "Stopping iteration", - this->it, rate_type, well_or_group, target_type); + const std::string msg = fmt::format("iteration {} : {} rate was limited due to {} {} target. " + "Stopping iteration", + this->it, + rate_type, + well_or_group, + target_type); this->parent.displayDebugMessage_(msg); } return true; @@ -1763,8 +1726,7 @@ checkRatesViolated(const LimitedRates& rates) const } void -GasLiftSingleWellGeneric::OptimizeState:: -debugShowIterationInfo(double alq) +GasLiftSingleWellGeneric::OptimizeState::debugShowIterationInfo(double alq) { const std::string msg = fmt::format("iteration {}, ALQ = {}", this->it, alq); this->parent.displayDebugMessage_(msg); @@ -1782,8 +1744,7 @@ debugShowIterationInfo(double alq) // BHP limit? // double -GasLiftSingleWellGeneric::OptimizeState:: -getBhpWithLimit() +GasLiftSingleWellGeneric::OptimizeState::getBhpWithLimit() { auto [new_bhp, limited] = this->parent.getBhpWithLimit_(this->bhp); if (limited) { @@ -1804,8 +1765,7 @@ getBhpWithLimit() * Methods declared in BasicRates ****************************************/ -GasLiftSingleWellGeneric::BasicRates:: -BasicRates(const LimitedRates& rates) +GasLiftSingleWellGeneric::BasicRates::BasicRates(const LimitedRates& rates) { oil = rates.oil; gas = rates.gas; diff --git a/opm/simulators/wells/GasLiftSingleWellGeneric.hpp b/opm/simulators/wells/GasLiftSingleWellGeneric.hpp index 82613fb0e..b958bda81 100644 --- a/opm/simulators/wells/GasLiftSingleWellGeneric.hpp +++ b/opm/simulators/wells/GasLiftSingleWellGeneric.hpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -93,7 +94,10 @@ public: const std::string& name() const { return well_name_; } std::optional calcIncOrDecGradient(double oil_rate, double gas_rate, - double alq, bool increase) const; + double water_rate, + double alq, + const std::string& gr_name_dont_limit, + bool increase) const; std::unique_ptr runOptimize(const int iteration_idx); @@ -237,7 +241,7 @@ protected: double getBhpWithLimit(); void warn_(std::string msg) {parent.displayWarning_(msg);} }; - bool checkGroupALQrateExceeded(double delta_alq) const; + bool checkGroupALQrateExceeded(double delta_alq, const std::string& gr_name_dont_limit = "") const; bool checkGroupTotalRateExceeded(double delta_alq, double delta_gas_rate) const; std::pair, bool> addOrSubtractAlqIncrement_( @@ -272,14 +276,14 @@ protected: std::pair getGasRateWithLimit_( const BasicRates& rates) const; std::pair getGasRateWithGroupLimit_( - double new_gas_rate, double gas_rate) const; + double new_gas_rate, double gas_rate, const std::string& gr_name_dont_limit) const; std::pair,double> getInitialRatesWithLimit_() const; LimitedRates getLimitedRatesFromRates_(const BasicRates& rates) const; std::tuple getLiquidRateWithGroupLimit_( const double new_oil_rate, const double oil_rate, - const double new_water_rate, const double water_rate) const; + const double new_water_rate, const double water_rate, const std::string& gr_name_dont_limit) const; std::pair getOilRateWithGroupLimit_( - double new_oil_rate, double oil_rate) const; + double new_oil_rate, double oil_rate, const std::string& gr_name_dont_limit) const; std::pair getOilRateWithLimit_(const BasicRates& rates) const; std::pair> getOilRateWithLimit2_( const BasicRates& rates) const; @@ -288,9 +292,9 @@ protected: std::pair> getRateWithLimit_( Rate rate_type, const BasicRates& rates) const; std::tuple getRateWithGroupLimit_( - Rate rate_type, const double new_rate, const double old_rate) const; + Rate rate_type, const double new_rate, const double old_rate, const std::string& gr_name_dont_limit) const; std::pair getWaterRateWithGroupLimit_( - double new_water_rate, double water_rate) const; + double new_water_rate, double water_rate, const std::string& gr_name_dont_limit) const; std::pair getWaterRateWithLimit_(const BasicRates& rates) const; std::pair> getWaterRateWithLimit2_( const BasicRates& rates) const; @@ -321,14 +325,13 @@ protected: const LimitedRates& new_rates, double delta_alq) const; LimitedRates updateRatesToGroupLimits_( - const BasicRates& rates, const LimitedRates& new_rates) const; + const BasicRates& rates, const LimitedRates& new_rates, const std::string& gr_name = "") const; void updateWellStateAlqFixedValue_(const GasLiftOpt::Well& well); bool useFixedAlq_(const GasLiftOpt::Well& well); void debugInfoGroupRatesExceedTarget( Rate rate_type, const std::string& gr_name, double rate, double target) const; void warnMaxIterationsExceeded_(); - const GroupState& group_state_; const Well& ecl_well_; const SummaryState& summary_state_; GasLiftGroupInfo& group_info_; diff --git a/opm/simulators/wells/GasLiftStage2.cpp b/opm/simulators/wells/GasLiftStage2.cpp index 422f7e134..d4f15f69f 100644 --- a/opm/simulators/wells/GasLiftStage2.cpp +++ b/opm/simulators/wells/GasLiftStage2.cpp @@ -28,7 +28,7 @@ #include #include #include - +#include #include #include #include @@ -44,14 +44,17 @@ GasLiftStage2::GasLiftStage2( const SummaryState& summary_state, DeferredLogger &deferred_logger, WellState &well_state, + const GroupState &group_state, GLiftProdWells &prod_wells, GLiftOptWells &glift_wells, + GasLiftGroupInfo& group_info, GLiftWellStateMap &state_map, bool glift_debug ) : - GasLiftCommon(well_state, deferred_logger, comm, glift_debug) + GasLiftCommon(well_state, group_state, deferred_logger, comm, glift_debug) , prod_wells_{prod_wells} , stage1_wells_{glift_wells} + , group_info_{group_info} , well_state_map_{state_map} , report_step_idx_{report_step_idx} , summary_state_{summary_state} @@ -114,24 +117,25 @@ addOrRemoveALQincrement_(GradMap &grad_map, const std::string& well_name, bool a } state.update(gi.new_oil_rate, gi.oil_is_limited, gi.new_gas_rate, gi.gas_is_limited, - gi.alq, gi.alq_is_limited, gi.new_water_rate, add); - this->well_state_.setALQ(well_name, gi.alq); - const auto& pu = this->well_state_.phaseUsage(); - std::vector well_pot(pu.num_phases, 0.0); - if(pu.phase_used[BlackoilPhases::PhaseIndex::Liquid]) - well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Liquid]] = gi.new_oil_rate; - if(pu.phase_used[BlackoilPhases::PhaseIndex::Aqua]) - well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Aqua]] = gi.new_water_rate; - if(pu.phase_used[BlackoilPhases::PhaseIndex::Vapour]) - well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Vapour]] = gi.new_gas_rate; + gi.alq, gi.alq_is_limited, gi.new_water_rate, gi.water_is_limited, add); - this->well_state_[well_name].well_potentials = well_pot; + this->well_state_.setALQ(well_name, gi.alq); + const auto& pu = this->well_state_.phaseUsage(); + std::vector well_pot(pu.num_phases, 0.0); + if(pu.phase_used[BlackoilPhases::PhaseIndex::Liquid]) + well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Liquid]] = gi.new_oil_rate; + if(pu.phase_used[BlackoilPhases::PhaseIndex::Aqua]) + well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Aqua]] = gi.new_water_rate; + if(pu.phase_used[BlackoilPhases::PhaseIndex::Vapour]) + well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Vapour]] = gi.new_gas_rate; + + this->well_state_[well_name].well_potentials = well_pot; } std::optional GasLiftStage2:: calcIncOrDecGrad_( - const std::string well_name, const GasLiftSingleWell &gs_well, bool increase) + const std::string well_name, const GasLiftSingleWell &gs_well, const std::string& gr_name_dont_limit, bool increase) { // only applies to wells in the well_state_map (i.e. wells on this rank) @@ -157,7 +161,7 @@ calcIncOrDecGrad_( else { auto [oil_rate, gas_rate] = state.getRates(); auto alq = state.alq(); - auto grad = gs_well.calcIncOrDecGradient(oil_rate, gas_rate, alq, increase); + auto grad = gs_well.calcIncOrDecGradient(oil_rate, gas_rate, state.waterRate(), alq, gr_name_dont_limit, increase); if (grad) { const std::string msg = fmt::format( "well {} : adding {} gradient = {}", @@ -191,7 +195,7 @@ checkRateAlreadyLimited_(GasLiftWellState &state, bool increase) if (increase) do_check = true; } if (do_check) { - if (state.gasIsLimited() || state.oilIsLimited() || state.alqIsLimited()) { + if (state.gasIsLimited() || state.oilIsLimited() || state.alqIsLimited() || state.waterIsLimited()) { const std::string msg = fmt::format( "{} gradient : skipping since {} was limited in previous step", (increase ? "incremental" : "decremental"), @@ -272,152 +276,34 @@ displayDebugMessage_(const std::string &msg, const std::string &group_name) } } -std::tuple +std::tuple GasLiftStage2:: getCurrentGroupRates_(const Group &group) { - auto rates = getCurrentGroupRatesRecursive_(group); - this->comm_.sum(rates.data(), rates.size()); - auto [oil_rate, gas_rate, alq] = rates; - if (this->debug) { - const std::string msg = fmt::format( - "Current group rates for {} : oil: {}, gas: {}, alq: {}", - group.name(), oil_rate, gas_rate, alq); - displayDebugMessageOnRank0_(msg); - } - - return {oil_rate, gas_rate, alq}; + return {this->group_info_.oilRate(group.name()), + this->group_info_.gasRate(group.name()), + this->group_info_.waterRate(group.name()), + this->group_info_.alqRate(group.name())}; } - -std::array -GasLiftStage2:: -getCurrentGroupRatesRecursive_(const Group &group) +std::optional +GasLiftStage2::getGroupMaxALQ_(const Group &group) { - double oil_rate = 0.0; - double gas_rate = 0.0; - double alq = 0.0; - // NOTE: A group can either contain wells or groups, but not both - if (group.wellgroup()) { - for (const std::string& well_name : group.wells()) { - auto [sw_oil_rate, sw_gas_rate, sw_alq] = - getCurrentWellRates_(well_name, group.name()); - oil_rate += sw_oil_rate; - gas_rate += sw_gas_rate; - alq += sw_alq; - } - + if (this->glo_.has_group(group.name())) { + const auto &gl_group = this->glo_.group(group.name()); + return gl_group.max_lift_gas(); } - else { - for (const std::string& group_name : group.groups()) { - if(this->schedule_.back().groups.has(group_name)) { - const Group& sub_group = - this->schedule_.getGroup(group_name, this->report_step_idx_); - // If groups have efficiency factors to model - // synchronized downtime of their subordinate wells - // (see keyword GEFAC), their lift gas injection rates - // are multiplied by their efficiency factors when - // they are added to the lift gas supply rate of the - // parent group. - const auto gefac = sub_group.getGroupEfficiencyFactor(); - auto rates = getCurrentGroupRatesRecursive_(sub_group); - auto [sg_oil_rate, sg_gas_rate, sg_alq] = rates; - oil_rate += (gefac * sg_oil_rate); - gas_rate += (gefac * sg_gas_rate); - alq += (gefac * sg_alq); - } - } - } - return {oil_rate, gas_rate, alq}; + return std::nullopt; // If GLIFTOPT is missing from schedule, assume unlimited alq } -std::tuple -GasLiftStage2:: -getCurrentWellRates_(const std::string &well_name, const std::string &group_name) +std::optional +GasLiftStage2::getGroupMaxTotalGas_(const Group &group) { - double oil_rate, gas_rate, alq; - bool success = false; - const WellInterfaceGeneric *well_ptr = nullptr; - std::string debug_info; - if (this->stage1_wells_.count(well_name) == 1) { - GasLiftSingleWell &gs_well = *(this->stage1_wells_.at(well_name).get()); - const WellInterfaceGeneric &well = gs_well.getWell(); - well_ptr = &well; - GasLiftWellState &state = *(this->well_state_map_.at(well_name).get()); - std::tie(oil_rate, gas_rate) = state.getRates(); - success = true; - if ( this->debug) debug_info = "(A)"; + if (this->glo_.has_group(group.name())) { + const auto &gl_group = this->glo_.group(group.name()); + return gl_group.max_total_gas(); } - else if (this->prod_wells_.count(well_name) == 1) { - well_ptr = this->prod_wells_.at(well_name); - std::tie(oil_rate, gas_rate) = getWellRates_(*well_ptr); - success = true; - if ( this->debug) debug_info = "(B)"; - } - - if (well_ptr) { - // we only want rates from wells owned by the rank - if (!well_state_.wellIsOwned(well_ptr->indexOfWell(), well_name)) { - success = false; - } - } - - if (success) { - assert(well_ptr); - assert(well_ptr->isProducer()); - alq = this->well_state_.getALQ(well_name); - if (this->debug) { - const std::string msg = fmt::format( - "Rates {} for well {} : oil: {}, gas: {}, alq: {}", - debug_info, well_name, oil_rate, gas_rate, alq); - displayDebugMessage_(msg, group_name); - } - // If wells have efficiency factors to take account of regular - // downtime (see keyword WEFAC), their lift gas injection - // rates are multiplied by their efficiency factors when they - // are added to the group lift gas supply rate. This is - // consistent with the summation of flow rates for wells with - // downtime, and preserves the ratio of production rate to - // lift gas injection rate. - const auto &well_ecl = well_ptr->wellEcl(); - double factor = well_ecl.getEfficiencyFactor(); - oil_rate *= factor; - gas_rate *= factor; - alq *= factor; - if (this->debug && (factor != 1)) { - const std::string msg = fmt::format( - "Well {} : efficiency factor {}. New rates : oil: {}, gas: {}, alq: {}", - well_name, factor, oil_rate, gas_rate, alq); - displayDebugMessage_(msg, group_name); - } - } - else { - // NOTE: This happens for wells that are not producers, or not active. - if (this->debug) { - const std::string msg = fmt::format("Could not determine current rates for " - "well {}: (not active or injector)", well_name); - displayDebugMessage_(msg, group_name); - } - oil_rate = 0.0; gas_rate = 0.0; alq = 0.0; - } - return std::make_tuple(oil_rate, gas_rate, alq); -} - -std::pair -GasLiftStage2:: -getWellRates_(const WellInterfaceGeneric &well) -{ - const int well_index = well.indexOfWell(); - const auto& ws = this->well_state_.well(well_index); - const auto& pu = well.phaseUsage(); - auto oil_rate = ws.well_potentials[pu.phase_pos[Oil]]; - double gas_rate = 0.0; - // See comment for setupPhaseVariables_() in GasLiftSingleWell_impl.hpp - // about the two-phase oil-water case. - if (pu.phase_used[BlackoilPhases::Vapour]) { - gas_rate = ws.well_potentials[pu.phase_pos[Gas]]; - } - return {oil_rate, gas_rate}; + return std::nullopt; // If GLIFTOPT is missing from schedule, assume unlimited alq } // Find all subordinate wells of a given group. @@ -517,13 +403,16 @@ void GasLiftStage2:: optimizeGroup_(const Group &group) { - const auto &gl_group = this->glo_.group(group.name()); - const auto &max_glift = gl_group.max_lift_gas(); - const auto &max_total_gas = gl_group.max_total_gas(); - if (group.has_control(Group::ProductionCMode::ORAT) - || max_glift || max_total_gas) + const auto& group_name = group.name(); + const auto prod_control = this->group_state_.production_control(group_name); + //if (group.has_control(Group::ProductionCMode::ORAT) || group.has_control(Group::ProductionCMode::LRAT) + // || max_glift || max_total_gas) + // NOTE: it only makes sense to try to optimize the distribution of the gaslift if the amount + // of gaslift is constrained either by the maximum allowed gaslift or total gas + // or the group is under individual control + if ((prod_control != Group::ProductionCMode::NONE) && (prod_control != Group::ProductionCMode::FLD)) { - displayDebugMessage_("optimizing", group.name()); + displayDebugMessage_("optimizing", group_name); auto wells = getGroupGliftWells_(group); std::vector inc_grads; std::vector dec_grads; @@ -531,7 +420,7 @@ optimizeGroup_(const Group &group) removeSurplusALQ_(group, inc_grads, dec_grads); } else { - displayDebugMessage_("skipping", group.name()); + displayDebugMessage_("skipping", group_name); } } @@ -546,22 +435,13 @@ optimizeGroupsRecursive_(const Group &group) group_name, this->report_step_idx_); optimizeGroupsRecursive_(sub_group); } - // TODO: should we also optimize groups that do not have GLIFTOPT defined? - // (i.e. glo_.has_group(name) returns false) - // IF GLIFTOPT is not specified for the group or if item 2 of GLIFTOPT - // is defaulted, there is no maximum lift gas supply for the group. - // But even if there is no limit on the liftgas supply it can still - // be desireable to use as little ALQ as possible to achieve a - // group oil rate limit or gas rate limit. - if (this->glo_.has_group(group.name())) // only optimize if GLIFTOPT is given - optimizeGroup_(group); - + optimizeGroup_(group); } void GasLiftStage2:: recalculateGradientAndUpdateData_( - GradPairItr &grad_itr, bool increase, + GradPairItr &grad_itr, const std::string& gr_name_dont_limit, bool increase, //incremental and decremental gradients, if 'grads' are incremental, then // 'other_grads' are decremental, or conversely, if 'grads' are decremental, then @@ -577,7 +457,7 @@ recalculateGradientAndUpdateData_( // the grads and other grads are synchronized later if(this->stage1_wells_.count(name) > 0) { GasLiftSingleWell &gs_well = *(this->stage1_wells_.at(name).get()); - auto grad = calcIncOrDecGrad_(name, gs_well, increase); + auto grad = calcIncOrDecGrad_(name, gs_well, gr_name_dont_limit, increase); if (grad) { grad_itr->second = grad->grad; old_grad = updateGrad_(name, *grad, increase); @@ -718,11 +598,11 @@ removeSurplusALQ_(const Group &group, return; } assert(!dec_grads.empty()); - const auto &gl_group = this->glo_.group(group.name()); - const auto &max_glift = gl_group.max_lift_gas(); + const auto max_glift = getGroupMaxALQ_(group); + const auto max_totalgas = getGroupMaxTotalGas_(group); const auto controls = group.productionControls(this->summary_state_); //const auto &max_total_gas = gl_group.max_total_gas(); - auto [oil_rate, gas_rate, alq] = getCurrentGroupRates_(group); + auto [oil_rate, gas_rate, water_rate, alq] = getCurrentGroupRates_(group); auto min_eco_grad = this->glo_.min_eco_gradient(); bool stop_iteration = false; if (this->debug) { @@ -730,12 +610,15 @@ removeSurplusALQ_(const Group &group, if (max_glift) max_glift_str = fmt::format("{}", *max_glift); const std::string msg = fmt::format("Starting iteration for group: {}. " "oil_rate = {}, oil_target = {}, gas_rate = {}, gas_target = {}, " - "alq = {}, max_alq = {}", group.name(), oil_rate, controls.oil_target, - gas_rate, controls.gas_target, alq, max_glift_str); + "water_rate = {}, liquid_target = {}, alq = {}, max_alq = {}", + group.name(), oil_rate, controls.oil_target, + gas_rate, controls.gas_target, water_rate, controls.liquid_target, + alq, max_glift_str); displayDebugMessage_(msg); } - SurplusState state {*this, group, oil_rate, gas_rate, alq, - min_eco_grad, controls.oil_target, controls.gas_target, max_glift }; + SurplusState state {*this, group, oil_rate, gas_rate, water_rate, alq, + min_eco_grad, controls.oil_target, controls.gas_target, controls.water_target, + controls.liquid_target, max_glift, max_totalgas }; while (!stop_iteration) { if (dec_grads.size() >= 2) { @@ -745,7 +628,12 @@ removeSurplusALQ_(const Group &group, const auto well_name = dec_grad_itr->first; auto eco_grad = dec_grad_itr->second; bool remove = false; - if (state.checkOilTarget() || state.checkGasTarget() || state.checkALQlimit()) { + const auto delta = state.computeDelta(well_name); + const auto& [delta_oil, delta_gas, delta_water, delta_alq] = delta; + if (state.checkOilTarget(delta_oil) || state.checkGasTarget(delta_gas) + || state.checkLiquidTarget(delta_oil + delta_water) || state.checkWaterTarget(delta_water) + || state.checkALQlimit(delta_alq, delta_gas)) + { remove = true; } else { @@ -757,10 +645,14 @@ removeSurplusALQ_(const Group &group, if (state.checkEcoGradient(well_name, eco_grad)) remove = true; } if (remove) { - state.updateRates(well_name); + state.updateRates(delta); state.addOrRemoveALQincrement( this->dec_grads_, well_name, /*add=*/false); + // We pass the current group rate in order to avoid limiting the rates + // and gaslift based on the current group limits. In other words we want to reduce + // the gasslift as much as possible as long as we are able to produce the group + // targets recalculateGradientAndUpdateData_( - dec_grad_itr, /*increase=*/false, dec_grads, inc_grads); + dec_grad_itr, group.name(), /*increase=*/false, dec_grads, inc_grads); // The dec_grads and inc_grads needs to be syncronized across ranks mpiSyncGlobalGradVector_(dec_grads); @@ -777,11 +669,11 @@ removeSurplusALQ_(const Group &group, } if (state.it >= 1) { if (this->debug) { - auto [oil_rate2, gas_rate2, alq2] = getCurrentGroupRates_(group); + auto [oil_rate2, gas_rate2, water_rate2, alq2] = getCurrentGroupRates_(group); const std::string msg = fmt::format( "Finished after {} iterations for group: {}." - " oil_rate = {}, gas_rate = {}, alq = {}", state.it, - group.name(), oil_rate2, gas_rate2, alq2); + " oil_rate = {}, gas_rate = {}, water_rate = {}, alq = {}", state.it, + group.name(), oil_rate2, gas_rate2, water_rate2, alq2); displayDebugMessage_(msg); } } @@ -867,12 +759,12 @@ calculateEcoGradients(std::vector &wells, for (auto well_ptr : wells) { const auto &gs_well = *well_ptr; // gs = GasLiftSingleWell const auto &name = gs_well.name(); - auto inc_grad = this->parent.calcIncOrDecGrad_(name, gs_well, /*increase=*/true); + auto inc_grad = this->parent.calcIncOrDecGrad_(name, gs_well, group.name(), /*increase=*/true); if (inc_grad) { inc_grads.emplace_back(std::make_pair(name, inc_grad->grad)); this->parent.saveIncGrad_(name, *inc_grad); } - auto dec_grad = this->parent.calcIncOrDecGrad_(name, gs_well, /*increase=*/false); + auto dec_grad = this->parent.calcIncOrDecGrad_(name, gs_well, group.name(), /*increase=*/false); if (dec_grad) { dec_grads.emplace_back(std::make_pair(name, dec_grad->grad)); this->parent.saveDecGrad_(name, *dec_grad); @@ -959,9 +851,9 @@ recalculateGradients( GradPairItr &min_dec_grad_itr, GradPairItr &max_inc_grad_itr) { this->parent.recalculateGradientAndUpdateData_( - max_inc_grad_itr, /*increase=*/true, inc_grads, dec_grads); + max_inc_grad_itr, this->group.name(), /*increase=*/true, inc_grads, dec_grads); this->parent.recalculateGradientAndUpdateData_( - min_dec_grad_itr, /*increase=*/false, dec_grads, inc_grads); + min_dec_grad_itr, this->group.name(), /*increase=*/false, dec_grads, inc_grads); // The dec_grads and inc_grads needs to be syncronized across ranks this->parent.mpiSyncGlobalGradVector_(dec_grads); @@ -1021,13 +913,11 @@ addOrRemoveALQincrement(GradMap &grad_map, const std::string& well_name, bool ad bool GasLiftStage2::SurplusState:: -checkALQlimit() +checkALQlimit(double delta_alq, double delta_gas) { if (this->max_glift) { double max_alq = *(this->max_glift); - double increment = this->parent.glo_.gaslift_increment(); - double epsilon = 1e-6 * increment; - if ((max_alq+epsilon) < this->alq ) { + if ((max_alq) < (this->alq + delta_alq) ) { if (this->parent.debug) { const std::string msg = fmt::format("group: {} : " "ALQ rate {} is greater than ALQ limit {}", this->group.name(), @@ -1037,6 +927,19 @@ checkALQlimit() return true; } } + if (this->max_total_gas) { + double max_total = *(this->max_total_gas); + double total_gas_rate = (this->alq + delta_alq + this->gas_rate + delta_gas); + if ((max_total) < total_gas_rate ) { + if (this->parent.debug) { + const std::string msg = fmt::format("group: {} : " + "Total gas rate {} is greater than Total gas limit {}", this->group.name(), + total_gas_rate, max_total); + this->parent.displayDebugMessage_(msg); + } + return true; + } + } return false; } @@ -1060,10 +963,10 @@ checkEcoGradient(const std::string &well_name, double eco_grad) bool GasLiftStage2::SurplusState:: -checkGasTarget() +checkGasTarget(double delta_gas) { if (this->group.has_control(Group::ProductionCMode::GRAT)) { - if (this->gas_target < this->gas_rate ) { + if (this->gas_target < (this->gas_rate + delta_gas) ) { if (this->parent.debug) { const std::string msg = fmt::format("group: {} : " "gas rate {} is greater than gas target {}", this->group.name(), @@ -1075,17 +978,19 @@ checkGasTarget() } return false; } - bool GasLiftStage2::SurplusState:: -checkOilTarget() +checkLiquidTarget(double delta_liquid) { - if (this->group.has_control(Group::ProductionCMode::ORAT)) { - if (this->oil_target < this->oil_rate ) { + if (this->group.has_control(Group::ProductionCMode::LRAT)) { + // the change in liquid rate from the is subtracted from the rate to make sure the + // group still can produce its target + auto liquid_rate = this->oil_rate + this->water_rate + delta_liquid; + if (this->liquid_target < (liquid_rate) ) { if (this->parent.debug) { const std::string msg = fmt::format("group: {} : " - "oil rate {} is greater than oil target {}", this->group.name(), - this->oil_rate, this->oil_target); + "liquid rate {} is greater than liquid target {}", this->group.name(), + liquid_rate, this->liquid_target); this->parent.displayDebugMessage_(msg); } return true; @@ -1094,11 +999,49 @@ checkOilTarget() return false; } -void +bool GasLiftStage2::SurplusState:: -updateRates(const std::string &well_name) +checkOilTarget(double delta_oil) { - std::array delta = {0.0,0.0,0.0}; + if (this->group.has_control(Group::ProductionCMode::ORAT)) { + // the change in oil rate from the eco_grad is subtracted from the rate to make sure the + // group still can produce its target + if (this->oil_target < (this->oil_rate + delta_oil) ) { + if (this->parent.debug) { + const std::string msg = fmt::format("group: {} : " + "oil rate {} is greater than oil target {}", this->group.name(), + this->oil_rate - delta_oil, this->oil_target); + this->parent.displayDebugMessage_(msg); + } + return true; + } + } + return false; +} + +bool +GasLiftStage2::SurplusState:: +checkWaterTarget(double delta_water) +{ + if (this->group.has_control(Group::ProductionCMode::WRAT)) { + if (this->water_target < (this->water_rate + delta_water) ) { + if (this->parent.debug) { + const std::string msg = fmt::format("group: {} : " + "water rate {} is greater than oil target {}", this->group.name(), + this->water_rate, this->water_target); + this->parent.displayDebugMessage_(msg); + } + return true; + } + } + return false; +} + +std::array +GasLiftStage2::SurplusState:: +computeDelta(const std::string &well_name) +{ + std::array delta = {0.0, 0.0, 0.0, 0.0}; // compute the delta on wells on own rank if (this->parent.well_state_map_.count(well_name) > 0) { const GradInfo &gi = this->parent.dec_grads_.at(well_name); @@ -1109,21 +1052,30 @@ updateRates(const std::string &well_name) if (this->parent.well_state_.wellIsOwned(well.indexOfWell(), well_name)) { const auto &well_ecl = well.wellEcl(); double factor = well_ecl.getEfficiencyFactor(); - auto& [delta_oil, delta_gas, delta_alq] = delta; - delta_oil = factor * (gi.new_oil_rate - state.oilRate()); - delta_gas = factor * (gi.new_gas_rate - state.gasRate()); - delta_alq = factor * (gi.alq - state.alq()); + auto& [delta_oil, delta_gas, delta_water, delta_alq] = delta; + delta_oil = factor * (gi.new_oil_rate - state.oilRate()); + delta_gas = factor * (gi.new_gas_rate - state.gasRate()); + delta_water = factor * (gi.new_water_rate - state.waterRate()); + delta_alq = factor * (gi.alq - state.alq()); } } // and communicate the results this->parent.comm_.sum(delta.data(), delta.size()); - // and update - const auto& [delta_oil, delta_gas, delta_alq] = delta; + return delta; +} + +void +GasLiftStage2::SurplusState:: +updateRates(const std::array& delta) +{ + const auto& [delta_oil, delta_gas, delta_water, delta_alq] = delta; this->oil_rate += delta_oil; this->gas_rate += delta_gas; + this->water_rate += delta_water; this->alq += delta_alq; } + } // namespace Opm diff --git a/opm/simulators/wells/GasLiftStage2.hpp b/opm/simulators/wells/GasLiftStage2.hpp index e2ce7bcbb..ae4c022ae 100644 --- a/opm/simulators/wells/GasLiftStage2.hpp +++ b/opm/simulators/wells/GasLiftStage2.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -66,8 +67,10 @@ public: const SummaryState& summary_state, DeferredLogger& deferred_logger, WellState& well_state, + const GroupState& group_state, GLiftProdWells& prod_wells, GLiftOptWells& glift_wells, + GasLiftGroupInfo& group_info, GLiftWellStateMap& state_map, bool glift_debug ); @@ -76,7 +79,7 @@ protected: void addOrRemoveALQincrement_( GradMap& grad_map, const std::string& well_name, bool add); std::optional calcIncOrDecGrad_( - const std::string name, const GasLiftSingleWell& gs_well, bool increase); + const std::string name, const GasLiftSingleWell& gs_well, const std::string& gr_name_dont_limit, bool increase); bool checkRateAlreadyLimited_(GasLiftWellState& state, bool increase); GradInfo deleteDecGradItem_(const std::string& name); GradInfo deleteIncGradItem_(const std::string& name); @@ -86,21 +89,17 @@ protected: void displayDebugMessage_(const std::string& msg, const std::string& group_name); void displayWarning_(const std::string& msg, const std::string& group_name); void displayWarning_(const std::string& msg); - std::tuple getCurrentGroupRates_( - const Group& group); - std::array getCurrentGroupRatesRecursive_( - const Group& group); - std::tuple getCurrentWellRates_( - const std::string& well_name, const std::string& group_name); + std::tuple getCurrentGroupRates_(const Group& group); + std::optional getGroupMaxALQ_(const Group &group); + std::optional getGroupMaxTotalGas_(const Group &group); std::vector getGroupGliftWells_( const Group& group); void getGroupGliftWellsRecursive_( const Group& group, std::vector& wells); - std::pair getWellRates_(const WellInterfaceGeneric& well); void optimizeGroup_(const Group& group); void optimizeGroupsRecursive_(const Group& group); void recalculateGradientAndUpdateData_( - GradPairItr& grad_itr, bool increase, + GradPairItr& grad_itr, const std::string& gr_name_dont_limit, bool increase, std::vector& grads, std::vector& other_grads); void redistributeALQ_( std::vector& wells, const Group& group, @@ -124,6 +123,7 @@ protected: GLiftProdWells& prod_wells_; GLiftOptWells& stage1_wells_; + GasLiftGroupInfo& group_info_; GLiftWellStateMap& well_state_map_; int report_step_idx_; @@ -169,38 +169,50 @@ protected: struct SurplusState { SurplusState( GasLiftStage2& parent_, const Group& group_, - double oil_rate_, double gas_rate_, double alq_, double min_eco_grad_, - double oil_target_, double gas_target_, - std::optional max_glift_) : + double oil_rate_, double gas_rate_, double water_rate_, double alq_, + double min_eco_grad_, + double oil_target_, double gas_target_, double water_target_, double liquid_target_, + std::optional max_glift_, std::optional max_total_gas_) : parent{parent_}, group{group_}, oil_rate{oil_rate_}, gas_rate{gas_rate_}, + water_rate{water_rate_}, alq{alq_}, min_eco_grad{min_eco_grad_}, oil_target{oil_target_}, gas_target{gas_target_}, + water_target(water_target_), + liquid_target{liquid_target_}, max_glift{max_glift_}, + max_total_gas{max_total_gas_}, it{0} {} GasLiftStage2 &parent; const Group &group; double oil_rate; double gas_rate; + double water_rate; double alq; const double min_eco_grad; const double oil_target; const double gas_target; + const double water_target; + const double liquid_target; std::optional max_glift; + std::optional max_total_gas; int it; void addOrRemoveALQincrement( GradMap &grad_map, const std::string& well_name, bool add); - bool checkALQlimit(); + bool checkALQlimit(double delta_alq, double delta_gas); bool checkEcoGradient(const std::string& well_name, double eco_grad); - bool checkGasTarget(); - bool checkOilTarget(); - void updateRates(const std::string& name); + bool checkGasTarget(double delta_gas); + bool checkLiquidTarget(double delta_liquid); + bool checkOilTarget(double delta_oil); + bool checkWaterTarget(double delta_water); + std::array computeDelta(const std::string& name); + void updateRates(const std::array& delta); }; }; diff --git a/opm/simulators/wells/GasLiftWellState.hpp b/opm/simulators/wells/GasLiftWellState.hpp index 204ed7534..3bda6db71 100644 --- a/opm/simulators/wells/GasLiftWellState.hpp +++ b/opm/simulators/wells/GasLiftWellState.hpp @@ -31,7 +31,7 @@ namespace Opm //GasLiftWellState() { } GasLiftWellState(double oil_rate, bool oil_is_limited, double gas_rate, bool gas_is_limited, - double alq, bool alq_is_limited, double water_rate, std::optional increase) : + double alq, bool alq_is_limited, double water_rate, bool water_is_limited, std::optional increase) : oil_rate_{oil_rate}, oil_is_limited_{oil_is_limited}, gas_rate_{gas_rate}, @@ -39,6 +39,7 @@ namespace Opm alq_{alq}, alq_is_limited_{alq_is_limited}, water_rate_{water_rate}, + water_is_limited_{water_is_limited}, increase_{increase} {} double alq() const { return alq_; } @@ -51,9 +52,11 @@ namespace Opm bool oilIsLimited() const { return oil_is_limited_; } double oilRate() const { return oil_rate_; } double waterRate() const { return water_rate_; } + bool waterIsLimited() const { return water_is_limited_; } void update(double oil_rate, bool oil_is_limited, double gas_rate, bool gas_is_limited, double alq, bool alq_is_limited, double water_rate, + double water_is_limited, bool increase) { oil_rate_ = oil_rate; @@ -63,6 +66,7 @@ namespace Opm alq_ = alq; alq_is_limited_ = alq_is_limited; water_rate_ = water_rate; + water_is_limited_ = water_is_limited; increase_ = increase; } private: @@ -73,6 +77,7 @@ namespace Opm double alq_; bool alq_is_limited_; double water_rate_; + bool water_is_limited_; std::optional increase_; }; diff --git a/opm/simulators/wells/WellInterface_impl.hpp b/opm/simulators/wells/WellInterface_impl.hpp index 51f07f1ad..7fd02ad39 100644 --- a/opm/simulators/wells/WellInterface_impl.hpp +++ b/opm/simulators/wells/WellInterface_impl.hpp @@ -346,7 +346,6 @@ namespace Opm deferred_logger.debug(msg); return; } - std::vector potentials; try { computeWellPotentials(simulator, well_state_copy, potentials, deferred_logger); diff --git a/tests/test_glift1.cpp b/tests/test_glift1.cpp index bc59097a6..31de21fe5 100644 --- a/tests/test_glift1.cpp +++ b/tests/test_glift1.cpp @@ -181,6 +181,7 @@ BOOST_AUTO_TEST_CASE(G1) well_model.phaseUsage(), deferred_logger, well_state, + group_state, comm, /*glift_debug=*/false };