mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4214 from totto82/glift3_fix
Fixes related to gaslift stage 2
This commit is contained in:
commit
5c26be0c28
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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}
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <opm/simulators/utils/DeferredLogger.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <fmt/format.h>
|
||||
@ -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;
|
||||
|
@ -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<double>
|
||||
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<double, double, double, double>
|
||||
GasLiftGroupInfo::
|
||||
@ -437,36 +478,56 @@ displayDebugMessage_(const std::string &msg, const std::string &well_name)
|
||||
}
|
||||
|
||||
|
||||
std::tuple<double, double, double>
|
||||
std::tuple<double, double, double, double, double, double>
|
||||
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<double, double, double, double>
|
||||
std::tuple<double, double, double, double, double, double, double>
|
||||
GasLiftGroupInfo::
|
||||
initializeGroupRatesRecursive_(const Group &group)
|
||||
{
|
||||
std::array<double,4> rates{};
|
||||
std::array<double,7> 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
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/simulators/wells/GasLiftCommon.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
#include <opm/simulators/utils/DeferredLogger.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
@ -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<double,double,double,double> getRates(const int group_idx) const;
|
||||
std::optional<double> gasTarget(const std::string& group_name) const;
|
||||
std::optional<double> 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<double, double, double> getProducerWellRates_(const int index);
|
||||
std::tuple<double, double, double, double>
|
||||
std::tuple<double, double, double, double, double, double>
|
||||
getProducerWellRates_(const Well* well, const int index);
|
||||
std::tuple<double, double, double, double, double, double, double>
|
||||
initializeGroupRatesRecursive_(const Group &group);
|
||||
void initializeWell2GroupMapRecursive_(
|
||||
const Group& group, std::vector<std::string>& 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<double> oil_target,
|
||||
std::optional<double> gas_target,
|
||||
std::optional<double> 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<double> oilTarget() const { return oil_target_; }
|
||||
std::optional<double> 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<double> oil_target_;
|
||||
std::optional<double> gas_target_;
|
||||
std::optional<double> water_target_;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,7 @@
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
#include <opm/simulators/wells/GasLiftGroupInfo.hpp>
|
||||
#include <opm/simulators/wells/GasLiftCommon.hpp>
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@ -93,7 +94,10 @@ public:
|
||||
const std::string& name() const { return well_name_; }
|
||||
|
||||
std::optional<GradInfo> 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<GasLiftWellState> 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<std::optional<double>, bool> addOrSubtractAlqIncrement_(
|
||||
@ -272,14 +276,14 @@ protected:
|
||||
std::pair<double, bool> getGasRateWithLimit_(
|
||||
const BasicRates& rates) const;
|
||||
std::pair<double, bool> 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<std::optional<LimitedRates>,double> getInitialRatesWithLimit_() const;
|
||||
LimitedRates getLimitedRatesFromRates_(const BasicRates& rates) const;
|
||||
std::tuple<double,double,bool,bool> 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<double, bool> 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<double, bool> getOilRateWithLimit_(const BasicRates& rates) const;
|
||||
std::pair<double, std::optional<Rate>> getOilRateWithLimit2_(
|
||||
const BasicRates& rates) const;
|
||||
@ -288,9 +292,9 @@ protected:
|
||||
std::pair<double, std::optional<Rate>> getRateWithLimit_(
|
||||
Rate rate_type, const BasicRates& rates) const;
|
||||
std::tuple<double, const std::string*, double> 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<double, bool> 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<double, bool> getWaterRateWithLimit_(const BasicRates& rates) const;
|
||||
std::pair<double, std::optional<Rate>> 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_;
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <opm/simulators/wells/GasLiftWellState.hpp>
|
||||
#include <opm/simulators/wells/WellInterfaceGeneric.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
#include <opm/simulators/wells/GasLiftGroupInfo.hpp>
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@ -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<double> 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<double> 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::GradInfo>
|
||||
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<double, double, double>
|
||||
std::tuple<double, double, double, double>
|
||||
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 <double, 3>
|
||||
GasLiftStage2::
|
||||
getCurrentGroupRatesRecursive_(const Group &group)
|
||||
std::optional<double>
|
||||
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<double, double, double>
|
||||
GasLiftStage2::
|
||||
getCurrentWellRates_(const std::string &well_name, const std::string &group_name)
|
||||
std::optional<double>
|
||||
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<double, double>
|
||||
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<GradPair> inc_grads;
|
||||
std::vector<GradPair> 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<GasLiftSingleWell *> &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<double, 3> 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<double, 4>
|
||||
GasLiftStage2::SurplusState::
|
||||
computeDelta(const std::string &well_name)
|
||||
{
|
||||
std::array<double, 4> 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<double, 4>& 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
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <opm/core/props/BlackoilPhases.hpp>
|
||||
#include <opm/simulators/wells/GasLiftSingleWellGeneric.hpp>
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
|
||||
#include <dune/common/version.hh>
|
||||
#include <dune/common/parallel/mpihelper.hh>
|
||||
@ -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<GradInfo> 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<double, double, double> getCurrentGroupRates_(
|
||||
const Group& group);
|
||||
std::array<double,3> getCurrentGroupRatesRecursive_(
|
||||
const Group& group);
|
||||
std::tuple<double, double, double> getCurrentWellRates_(
|
||||
const std::string& well_name, const std::string& group_name);
|
||||
std::tuple<double, double, double, double> getCurrentGroupRates_(const Group& group);
|
||||
std::optional<double> getGroupMaxALQ_(const Group &group);
|
||||
std::optional<double> getGroupMaxTotalGas_(const Group &group);
|
||||
std::vector<GasLiftSingleWell *> getGroupGliftWells_(
|
||||
const Group& group);
|
||||
void getGroupGliftWellsRecursive_(
|
||||
const Group& group, std::vector<GasLiftSingleWell *>& wells);
|
||||
std::pair<double, double> 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<GradPair>& grads, std::vector<GradPair>& other_grads);
|
||||
void redistributeALQ_(
|
||||
std::vector<GasLiftSingleWell *>& 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<double> 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<double> max_glift_, std::optional<double> 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<double> max_glift;
|
||||
std::optional<double> 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<double, 4> computeDelta(const std::string& name);
|
||||
void updateRates(const std::array<double, 4>& delta);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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<bool> increase) :
|
||||
double alq, bool alq_is_limited, double water_rate, bool water_is_limited, std::optional<bool> 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<bool> increase_;
|
||||
};
|
||||
|
||||
|
@ -346,7 +346,6 @@ namespace Opm
|
||||
deferred_logger.debug(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<double> potentials;
|
||||
try {
|
||||
computeWellPotentials(simulator, well_state_copy, potentials, deferred_logger);
|
||||
|
@ -181,6 +181,7 @@ BOOST_AUTO_TEST_CASE(G1)
|
||||
well_model.phaseUsage(),
|
||||
deferred_logger,
|
||||
well_state,
|
||||
group_state,
|
||||
comm,
|
||||
/*glift_debug=*/false
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user