diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index cad50ed06..07668d1bf 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -64,6 +64,7 @@ list (APPEND MAIN_SOURCE_FILES opm/simulators/utils/ParallelRestart.cpp opm/simulators/wells/ALQState.cpp opm/simulators/wells/BlackoilWellModelGeneric.cpp + opm/simulators/wells/GasLiftCommon.cpp opm/simulators/wells/GasLiftGroupInfo.cpp opm/simulators/wells/GasLiftSingleWellGeneric.cpp opm/simulators/wells/GasLiftStage2.cpp diff --git a/opm/simulators/wells/ALQState.cpp b/opm/simulators/wells/ALQState.cpp index 2172b762e..500b18edf 100644 --- a/opm/simulators/wells/ALQState.cpp +++ b/opm/simulators/wells/ALQState.cpp @@ -48,6 +48,19 @@ void ALQState::set(const std::string& wname, double value) { this->current_alq_[wname] = value; } +int ALQState::get_debug_counter() { + return this->debug_counter_; +} + +int ALQState::update_debug_counter() { + this->debug_counter_++; + return this->debug_counter_; +} + +void ALQState::set_debug_counter(int value) { + this->debug_counter_ = value; +} + namespace { int get_counter(const std::map& count_map, const std::string& wname) { diff --git a/opm/simulators/wells/ALQState.hpp b/opm/simulators/wells/ALQState.hpp index d9ba27dcf..3c166706e 100644 --- a/opm/simulators/wells/ALQState.hpp +++ b/opm/simulators/wells/ALQState.hpp @@ -42,12 +42,16 @@ public: void reset_count(); int get_increment_count(const std::string& wname) const; int get_decrement_count(const std::string& wname) const; + void set_debug_counter(int value); + int get_debug_counter(); + int update_debug_counter(); private: std::map current_alq_; std::map default_alq_; std::map alq_increase_count_; std::map alq_decrease_count_; + int debug_counter_ = 0; }; diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index 9ac30bb5a..310475754 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -2233,7 +2233,9 @@ gasLiftOptimizationStage2(DeferredLogger& deferred_logger, this->wellState(), prod_wells, glift_wells, - glift_well_state_map}; + glift_well_state_map, + this->glift_debug + }; glift.runOptimize(); } diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index f72f8611f..79edd0db8 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -896,7 +896,8 @@ namespace Opm { phase_usage_, deferred_logger, this->wellState(), - ebosSimulator_.vanguard().grid().comm() + ebosSimulator_.vanguard().grid().comm(), + this->glift_debug }; group_info.initialize(); gasLiftOptimizationStage1( @@ -951,9 +952,11 @@ namespace Opm { // NOTE: Only the wells in "group_info" needs to be optimized if (group_info.hasWell(well->name())) { well->gasLiftOptimizationStage1( - this->wellState(), this->groupState(), ebosSimulator_, deferred_logger, + this->wellState(), this->groupState(), ebosSimulator_, + deferred_logger, prod_wells, glift_wells, state_map, - group_info, groups_to_sync); + group_info, groups_to_sync, this->glift_debug + ); } } num_rates_to_sync = groups_to_sync.size(); @@ -1006,6 +1009,16 @@ namespace Opm { group_oil_rates[j], group_gas_rates[j], group_water_rates[j], group_alq_rates[j]); } } + if (this->glift_debug) { + int counter = 0; + if (comm.rank() == i) { + counter = this->wellState().gliftGetDebugCounter(); + } + counter = comm.sum(counter); + if (comm.rank() != i) { + this->wellState().gliftSetDebugCounter(counter); + } + } } } } diff --git a/opm/simulators/wells/GasLiftCommon.cpp b/opm/simulators/wells/GasLiftCommon.cpp new file mode 100644 index 000000000..88071979b --- /dev/null +++ b/opm/simulators/wells/GasLiftCommon.cpp @@ -0,0 +1,58 @@ +/* + Copyright 2022 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#include +#include + +namespace Opm { + +GasLiftCommon:: +GasLiftCommon( + WellState &well_state, + DeferredLogger &deferred_logger, + bool glift_debug +) : + well_state_{well_state}, + deferred_logger_{deferred_logger}, + debug{glift_debug} +{ + +} + +/**************************************** + * Protected methods in alphabetical order + ****************************************/ + +int +GasLiftCommon:: +debugUpdateGlobalCounter_() const +{ + auto count = this->well_state_.gliftUpdateDebugCounter(); + const std::string msg = fmt::format("global counter = {}", count); + displayDebugMessage_(msg); + return count; +} + + +/**************************************** + * Private methods in alphabetical order + ****************************************/ + + +} // namespace Opm diff --git a/opm/simulators/wells/GasLiftCommon.hpp b/opm/simulators/wells/GasLiftCommon.hpp new file mode 100644 index 000000000..e3af744ac --- /dev/null +++ b/opm/simulators/wells/GasLiftCommon.hpp @@ -0,0 +1,51 @@ +/* + Copyright 2022 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_GASLIFT_COMMON_HEADER_INCLUDED +#define OPM_GASLIFT_COMMON_HEADER_INCLUDED + +#include +#include + +#include +#include + +namespace Opm +{ +class GasLiftCommon +{ +public: + virtual ~GasLiftCommon() = default; + +protected: + GasLiftCommon( + WellState &well_state, + DeferredLogger &deferred_logger, + bool debug + ); + int debugUpdateGlobalCounter_() const; + virtual void displayDebugMessage_(const std::string& msg) const = 0; + bool debug; + DeferredLogger &deferred_logger_; + WellState &well_state_; +}; + +} // namespace Opm + +#endif // OPM_GASLIFT_COMMON_INCLUDED diff --git a/opm/simulators/wells/GasLiftGroupInfo.cpp b/opm/simulators/wells/GasLiftGroupInfo.cpp index 08e5462ec..0b268ce2f 100644 --- a/opm/simulators/wells/GasLiftGroupInfo.cpp +++ b/opm/simulators/wells/GasLiftGroupInfo.cpp @@ -32,19 +32,18 @@ GasLiftGroupInfo( const PhaseUsage &phase_usage, DeferredLogger &deferred_logger, WellState &well_state, - const Communication &comm + const Communication &comm, + bool glift_debug ) : - ecl_wells_{ecl_wells}, - schedule_{schedule}, - summary_state_{summary_state}, - report_step_idx_{report_step_idx}, - iteration_idx_{iteration_idx}, - phase_usage_{phase_usage}, - deferred_logger_{deferred_logger}, - well_state_{well_state}, - comm_{comm}, - glo_{schedule_.glo(report_step_idx_)}, - debug{false} + GasLiftCommon(well_state, deferred_logger, glift_debug) + , ecl_wells_{ecl_wells} + , schedule_{schedule} + , summary_state_{summary_state} + , report_step_idx_{report_step_idx} + , iteration_idx_{iteration_idx} + , phase_usage_{phase_usage} + , comm_{comm} + , glo_{schedule_.glo(report_step_idx_)} { } @@ -264,7 +263,7 @@ updateRate(int idx, double oil_rate, double gas_rate, double water_rate, double } /**************************************** - * Private methods in alphabetical order + * Protected methods in alphabetical order ****************************************/ @@ -353,7 +352,7 @@ checkNewtonIterationIdxOk_(const std::string &well_name) void GasLiftGroupInfo:: -displayDebugMessage_(const std::string &msg) +displayDebugMessage_(const std::string &msg) const { if (this->debug) { const std::string message = fmt::format( diff --git a/opm/simulators/wells/GasLiftGroupInfo.hpp b/opm/simulators/wells/GasLiftGroupInfo.hpp index 45f19e7cc..805188f0c 100644 --- a/opm/simulators/wells/GasLiftGroupInfo.hpp +++ b/opm/simulators/wells/GasLiftGroupInfo.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,8 +43,9 @@ namespace Opm { -class GasLiftGroupInfo +class GasLiftGroupInfo : public GasLiftCommon { +protected: class GroupRates; // NOTE: In the Well2GroupMap below, in the std::vector value we store // pairs of group names and efficiency factors. The efficiency factors @@ -79,7 +81,9 @@ public: const PhaseUsage& phase_usage, DeferredLogger& deferred_logger, WellState& well_state, - const Parallel::Communication& comm); + const Parallel::Communication& comm, + bool glift_debug + ); std::vector>& getWellGroups( const std::string& well_name); @@ -105,10 +109,10 @@ public: double delta_oil, double delta_gas, double delta_water, double delta_alq); void updateRate(int idx, double oil_rate, double gas_rate, double water_rate, double alq); const Well2GroupMap& wellGroupMap() { return well_group_map_; } -private: +protected: + void displayDebugMessage_(const std::string& msg) const override; bool checkDoGasLiftOptimization_(const std::string& well_name); bool checkNewtonIterationIdxOk_(const std::string& well_name); - void displayDebugMessage_(const std::string& msg); void displayDebugMessage_(const std::string& msg, const std::string& well_name); std::tuple getProducerWellRates_(const int index); std::tuple @@ -183,13 +187,10 @@ private: const int report_step_idx_; const int iteration_idx_; const PhaseUsage &phase_usage_; - DeferredLogger &deferred_logger_; - WellState &well_state_; const Parallel::Communication &comm_; const GasLiftOpt& glo_; GroupRateMap group_rate_map_; Well2GroupMap well_group_map_; - bool debug; GroupIdxMap group_idx_; int next_group_idx_ = 0; // Optimize only wells under THP control diff --git a/opm/simulators/wells/GasLiftSingleWell.hpp b/opm/simulators/wells/GasLiftSingleWell.hpp index 71c8df05b..70a8883aa 100644 --- a/opm/simulators/wells/GasLiftSingleWell.hpp +++ b/opm/simulators/wells/GasLiftSingleWell.hpp @@ -57,7 +57,8 @@ namespace Opm WellState &well_state, const GroupState& group_state, GasLiftGroupInfo &group_info, - GLiftSyncGroups &sync_groups + GLiftSyncGroups &sync_groups, + bool glift_debug ); const WellInterfaceGeneric &getStdWell() const override { return std_well_; } diff --git a/opm/simulators/wells/GasLiftSingleWellGeneric.cpp b/opm/simulators/wells/GasLiftSingleWellGeneric.cpp index 9f33fb38c..de5374df8 100644 --- a/opm/simulators/wells/GasLiftSingleWellGeneric.cpp +++ b/opm/simulators/wells/GasLiftSingleWellGeneric.cpp @@ -46,10 +46,10 @@ GasLiftSingleWellGeneric::GasLiftSingleWellGeneric( GasLiftGroupInfo &group_info, const Schedule& schedule, const int report_step_idx, - GLiftSyncGroups &sync_groups + GLiftSyncGroups &sync_groups, + bool glift_debug ) : - deferred_logger_{deferred_logger} - , well_state_{well_state} + GasLiftCommon(well_state, deferred_logger, glift_debug) , group_state_{group_state} , ecl_well_{ecl_well} , summary_state_{summary_state} @@ -57,7 +57,6 @@ GasLiftSingleWellGeneric::GasLiftSingleWellGeneric( , sync_groups_{sync_groups} , controls_{ecl_well_.productionControls(summary_state_)} , num_phases_{well_state_.numPhases()} - , debug_{false} // extra debugging output , debug_limit_increase_decrease_{false} { this->well_name_ = ecl_well_.name(); @@ -80,7 +79,6 @@ GasLiftSingleWellGeneric::GasLiftSingleWellGeneric( // injection (which seems strange) this->eco_grad_ = glo.min_eco_gradient(); gl_well_ = &glo.well(this->well_name_); - } /**************************************** @@ -134,7 +132,7 @@ runOptimize(const int iteration_idx) // (either increase or decrease) if (state->increase()) { // ALQ changed.. double alq = state->alq(); - if (this->debug_) + if (this->debug) logSuccess_(alq, iteration_idx); this->well_state_.setALQ(this->well_name_, alq); } @@ -232,7 +230,7 @@ checkGroupTargetsViolated(double delta_oil, double delta_gas, double delta_water double oil_rate = this->group_info_.oilRate(group_name) + efficiency * delta_oil; if (oil_rate > *oil_target_opt) { - if (this->debug_) { + if (this->debug) { const std::string msg = fmt::format( "Group {} : oil rate {} exceeds oil target {}. Stopping iteration", group_name, oil_rate, *oil_target_opt); @@ -246,7 +244,7 @@ checkGroupTargetsViolated(double delta_oil, double delta_gas, double delta_water double gas_rate = this->group_info_.gasRate(group_name) + efficiency * delta_gas; if (gas_rate > *gas_target_opt) { - if (this->debug_) { + if (this->debug) { const std::string msg = fmt::format( "Group {} : gas rate {} exceeds gas target {}. Stopping iteration", group_name, gas_rate, *gas_target_opt); @@ -263,7 +261,7 @@ checkGroupTargetsViolated(double delta_oil, double delta_gas, double delta_water this->group_info_.waterRate(group_name) + efficiency * delta_water; double liquid_rate = oil_rate + water_rate; if (liquid_rate > *liquid_target_opt) { - if (this->debug_) { + if (this->debug) { const std::string msg = fmt::format( "Group {} : liquid rate {} exceeds liquid target {}. Stopping iteration", group_name, liquid_rate, *liquid_target_opt); @@ -277,7 +275,7 @@ checkGroupTargetsViolated(double delta_oil, double delta_gas, double delta_water double water_rate = this->group_info_.waterRate(group_name) + efficiency * delta_water; if (water_rate > *water_target_opt) { - if (this->debug_) { + if (this->debug) { const std::string msg = fmt::format( "Group {} : water rate {} exceeds water target {}. Stopping iteration", group_name, water_rate, *water_target_opt); @@ -483,7 +481,7 @@ GasLiftSingleWellGeneric:: displayDebugMessage_(const std::string& msg) const { - if (this->debug_) { + if (this->debug) { const std::string message = fmt::format( " GLIFT (DEBUG) : Well {} : {}", this->well_name_, msg); this->deferred_logger_.info(message); @@ -749,7 +747,7 @@ getRateWithGroupLimit_( } } } - if (this->debug_ && group_name) { + if (this->debug && group_name) { const std::string msg = fmt::format( "limiting {} rate from {} to {} to meet group target {} " "for group {}. Computed group rate was: {}", @@ -887,7 +885,7 @@ maybeAdjustALQbeforeOptimizeLoop_( std::vector &potentials) { double orig_alq = alq; - if (this->debug_) { + if (this->debug) { const std::string msg = fmt::format("initial ALQ: {}", alq); displayDebugMessage_(msg); } @@ -928,7 +926,7 @@ maybeAdjustALQbeforeOptimizeLoop_( oil_is_limited, gas_is_limited, potentials); } } - if (this->debug_ && (orig_alq != alq)) { + if (this->debug && (orig_alq != alq)) { const std::string msg = fmt::format("adjusted ALQ to: {}", alq); displayDebugMessage_(msg); } @@ -1035,7 +1033,7 @@ reduceALQtoWellTarget_(double alq, std::tie(gas_rate, gas_is_limited) = getGasRateWithLimit_(potentials); std::tie(water_rate, water_is_limited) = getWaterRateWithLimit_(potentials); - if (this->debug_) { + if (this->debug) { assert( alq <= orig_alq ); std::string type; double target = 0.0; @@ -1098,9 +1096,9 @@ runOptimizeLoop_(bool increase) double oil_rate, gas_rate, water_rate; std::tie(oil_rate, gas_rate, water_rate, oil_is_limited, gas_is_limited, water_is_limited) = getInitialRatesWithLimit_(potentials); - //if (this->debug_) debugShowBhpAlqTable_(); - if (this->debug_) debugShowAlqIncreaseDecreaseCounts_(); - if (this->debug_) debugShowTargets_(); + //if (this->debug) debugShowBhpAlqTable_(); + if (this->debug) debugShowAlqIncreaseDecreaseCounts_(); + if (this->debug) debugShowTargets_(); bool success = false; // did we succeed to increase alq? auto cur_alq = this->orig_alq_; double new_oil_rate, new_gas_rate, new_water_rate, new_alq; @@ -1143,7 +1141,7 @@ runOptimizeLoop_(bool increase) } auto temp_alq = cur_alq; - if (this->debug_) debugShowStartIteration_(temp_alq, increase, oil_rate); + if (this->debug) debugShowStartIteration_(temp_alq, increase, oil_rate); while (!state.stop_iteration && (++state.it <= this->max_iterations_)) { if (!increase && state.checkNegativeOilRate(oil_rate)) break; if (state.checkWellRatesViolated(potentials)) break; @@ -1156,7 +1154,7 @@ runOptimizeLoop_(bool increase) delta_alq = *alq_opt - temp_alq; if (state.checkGroupALQrateExceeded(delta_alq)) break; temp_alq = *alq_opt; - if (this->debug_) state.debugShowIterationInfo(temp_alq); + if (this->debug) state.debugShowIterationInfo(temp_alq); if (!state.computeBhpAtThpLimit(temp_alq)) break; // NOTE: if BHP is below limit, we set state.stop_iteration = true auto bhp = state.getBhpWithLimit(); @@ -1194,7 +1192,7 @@ runOptimizeLoop_(bool increase) */ auto gradient = state.calcEcoGradient( oil_rate, new_oil_rate, gas_rate, new_gas_rate); - if (this->debug_) + if (this->debug) debugCheckNegativeGradient_( gradient, cur_alq, temp_alq, oil_rate, new_oil_rate, gas_rate, new_gas_rate, increase); @@ -1492,7 +1490,7 @@ checkAlqOutsideLimits(double alq, [[maybe_unused]] double oil_rate) } } } - if (this->parent.debug_) { + if (this->parent.debug) { const std::string msg = ss.str(); if (!msg.empty()) this->parent.displayDebugMessage_(msg); @@ -1512,7 +1510,7 @@ checkGroupALQrateExceeded(double delta_alq) double alq = this->parent.group_info_.alqRate(group_name) + efficiency * delta_alq; if (alq > *max_alq_opt) { - if (this->parent.debug_) { + if (this->parent.debug) { const std::string msg = fmt::format( "Group {} : alq {} exceeds max_alq {}. Stopping iteration", group_name, alq, *max_alq_opt); @@ -1568,30 +1566,30 @@ checkEcoGradient(double gradient) std::ostringstream ss; bool result = false; - if (this->parent.debug_) { + if (this->parent.debug) { 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"; + if (this->parent.debug) ss << "no, continue"; } } else { // decreasing lift gas - 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"; + 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; } @@ -1600,7 +1598,7 @@ GasLiftSingleWellGeneric::OptimizeState:: checkRate(double rate, double limit, const std::string& rate_str) const { if (limit < rate) { - if (this->parent.debug_) { + if (this->parent.debug) { const std::string msg = fmt::format( "iteration {} : {} rate {} exceeds target {}. Stopping iteration", this->it, rate_str, rate, limit); diff --git a/opm/simulators/wells/GasLiftSingleWellGeneric.hpp b/opm/simulators/wells/GasLiftSingleWellGeneric.hpp index aa339a3da..aa2ea6c88 100644 --- a/opm/simulators/wells/GasLiftSingleWellGeneric.hpp +++ b/opm/simulators/wells/GasLiftSingleWellGeneric.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,7 @@ class WellInterfaceGeneric; class WellState; class GroupState; -class GasLiftSingleWellGeneric +class GasLiftSingleWellGeneric : public GasLiftCommon { protected: static const int Water = BlackoilPhases::Aqua; @@ -102,7 +103,8 @@ protected: GasLiftGroupInfo &group_info, const Schedule& schedule, const int report_step_idx, - GLiftSyncGroups &sync_groups + GLiftSyncGroups &sync_groups, + bool glift_debug ); struct OptimizeState @@ -174,7 +176,7 @@ protected: void debugShowTargets_(); - void displayDebugMessage_(const std::string& msg) const; + void displayDebugMessage_(const std::string& msg) const override; void displayWarning_(const std::string& warning); std::pair getBhpWithLimit_(double bhp) const; @@ -249,8 +251,6 @@ protected: void warnMaxIterationsExceeded_(); - DeferredLogger& deferred_logger_; - WellState& well_state_; const GroupState& group_state_; const Well& ecl_well_; const SummaryState& summary_state_; @@ -279,7 +279,6 @@ protected: const GasLiftOpt::Well* gl_well_; bool optimize_; - bool debug_; // extra debug output bool debug_limit_increase_decrease_; bool debug_abort_if_decrease_and_oil_is_limited_ = false; bool debug_abort_if_increase_and_gas_is_limited_ = false; diff --git a/opm/simulators/wells/GasLiftSingleWell_impl.hpp b/opm/simulators/wells/GasLiftSingleWell_impl.hpp index 6d192c8f8..af161521b 100644 --- a/opm/simulators/wells/GasLiftSingleWell_impl.hpp +++ b/opm/simulators/wells/GasLiftSingleWell_impl.hpp @@ -28,7 +28,8 @@ GasLiftSingleWell(const StdWell &std_well, WellState &well_state, const GroupState &group_state, GasLiftGroupInfo &group_info, - GLiftSyncGroups &sync_groups + GLiftSyncGroups &sync_groups, + bool glift_debug ) // The parent class GasLiftSingleWellGeneric contains all stuff // that is not dependent on TypeTag @@ -41,7 +42,8 @@ GasLiftSingleWell(const StdWell &std_well, group_info, ebos_simulator.vanguard().schedule(), ebos_simulator.episodeIndex(), - sync_groups + sync_groups, + glift_debug ) , ebos_simulator_{ebos_simulator} , std_well_{std_well} diff --git a/opm/simulators/wells/GasLiftStage2.cpp b/opm/simulators/wells/GasLiftStage2.cpp index 9fbe1f341..cdc7bea9c 100644 --- a/opm/simulators/wells/GasLiftStage2.cpp +++ b/opm/simulators/wells/GasLiftStage2.cpp @@ -46,19 +46,18 @@ GasLiftStage2::GasLiftStage2( WellState &well_state, GLiftProdWells &prod_wells, GLiftOptWells &glift_wells, - GLiftWellStateMap &state_map + GLiftWellStateMap &state_map, + bool glift_debug ) : - deferred_logger_{deferred_logger}, - well_state_{well_state}, - prod_wells_{prod_wells}, - stage1_wells_{glift_wells}, - well_state_map_{state_map}, - report_step_idx_{report_step_idx}, - summary_state_{summary_state}, - schedule_{schedule}, - glo_{schedule_.glo(report_step_idx_)}, - comm_{comm}, - debug_{false} + GasLiftCommon(well_state, deferred_logger, glift_debug) + , prod_wells_{prod_wells} + , stage1_wells_{glift_wells} + , well_state_map_{state_map} + , report_step_idx_{report_step_idx} + , summary_state_{summary_state} + , schedule_{schedule} + , glo_{schedule_.glo(report_step_idx_)} + , comm_{comm} { // this->time_step_idx_ // = this->ebos_simulator_.model().newtonMethod().currentTimeStep(); @@ -89,7 +88,7 @@ runOptimize() /******************************************** - * Private methods in alphabetical order + * Protected methods in alphabetical order ********************************************/ // Update GasLiftWellState and WellState for "well_name" to the @@ -106,7 +105,7 @@ addOrRemoveALQincrement_(GradMap &grad_map, const std::string& well_name, bool a GasLiftWellState &state = *(it->second.get()); const GradInfo &gi = grad_map.at(well_name); - if (this->debug_) { + if (this->debug) { auto new_alq = gi.alq; auto old_alq = state.alq(); const std::string msg = fmt::format("well {} : {} ALQ increment, " @@ -237,9 +236,9 @@ displayWarning_(const std::string &msg) void GasLiftStage2:: -displayDebugMessage_(const std::string &msg) +displayDebugMessage_(const std::string &msg) const { - if (this->debug_) { + if (this->debug) { const std::string message = fmt::format( " GLIFT2 (DEBUG) : {}", msg); this->deferred_logger_.info(message); @@ -250,7 +249,7 @@ void GasLiftStage2:: displayDebugMessage2B_(const std::string &msg) { - if (this->debug_) { + if (this->debug) { const std::string message = fmt::format( "Stage 2B : {}", msg); displayDebugMessage_(message); @@ -261,7 +260,7 @@ void GasLiftStage2:: displayDebugMessage_(const std::string &msg, const std::string &group_name) { - if (this->debug_) { + if (this->debug) { const std::string message = fmt::format( "Group {} : {}", group_name, msg); displayDebugMessage_(message); @@ -275,7 +274,7 @@ 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_) { + if (this->debug) { const std::string msg = fmt::format( "Current group rates for {} : oil: {}, gas: {}, alq: {}", group.name(), oil_rate, gas_rate, alq); @@ -342,13 +341,13 @@ getCurrentWellRates_(const std::string &well_name, const std::string &group_name 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->debug) debug_info = "(A)"; } else if (this->prod_wells_.count(well_name) == 1) { well_ptr = this->prod_wells_.at(well_name); std::tie(oil_rate, gas_rate) = getStdWellRates_(*well_ptr); success = true; - if ( this->debug_) debug_info = "(B)"; + if ( this->debug) debug_info = "(B)"; } if (well_ptr) { @@ -362,7 +361,7 @@ getCurrentWellRates_(const std::string &well_name, const std::string &group_name assert(well_ptr); assert(well_ptr->isProducer()); alq = this->well_state_.getALQ(well_name); - if (this->debug_) { + if (this->debug) { const std::string msg = fmt::format( "Rates {} for well {} : oil: {}, gas: {}, alq: {}", debug_info, well_name, oil_rate, gas_rate, alq); @@ -380,7 +379,7 @@ getCurrentWellRates_(const std::string &well_name, const std::string &group_name oil_rate *= factor; gas_rate *= factor; alq *= factor; - if (this->debug_ && (factor != 1)) { + 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); @@ -389,7 +388,7 @@ getCurrentWellRates_(const std::string &well_name, const std::string &group_name } else { // NOTE: This happens for wells that are not producers, or not active. - if (this->debug_) { + 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); @@ -716,7 +715,7 @@ removeSurplusALQ_(const Group &group, auto [oil_rate, gas_rate, alq] = getCurrentGroupRates_(group); auto min_eco_grad = this->glo_.min_eco_gradient(); bool stop_iteration = false; - if (this->debug_) { + if (this->debug) { std::string max_glift_str = "unlimited"; if (max_glift) max_glift_str = fmt::format("{}", *max_glift); const std::string msg = fmt::format("Starting iteration for group: {}. " @@ -767,7 +766,7 @@ removeSurplusALQ_(const Group &group, } } if (state.it >= 1) { - if (this->debug_) { + if (this->debug) { auto [oil_rate2, gas_rate2, alq2] = getCurrentGroupRates_(group); const std::string msg = fmt::format( "Finished after {} iterations for group: {}." @@ -1002,7 +1001,7 @@ void GasLiftStage2::SurplusState:: addOrRemoveALQincrement(GradMap &grad_map, const std::string& well_name, bool add) { - if (this->parent.debug_) { + if (this->parent.debug) { const std::string msg = fmt::format("group: {} : well {} : {} ALQ increment", this->group.name(), well_name, (add ? "adding" : "subtracting")); this->parent.displayDebugMessage2B_(msg); @@ -1019,7 +1018,7 @@ checkALQlimit() double increment = this->parent.glo_.gaslift_increment(); double epsilon = 1e-6 * increment; if ((max_alq+epsilon) < this->alq ) { - if (this->parent.debug_) { + if (this->parent.debug) { const std::string msg = fmt::format("group: {} : " "ALQ rate {} is greater than ALQ limit {}", this->group.name(), this->alq, max_alq); @@ -1036,7 +1035,7 @@ GasLiftStage2::SurplusState:: checkEcoGradient(const std::string &well_name, double eco_grad) { if (eco_grad < this->min_eco_grad) { - if (this->parent.debug_) { + if (this->parent.debug) { const std::string msg = fmt::format("group: {}, well: {} : " "economic gradient {} less than minimum ({})", this->group.name(), well_name, eco_grad, this->min_eco_grad); @@ -1055,7 +1054,7 @@ checkGasTarget() { if (this->group.has_control(Group::ProductionCMode::GRAT)) { if (this->gas_target < this->gas_rate ) { - if (this->parent.debug_) { + if (this->parent.debug) { const std::string msg = fmt::format("group: {} : " "gas rate {} is greater than gas target {}", this->group.name(), this->gas_rate, this->gas_target); @@ -1073,7 +1072,7 @@ checkOilTarget() { if (this->group.has_control(Group::ProductionCMode::ORAT)) { if (this->oil_target < this->oil_rate ) { - if (this->parent.debug_) { + 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); diff --git a/opm/simulators/wells/GasLiftStage2.hpp b/opm/simulators/wells/GasLiftStage2.hpp index f17c0ef95..dfeaa8680 100644 --- a/opm/simulators/wells/GasLiftStage2.hpp +++ b/opm/simulators/wells/GasLiftStage2.hpp @@ -45,7 +45,7 @@ class Schedule; class WellInterfaceGeneric; class WellState; -class GasLiftStage2 { +class GasLiftStage2 : public GasLiftCommon { using GasLiftSingleWell = GasLiftSingleWellGeneric; using GLiftOptWells = std::map>; using GLiftProdWells = std::map; @@ -68,10 +68,11 @@ public: WellState& well_state, GLiftProdWells& prod_wells, GLiftOptWells& glift_wells, - GLiftWellStateMap& state_map + GLiftWellStateMap& state_map, + bool glift_debug ); void runOptimize(); -private: +protected: void addOrRemoveALQincrement_( GradMap& grad_map, const std::string& well_name, bool add); std::optional calcIncOrDecGrad_( @@ -80,7 +81,7 @@ private: GradInfo deleteDecGradItem_(const std::string& name); GradInfo deleteIncGradItem_(const std::string& name); GradInfo deleteGrad_(const std::string& name, bool increase); - void displayDebugMessage_(const std::string& msg); + void displayDebugMessage_(const std::string& msg) const override; void displayDebugMessage2B_(const std::string& msg); void displayDebugMessage_(const std::string& msg, const std::string& group_name); void displayWarning_(const std::string& msg, const std::string& group_name); @@ -121,8 +122,6 @@ private: std::vector& grads_global) const; - DeferredLogger& deferred_logger_; - WellState& well_state_; GLiftProdWells& prod_wells_; GLiftOptWells& stage1_wells_; GLiftWellStateMap& well_state_map_; @@ -134,7 +133,6 @@ private: const Parallel::Communication& comm_; GradMap inc_grads_; GradMap dec_grads_; - bool debug_; int max_iterations_ = 1000; //int time_step_idx_; diff --git a/opm/simulators/wells/MultisegmentWell.hpp b/opm/simulators/wells/MultisegmentWell.hpp index abb911d41..699331f36 100644 --- a/opm/simulators/wells/MultisegmentWell.hpp +++ b/opm/simulators/wells/MultisegmentWell.hpp @@ -108,7 +108,8 @@ namespace Opm GLiftOptWells &, GLiftWellStateMap &, GasLiftGroupInfo &, - GLiftSyncGroups & + GLiftSyncGroups &, + bool ) const override { // Not implemented yet } diff --git a/opm/simulators/wells/StandardWell.hpp b/opm/simulators/wells/StandardWell.hpp index d0cd63749..3c3101e10 100644 --- a/opm/simulators/wells/StandardWell.hpp +++ b/opm/simulators/wells/StandardWell.hpp @@ -211,7 +211,8 @@ namespace Opm GLiftOptWells &glift_wells, GLiftWellStateMap &state_map, GasLiftGroupInfo &group_info, - GLiftSyncGroups &sync_groups + GLiftSyncGroups &sync_groups, + bool glift_debug ) const override; /* returns BHP */ diff --git a/opm/simulators/wells/StandardWellGeneric.cpp b/opm/simulators/wells/StandardWellGeneric.cpp index 543ce31ed..c258c5814 100644 --- a/opm/simulators/wells/StandardWellGeneric.cpp +++ b/opm/simulators/wells/StandardWellGeneric.cpp @@ -193,111 +193,6 @@ computeConnectionPressureDelta() baseif_.parallelWellInfo().partialSumPerfValues(beg, end); } -template -void -StandardWellGeneric:: -gliftDebug(const std::string &msg, - DeferredLogger& deferred_logger) const -{ - if (glift_debug) { - const std::string message = fmt::format( - " GLIFT (DEBUG) : SW : Well {} : {}", baseif_.name(), msg); - deferred_logger.info(message); - } -} - -template -bool -StandardWellGeneric:: -checkGliftNewtonIterationIdxOk(const int report_step_idx, - const int iteration_idx, - const Schedule& schedule, - DeferredLogger& deferred_logger ) const -{ - const GasLiftOpt& glo = schedule.glo(report_step_idx); - if (glo.all_newton()) { - const int nupcol = schedule[report_step_idx].nupcol(); - if (this->glift_debug) { - const std::string msg = fmt::format( - "LIFTOPT item4 == YES, it = {}, nupcol = {} --> GLIFT optimize = {}", - iteration_idx, - nupcol, - ((iteration_idx <= nupcol) ? "TRUE" : "FALSE")); - gliftDebug(msg, deferred_logger); - } - return iteration_idx <= nupcol; - } - else { - if (this->glift_debug) { - const std::string msg = fmt::format( - "LIFTOPT item4 == NO, it = {} --> GLIFT optimize = {}", - iteration_idx, ((iteration_idx == 1) ? "TRUE" : "FALSE")); - gliftDebug(msg, deferred_logger); - } - return iteration_idx == 1; - } -} - -/* At this point we know that the well does not have BHP control mode and - that it does have THP constraints, see computeWellPotentials(). - * TODO: Currently we limit the application of gas lift optimization to wells - * operating under THP control mode, does it make sense to - * extend it to other modes? - */ -template -bool -StandardWellGeneric:: -doGasLiftOptimize(const WellState &well_state, - const int report_step_idx, - const int iteration_idx, - const Schedule& schedule, - DeferredLogger& deferred_logger) const -{ - if (well_state.gliftCheckAlqOscillation(baseif_.name())) { - gliftDebug("further optimization skipped due to oscillation in ALQ", - deferred_logger); - return false; - } - if (glift_optimize_only_thp_wells) { - const int well_index = baseif_.indexOfWell(); - auto control_mode = well_state.well(well_index).production_cmode; - if (control_mode != Well::ProducerCMode::THP ) { - gliftDebug("Not THP control", deferred_logger); - return false; - } - } - if (!checkGliftNewtonIterationIdxOk(report_step_idx, - iteration_idx, - schedule, - deferred_logger)) { - return false; - } - const GasLiftOpt& glo = schedule.glo(report_step_idx); - if (!glo.has_well(baseif_.name())) { - gliftDebug("Gas Lift not activated: WLIFTOPT is probably missing", - deferred_logger); - return false; - } - auto increment = glo.gaslift_increment(); - // NOTE: According to the manual: LIFTOPT, item 1, : - // "Increment size for lift gas injection rate. Lift gas is - // allocated to individual wells in whole numbers of the increment - // size. If gas lift optimization is no longer required, it can be - // turned off by entering a zero or negative number." - if (increment <= 0) { - if (glift_debug) { - const std::string msg = fmt::format( - "Gas Lift switched off in LIFTOPT item 1 due to non-positive " - "value: {}", increment); - gliftDebug(msg, deferred_logger); - } - return false; - } - else { - return true; - } -} - template std::optional StandardWellGeneric:: diff --git a/opm/simulators/wells/StandardWellGeneric.hpp b/opm/simulators/wells/StandardWellGeneric.hpp index 057cd01b9..bdb18c297 100644 --- a/opm/simulators/wells/StandardWellGeneric.hpp +++ b/opm/simulators/wells/StandardWellGeneric.hpp @@ -107,18 +107,6 @@ protected: DeferredLogger& deferred_logger, double alq_value) const; - void gliftDebug(const std::string &msg, - DeferredLogger& deferred_logger) const; - bool checkGliftNewtonIterationIdxOk(const int report_step_idx, - const int iteration_idx, - const Schedule& schedule, - DeferredLogger& deferred_logger) const; - bool doGasLiftOptimize(const WellState &well_state, - const int report_step_idx, - const int iteration_idx, - const Schedule& schedule, - DeferredLogger& deferred_logger) const; - // Base interface reference const WellInterfaceGeneric& baseif_; @@ -130,11 +118,6 @@ protected: // pressure drop between different perforations std::vector perf_pressure_diffs_; - // Enable GLIFT debug mode. This will enable output of logging messages. - bool glift_debug = false; - // Optimize only wells under THP control - bool glift_optimize_only_thp_wells = true; - // two off-diagonal matrices OffDiagMatWell duneB_; OffDiagMatWell duneC_; diff --git a/opm/simulators/wells/StandardWell_impl.hpp b/opm/simulators/wells/StandardWell_impl.hpp index d32eda972..eee8c5cb0 100644 --- a/opm/simulators/wells/StandardWell_impl.hpp +++ b/opm/simulators/wells/StandardWell_impl.hpp @@ -1824,14 +1824,16 @@ namespace Opm GLiftOptWells &glift_wells, GLiftWellStateMap &glift_state_map, GasLiftGroupInfo &group_info, - GLiftSyncGroups &sync_groups + GLiftSyncGroups &sync_groups, + bool glift_debug ) const { const auto& summary_state = ebos_simulator.vanguard().summaryState(); std::unique_ptr glift = std::make_unique( *this, ebos_simulator, summary_state, - deferred_logger, well_state, group_state, group_info, sync_groups); + deferred_logger, well_state, group_state, group_info, + sync_groups, glift_debug); auto state = glift->runOptimize( ebos_simulator.model().newtonMethod().numIterations()); if (state) { diff --git a/opm/simulators/wells/WellInterface.hpp b/opm/simulators/wells/WellInterface.hpp index 585bb3015..25871e13e 100644 --- a/opm/simulators/wells/WellInterface.hpp +++ b/opm/simulators/wells/WellInterface.hpp @@ -168,7 +168,8 @@ public: GLiftOptWells& glift_wells, GLiftWellStateMap& state_map, GasLiftGroupInfo &group_info, - GLiftSyncGroups &sync_groups + GLiftSyncGroups &sync_groups, + bool glift_debug ) const = 0; /// using the solution x to recover the solution xw for wells and applying diff --git a/opm/simulators/wells/WellState.hpp b/opm/simulators/wells/WellState.hpp index c27580322..96bd6ad8e 100644 --- a/opm/simulators/wells/WellState.hpp +++ b/opm/simulators/wells/WellState.hpp @@ -164,6 +164,18 @@ public: this->alq_state.set(name, value); } + int gliftGetDebugCounter() { + return this->alq_state.get_debug_counter(); + } + + void gliftSetDebugCounter(int value) { + return this->alq_state.set_debug_counter(value); + } + + int gliftUpdateDebugCounter() { + return this->alq_state.update_debug_counter(); + } + bool gliftCheckAlqOscillation(const std::string &name) const { return this->alq_state.oscillation(name); } diff --git a/tests/test_glift1.cpp b/tests/test_glift1.cpp index 43c126e32..77d09724f 100644 --- a/tests/test_glift1.cpp +++ b/tests/test_glift1.cpp @@ -181,11 +181,14 @@ BOOST_AUTO_TEST_CASE(G1) well_model.phaseUsage(), deferred_logger, well_state, - simulator->vanguard().grid().comm() + simulator->vanguard().grid().comm(), + /*glift_debug=*/false }; GLiftSyncGroups sync_groups; GasLiftSingleWell glift {*std_well, *(simulator.get()), summary_state, - deferred_logger, well_state, group_state, group_info, sync_groups}; + deferred_logger, well_state, group_state, group_info, sync_groups, + /*glift_debug=*/false + }; group_info.initialize(); auto state = glift.runOptimize(iteration_idx); BOOST_CHECK_CLOSE(state->oilRate(), 0.01736111111111111, 1e-8);