Merge pull request #5303 from akva2/gaslift_template_scalar

GasLift: template Scalar type
This commit is contained in:
Atgeirr Flø Rasmussen 2024-05-14 09:59:42 +02:00 committed by GitHub
commit 226410cd44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 1587 additions and 1230 deletions

View File

@ -118,8 +118,8 @@ class WellContributions;
using GLiftProdWells = typename BlackoilWellModelGeneric<Scalar>::GLiftProdWells; using GLiftProdWells = typename BlackoilWellModelGeneric<Scalar>::GLiftProdWells;
using GLiftWellStateMap = using GLiftWellStateMap =
typename BlackoilWellModelGeneric<Scalar>::GLiftWellStateMap; typename BlackoilWellModelGeneric<Scalar>::GLiftWellStateMap;
using GLiftEclWells = typename GasLiftGroupInfo::GLiftEclWells; using GLiftEclWells = typename GasLiftGroupInfo<Scalar>::GLiftEclWells;
using GLiftSyncGroups = typename GasLiftSingleWellGeneric::GLiftSyncGroups; using GLiftSyncGroups = typename GasLiftSingleWellGeneric<Scalar>::GLiftSyncGroups;
constexpr static std::size_t pressureVarIndex = GetPropType<TypeTag, Properties::Indices>::pressureSwitchIdx; constexpr static std::size_t pressureVarIndex = GetPropType<TypeTag, Properties::Indices>::pressureSwitchIdx;
typedef typename BaseAuxiliaryModule<TypeTag>::NeighborSet NeighborSet; typedef typename BaseAuxiliaryModule<TypeTag>::NeighborSet NeighborSet;
@ -524,14 +524,18 @@ class WellContributions;
bool maybeDoGasLiftOptimize(DeferredLogger& deferred_logger); bool maybeDoGasLiftOptimize(DeferredLogger& deferred_logger);
void gasLiftOptimizationStage1(DeferredLogger& deferred_logger, void gasLiftOptimizationStage1(DeferredLogger& deferred_logger,
GLiftProdWells &prod_wells, GLiftOptWells &glift_wells, GLiftProdWells& prod_wells,
GasLiftGroupInfo &group_info, GLiftWellStateMap &state_map); GLiftOptWells& glift_wells,
GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap& state_map);
// cannot be const since it accesses the non-const WellState // cannot be const since it accesses the non-const WellState
void gasLiftOptimizationStage1SingleWell(WellInterface<TypeTag>* well, void gasLiftOptimizationStage1SingleWell(WellInterface<TypeTag>* well,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
GLiftProdWells &prod_wells, GLiftOptWells &glift_wells, GLiftProdWells& prod_wells,
GasLiftGroupInfo &group_info, GLiftWellStateMap &state_map, GLiftOptWells& glift_wells,
GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap& state_map,
GLiftSyncGroups& groups_to_sync); GLiftSyncGroups& groups_to_sync);
void extractLegacyCellPvtRegionIndex_(); void extractLegacyCellPvtRegionIndex_();

View File

@ -1397,7 +1397,7 @@ void BlackoilWellModelGeneric<Scalar>::
gasLiftOptimizationStage2(DeferredLogger& deferred_logger, gasLiftOptimizationStage2(DeferredLogger& deferred_logger,
GLiftProdWells& prod_wells, GLiftProdWells& prod_wells,
GLiftOptWells& glift_wells, GLiftOptWells& glift_wells,
GasLiftGroupInfo& group_info, GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap& glift_well_state_map, GLiftWellStateMap& glift_well_state_map,
const int episodeIndex) const int episodeIndex)
{ {

View File

@ -53,9 +53,9 @@
namespace Opm { namespace Opm {
class DeferredLogger; class DeferredLogger;
class EclipseState; class EclipseState;
class GasLiftGroupInfo; template<class Scalar> class GasLiftGroupInfo;
class GasLiftSingleWellGeneric; template<class Scalar> class GasLiftSingleWellGeneric;
class GasLiftWellState; template<class Scalar> class GasLiftWellState;
class Group; class Group;
class GuideRateConfig; class GuideRateConfig;
class ParallelWellInfo; class ParallelWellInfo;
@ -83,9 +83,9 @@ class BlackoilWellModelGeneric
{ {
public: public:
// --------- Types --------- // --------- Types ---------
using GLiftOptWells = std::map<std::string, std::unique_ptr<GasLiftSingleWellGeneric>>; using GLiftOptWells = std::map<std::string, std::unique_ptr<GasLiftSingleWellGeneric<Scalar>>>;
using GLiftProdWells = std::map<std::string, const WellInterfaceGeneric*>; using GLiftProdWells = std::map<std::string, const WellInterfaceGeneric*>;
using GLiftWellStateMap = std::map<std::string, std::unique_ptr<GasLiftWellState>>; using GLiftWellStateMap = std::map<std::string, std::unique_ptr<GasLiftWellState<Scalar>>>;
BlackoilWellModelGeneric(Schedule& schedule, BlackoilWellModelGeneric(Schedule& schedule,
const SummaryState& summaryState, const SummaryState& summaryState,
@ -387,7 +387,7 @@ protected:
void gasLiftOptimizationStage2(DeferredLogger& deferred_logger, void gasLiftOptimizationStage2(DeferredLogger& deferred_logger,
GLiftProdWells& prod_wells, GLiftProdWells& prod_wells,
GLiftOptWells& glift_wells, GLiftOptWells& glift_wells,
GasLiftGroupInfo& group_info, GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap& map, GLiftWellStateMap& map,
const int episodeIndex); const int episodeIndex);

View File

@ -1343,8 +1343,10 @@ namespace Opm {
void void
BlackoilWellModel<TypeTag>:: BlackoilWellModel<TypeTag>::
gasLiftOptimizationStage1(DeferredLogger& deferred_logger, gasLiftOptimizationStage1(DeferredLogger& deferred_logger,
GLiftProdWells &prod_wells, GLiftOptWells &glift_wells, GLiftProdWells& prod_wells,
GasLiftGroupInfo &group_info, GLiftWellStateMap &state_map) GLiftOptWells &glift_wells,
GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap& state_map)
{ {
auto comm = simulator_.vanguard().grid().comm(); auto comm = simulator_.vanguard().grid().comm();
int num_procs = comm.size(); int num_procs = comm.size();
@ -1450,8 +1452,10 @@ namespace Opm {
BlackoilWellModel<TypeTag>:: BlackoilWellModel<TypeTag>::
gasLiftOptimizationStage1SingleWell(WellInterface<TypeTag>* well, gasLiftOptimizationStage1SingleWell(WellInterface<TypeTag>* well,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
GLiftProdWells &prod_wells, GLiftOptWells &glift_wells, GLiftProdWells& prod_wells,
GasLiftGroupInfo &group_info, GLiftWellStateMap &state_map, GLiftOptWells& glift_wells,
GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap& state_map,
GLiftSyncGroups& sync_groups) GLiftSyncGroups& sync_groups)
{ {
const auto& summary_state = simulator_.vanguard().summaryState(); const auto& summary_state = simulator_.vanguard().summaryState();

View File

@ -28,30 +28,27 @@
namespace Opm { namespace Opm {
GasLiftCommon:: template<class Scalar>
GasLiftCommon( GasLiftCommon<Scalar>::
WellState<double>& well_state, GasLiftCommon(WellState<Scalar>& well_state,
const GroupState<double>& group_state, const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
const Parallel::Communication& comm, const Parallel::Communication& comm,
bool glift_debug bool glift_debug)
) : : well_state_{well_state}
well_state_{well_state}, , group_state_{group_state}
group_state_{group_state}, , deferred_logger_{deferred_logger}
deferred_logger_{deferred_logger}, , comm_{comm}
comm_{comm}, , debug{glift_debug}
debug{glift_debug} {}
{
}
/**************************************** /****************************************
* Protected methods in alphabetical order * Protected methods in alphabetical order
****************************************/ ****************************************/
template<class Scalar>
int int
GasLiftCommon:: GasLiftCommon<Scalar>::debugUpdateGlobalCounter_() const
debugUpdateGlobalCounter_() const
{ {
auto count = this->well_state_.gliftUpdateDebugCounter(); auto count = this->well_state_.gliftUpdateDebugCounter();
const std::string msg = fmt::format("global counter = {}", count); const std::string msg = fmt::format("global counter = {}", count);
@ -59,8 +56,8 @@ debugUpdateGlobalCounter_() const
return count; return count;
} }
void template<class Scalar>
GasLiftCommon:: void GasLiftCommon<Scalar>::
displayDebugMessageOnRank0_(const std::string& msg) const displayDebugMessageOnRank0_(const std::string& msg) const
{ {
// This output should be identical for all ranks. // This output should be identical for all ranks.
@ -71,12 +68,13 @@ displayDebugMessageOnRank0_(const std::string &msg) const
} }
} }
void template<class Scalar>
GasLiftCommon:: void GasLiftCommon<Scalar>::
logMessage_( logMessage_(const std::string& prefix,
const std::string& prefix, const std::string& msg, MessageType msg_type) const const std::string& msg,
MessageType msg_type) const
{ {
std::string rank = ""; std::string rank;
if (this->comm_.size() > 1) { if (this->comm_.size() > 1) {
rank = fmt::format(" Rank #{} :", this->comm_.rank()); rank = fmt::format(" Rank #{} :", this->comm_.rank());
} }
@ -105,9 +103,6 @@ logMessage_(
} }
} }
/**************************************** template class GasLiftCommon<double>;
* Private methods in alphabetical order
****************************************/
} // namespace Opm } // namespace Opm

View File

@ -24,38 +24,36 @@
#include <string> #include <string>
namespace Opm namespace Opm {
{
class DeferredLogger; class DeferredLogger;
template<class Scalar> class GroupState; template<class Scalar> class GroupState;
template<class Scalar> class WellState; template<class Scalar> class WellState;
template<class Scalar>
class GasLiftCommon class GasLiftCommon
{ {
public: public:
virtual ~GasLiftCommon() = default; virtual ~GasLiftCommon() = default;
protected: protected:
GasLiftCommon( GasLiftCommon(WellState<Scalar>& well_state,
WellState<double>& well_state, const GroupState<Scalar>& group_state,
const GroupState<double>& group_state,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
const Parallel::Communication& comm, const Parallel::Communication& comm,
bool debug bool glift_debug);
);
enum class MessageType { INFO, WARNING }; enum class MessageType { INFO, WARNING };
int debugUpdateGlobalCounter_() const; int debugUpdateGlobalCounter_() const;
virtual void displayDebugMessage_(const std::string& msg) const = 0; virtual void displayDebugMessage_(const std::string& msg) const = 0;
void displayDebugMessageOnRank0_(const std::string& msg) const; void displayDebugMessageOnRank0_(const std::string& msg) const;
void logMessage_( void logMessage_(const std::string& prefix,
const std::string& prefix,
const std::string& msg, const std::string& msg,
MessageType msg_type = MessageType::INFO) const; MessageType msg_type = MessageType::INFO) const;
WellState<double>& well_state_; WellState<Scalar>& well_state_;
const GroupState<double>& group_state_; const GroupState<Scalar>& group_state_;
DeferredLogger& deferred_logger_; DeferredLogger& deferred_logger_;
const Parallel::Communication& comm_; const Parallel::Communication& comm_;
bool debug; bool debug;

View File

@ -32,21 +32,20 @@
namespace Opm { namespace Opm {
GasLiftGroupInfo:: template<class Scalar>
GasLiftGroupInfo( GasLiftGroupInfo<Scalar>::
GLiftEclWells &ecl_wells, GasLiftGroupInfo(GLiftEclWells& ecl_wells,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summary_state, const SummaryState& summary_state,
const int report_step_idx, const int report_step_idx,
const int iteration_idx, const int iteration_idx,
const PhaseUsage& phase_usage, const PhaseUsage& phase_usage,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
WellState<double>& well_state, WellState<Scalar>& well_state,
const GroupState<double>& group_state, const GroupState<Scalar>& group_state,
const Communication& comm, const Communication& comm,
bool glift_debug bool glift_debug)
) : : GasLiftCommon<Scalar>(well_state, group_state, deferred_logger, comm, glift_debug)
GasLiftCommon(well_state, group_state, deferred_logger, comm, glift_debug)
, ecl_wells_{ecl_wells} , ecl_wells_{ecl_wells}
, schedule_{schedule} , schedule_{schedule}
, summary_state_{summary_state} , summary_state_{summary_state}
@ -54,69 +53,70 @@ GasLiftGroupInfo(
, iteration_idx_{iteration_idx} , iteration_idx_{iteration_idx}
, phase_usage_{phase_usage} , phase_usage_{phase_usage}
, glo_{schedule_.glo(report_step_idx_)} , glo_{schedule_.glo(report_step_idx_)}
{ {}
}
/**************************************** /****************************************
* Public methods in alphabetical order * Public methods in alphabetical order
****************************************/ ****************************************/
double template<class Scalar>
GasLiftGroupInfo:: Scalar GasLiftGroupInfo<Scalar>::
alqRate(const std::string& group_name) alqRate(const std::string& group_name)
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.alq(); return group_rate.alq();
} }
int template<class Scalar>
GasLiftGroupInfo:: int GasLiftGroupInfo<Scalar>::
getGroupIdx(const std::string& group_name) getGroupIdx(const std::string& group_name)
{ {
return this->group_idx_.at(group_name); return this->group_idx_.at(group_name);
} }
double template<class Scalar>
GasLiftGroupInfo:: Scalar GasLiftGroupInfo<Scalar>::
gasRate(const std::string& group_name) const gasRate(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.gasRate(); return group_rate.gasRate();
} }
double template<class Scalar>
GasLiftGroupInfo:: Scalar GasLiftGroupInfo<Scalar>::
gasPotential(const std::string& group_name) const gasPotential(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.gasPotential(); return group_rate.gasPotential();
} }
double
GasLiftGroupInfo:: template<class Scalar>
Scalar GasLiftGroupInfo<Scalar>::
waterPotential(const std::string& group_name) const waterPotential(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.waterPotential(); return group_rate.waterPotential();
} }
double
GasLiftGroupInfo:: template<class Scalar>
Scalar GasLiftGroupInfo<Scalar>::
oilPotential(const std::string& group_name) const oilPotential(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.oilPotential(); return group_rate.oilPotential();
} }
std::optional<double> template<class Scalar>
GasLiftGroupInfo:: std::optional<Scalar>
GasLiftGroupInfo<Scalar>::
gasTarget(const std::string& group_name) const gasTarget(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.gasTarget(); return group_rate.gasTarget();
} }
double template<class Scalar>
GasLiftGroupInfo:: Scalar GasLiftGroupInfo<Scalar>::
getRate(Rate rate_type, const std::string& group_name) const getRate(Rate rate_type, const std::string& group_name) const
{ {
switch (rate_type) { switch (rate_type) {
@ -133,8 +133,9 @@ getRate(Rate rate_type, const std::string& group_name) const
throw std::runtime_error("This should not happen"); throw std::runtime_error("This should not happen");
} }
} }
double
GasLiftGroupInfo:: template<class Scalar>
Scalar GasLiftGroupInfo<Scalar>::
getPotential(Rate rate_type, const std::string& group_name) const getPotential(Rate rate_type, const std::string& group_name) const
{ {
switch (rate_type) { switch (rate_type) {
@ -152,8 +153,9 @@ getPotential(Rate rate_type, const std::string& group_name) const
} }
} }
std::tuple<double, double, double, double> template<class Scalar>
GasLiftGroupInfo:: std::tuple<Scalar, Scalar, Scalar, Scalar>
GasLiftGroupInfo<Scalar>::
getRates(const int group_idx) const getRates(const int group_idx) const
{ {
const auto& group_name = groupIdxToName(group_idx); const auto& group_name = groupIdxToName(group_idx);
@ -161,8 +163,9 @@ getRates(const int group_idx) const
return std::make_tuple(rates.oilRate(), rates.gasRate(), rates.waterRate(), rates.alq()); return std::make_tuple(rates.oilRate(), rates.gasRate(), rates.waterRate(), rates.alq());
} }
std::optional<double> template<class Scalar>
GasLiftGroupInfo:: std::optional<Scalar>
GasLiftGroupInfo<Scalar>::
getTarget(Rate rate_type, const std::string& group_name) const getTarget(Rate rate_type, const std::string& group_name) const
{ {
switch (rate_type) { switch (rate_type) {
@ -180,16 +183,18 @@ getTarget(Rate rate_type, const std::string& group_name) const
} }
} }
std::vector<std::pair<std::string,double>>& template<class Scalar>
GasLiftGroupInfo:: std::vector<std::pair<std::string,Scalar>>&
GasLiftGroupInfo<Scalar>::
getWellGroups(const std::string& well_name) getWellGroups(const std::string& well_name)
{ {
assert(this->well_group_map_.count(well_name) == 1); assert(this->well_group_map_.count(well_name) == 1);
return this->well_group_map_[well_name]; return this->well_group_map_[well_name];
} }
template<class Scalar>
const std::string& const std::string&
GasLiftGroupInfo:: GasLiftGroupInfo<Scalar>::
groupIdxToName(int group_idx) const groupIdxToName(int group_idx) const
{ {
const std::string* group_name = nullptr; const std::string* group_name = nullptr;
@ -209,75 +214,80 @@ groupIdxToName(int group_idx) const
return *group_name; return *group_name;
} }
bool template<class Scalar>
GasLiftGroupInfo:: bool GasLiftGroupInfo<Scalar>::
hasAnyTarget(const std::string& group_name) const hasAnyTarget(const std::string& group_name) const
{ {
return oilTarget(group_name) || gasTarget(group_name) return oilTarget(group_name) || gasTarget(group_name)
|| waterTarget(group_name) || liquidTarget(group_name); || waterTarget(group_name) || liquidTarget(group_name);
} }
bool template<class Scalar>
GasLiftGroupInfo:: bool GasLiftGroupInfo<Scalar>::
hasWell(const std::string& well_name) hasWell(const std::string& well_name)
{ {
return this->well_group_map_.count(well_name) == 1; return this->well_group_map_.count(well_name) == 1;
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
initialize() initialize()
{ {
const auto& group = this->schedule_.getGroup("FIELD", this->report_step_idx_); const auto& group = this->schedule_.getGroup("FIELD", this->report_step_idx_);
initializeGroupRatesRecursive_(group); initializeGroupRatesRecursive_(group);
std::vector<std::string> group_names; std::vector<std::string> group_names;
std::vector<double> group_efficiency; std::vector<Scalar> group_efficiency;
initializeWell2GroupMapRecursive_( initializeWell2GroupMapRecursive_(
group, group_names, group_efficiency, /*current efficiency=*/1.0); group, group_names, group_efficiency, /*current efficiency=*/1.0);
} }
std::optional<double> template<class Scalar>
GasLiftGroupInfo:: std::optional<Scalar>
GasLiftGroupInfo<Scalar>::
liquidTarget(const std::string& group_name) const liquidTarget(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.liquidTarget(); return group_rate.liquidTarget();
} }
std::optional<double> template<class Scalar>
GasLiftGroupInfo:: std::optional<Scalar>
GasLiftGroupInfo<Scalar>::
maxAlq(const std::string& group_name) maxAlq(const std::string& group_name)
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.maxAlq(); return group_rate.maxAlq();
} }
std::optional<double> template<class Scalar>
GasLiftGroupInfo:: std::optional<Scalar>
GasLiftGroupInfo<Scalar>::
maxTotalGasRate(const std::string& group_name) maxTotalGasRate(const std::string& group_name)
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.maxTotalGasRate(); return group_rate.maxTotalGasRate();
} }
double template<class Scalar>
GasLiftGroupInfo:: Scalar GasLiftGroupInfo<Scalar>::
oilRate(const std::string& group_name) const oilRate(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.oilRate(); return group_rate.oilRate();
} }
std::optional<double> template<class Scalar>
GasLiftGroupInfo:: std::optional<Scalar>
GasLiftGroupInfo<Scalar>::
oilTarget(const std::string& group_name) const oilTarget(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.oilTarget(); return group_rate.oilTarget();
} }
template<class Scalar>
const std::string const std::string
GasLiftGroupInfo:: GasLiftGroupInfo<Scalar>::
rateToString(Rate rate) { rateToString(Rate rate) {
switch (rate) { switch (rate) {
case Rate::oil: case Rate::oil:
@ -293,34 +303,42 @@ rateToString(Rate rate) {
} }
} }
double template<class Scalar>
GasLiftGroupInfo:: Scalar GasLiftGroupInfo<Scalar>::
waterRate(const std::string& group_name) const waterRate(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.waterRate(); return group_rate.waterRate();
} }
std::optional<double> template<class Scalar>
GasLiftGroupInfo:: std::optional<Scalar>
GasLiftGroupInfo<Scalar>::
waterTarget(const std::string& group_name) const waterTarget(const std::string& group_name) const
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
return group_rate.waterTarget(); return group_rate.waterTarget();
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
update( update(const std::string& group_name,
const std::string &group_name, double delta_oil, double delta_gas, double delta_water, double delta_alq) Scalar delta_oil,
Scalar delta_gas,
Scalar delta_water,
Scalar delta_alq)
{ {
auto& group_rate = this->group_rate_map_.at(group_name); auto& group_rate = this->group_rate_map_.at(group_name);
group_rate.update(delta_oil, delta_gas, delta_water, delta_alq); group_rate.update(delta_oil, delta_gas, delta_water, delta_alq);
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
updateRate(int idx, double oil_rate, double gas_rate, double water_rate, double alq) updateRate(int idx,
Scalar oil_rate,
Scalar gas_rate,
Scalar water_rate,
Scalar alq)
{ {
const auto& group_name = groupIdxToName(idx); const auto& group_name = groupIdxToName(idx);
auto& rates = this->group_rate_map_.at(group_name); auto& rates = this->group_rate_map_.at(group_name);
@ -331,9 +349,8 @@ updateRate(int idx, double oil_rate, double gas_rate, double water_rate, double
* Protected methods in alphabetical order * Protected methods in alphabetical order
****************************************/ ****************************************/
template<class Scalar>
bool bool GasLiftGroupInfo<Scalar>::
GasLiftGroupInfo::
checkDoGasLiftOptimization_(const std::string& well_name) checkDoGasLiftOptimization_(const std::string& well_name)
{ {
if (this->well_state_.gliftCheckAlqOscillation(well_name)) { if (this->well_state_.gliftCheckAlqOscillation(well_name)) {
@ -390,8 +407,8 @@ checkDoGasLiftOptimization_(const std::string &well_name)
} }
} }
bool template<class Scalar>
GasLiftGroupInfo:: bool GasLiftGroupInfo<Scalar>::
checkNewtonIterationIdxOk_(const std::string& well_name) checkNewtonIterationIdxOk_(const std::string& well_name)
{ {
if (this->glo_.all_newton()) { if (this->glo_.all_newton()) {
@ -420,16 +437,19 @@ checkNewtonIterationIdxOk_(const std::string &well_name)
// This is called by each rank, but the value of "well_name" should be unique // This is called by each rank, but the value of "well_name" should be unique
// across ranks // across ranks
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
debugDisplayWellContribution_( debugDisplayWellContribution_(const std::string& gr_name,
const std::string& gr_name, const std::string& well_name, const std::string& well_name,
double eff_factor, Scalar eff_factor,
double well_oil_rate, double well_gas_rate, double well_water_rate, Scalar well_oil_rate,
double well_alq, Scalar well_gas_rate,
double oil_rate, double gas_rate, double water_rate, Scalar well_water_rate,
double alq Scalar well_alq,
) const Scalar oil_rate,
Scalar gas_rate,
Scalar water_rate,
Scalar alq) const
{ {
const std::string msg = fmt::format("Group rate for {} : Well {} : " const std::string msg = fmt::format("Group rate for {} : Well {} : "
"eff_factor = {}, oil_rate = {}, gas_rate = {}, water_rate = {}, " "eff_factor = {}, oil_rate = {}, gas_rate = {}, water_rate = {}, "
@ -439,46 +459,48 @@ debugDisplayWellContribution_(
displayDebugMessage_(msg); displayDebugMessage_(msg);
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
debugDisplayUpdatedGroupRates( debugDisplayUpdatedGroupRates(const std::string& name,
const std::string& name, Scalar oil_rate,
double oil_rate, double gas_rate, double water_rate, double alq) const Scalar gas_rate,
Scalar water_rate,
Scalar alq) const
{ {
const std::string msg = fmt::format("Updated group info for {} : " const std::string msg = fmt::format("Updated group info for {} : "
"oil_rate = {}, gas_rate = {}, water_rate = {}, alq = {}", "oil_rate = {}, gas_rate = {}, water_rate = {}, alq = {}",
name, oil_rate, gas_rate, water_rate, alq); name, oil_rate, gas_rate, water_rate, alq);
displayDebugMessageOnRank0_(msg); this->displayDebugMessageOnRank0_(msg);
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
debugEndInitializeGroup(const std::string& name) const debugEndInitializeGroup(const std::string& name) const
{ {
const std::string msg = fmt::format("Finished with group {} ...", name); const std::string msg = fmt::format("Finished with group {} ...", name);
displayDebugMessageOnRank0_(msg); this->displayDebugMessageOnRank0_(msg);
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
debugStartInitializeGroup(const std::string& name) const debugStartInitializeGroup(const std::string& name) const
{ {
const std::string msg = fmt::format("Initializing group {} ...", name); const std::string msg = fmt::format("Initializing group {} ...", name);
displayDebugMessageOnRank0_(msg); this->displayDebugMessageOnRank0_(msg);
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
displayDebugMessage_(const std::string& msg) const displayDebugMessage_(const std::string& msg) const
{ {
if (this->debug) { if (this->debug) {
const std::string message = fmt::format("Init group info : {}", msg); const std::string message = fmt::format("Init group info : {}", msg);
logMessage_(/*prefix=*/"GLIFT", message); this->logMessage_(/*prefix=*/"GLIFT", message);
} }
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
displayDebugMessage_(const std::string& msg, const std::string& well_name) displayDebugMessage_(const std::string& msg, const std::string& well_name)
{ {
if (this->debug) { if (this->debug) {
@ -487,9 +509,9 @@ displayDebugMessage_(const std::string &msg, const std::string &well_name)
} }
} }
template<class Scalar>
std::tuple<double, double, double, double, double, double> std::tuple<Scalar, Scalar, Scalar, Scalar, Scalar, Scalar>
GasLiftGroupInfo:: GasLiftGroupInfo<Scalar>::
getProducerWellRates_(const Well* well, int well_index) getProducerWellRates_(const Well* well, int well_index)
{ {
const auto& pu = this->phase_usage_; const auto& pu = this->phase_usage_;
@ -509,21 +531,21 @@ getProducerWellRates_(const Well* well, int well_index)
: 0.0; : 0.0;
const auto controls = well->productionControls(this->summary_state_); const auto controls = well->productionControls(this->summary_state_);
double oil_rate = oil_pot; Scalar oil_rate = oil_pot;
if (controls.hasControl(Well::ProducerCMode::ORAT)) { if (controls.hasControl(Well::ProducerCMode::ORAT)) {
oil_rate = std::min(controls.oil_rate, oil_rate); oil_rate = std::min(static_cast<Scalar>(controls.oil_rate), oil_rate);
} }
double gas_rate = gas_pot; Scalar gas_rate = gas_pot;
if (controls.hasControl(Well::ProducerCMode::GRAT)) { if (controls.hasControl(Well::ProducerCMode::GRAT)) {
gas_rate = std::min(controls.gas_rate, gas_rate); gas_rate = std::min(static_cast<Scalar>(controls.gas_rate), gas_rate);
} }
double water_rate = water_pot; Scalar water_rate = water_pot;
if (controls.hasControl(Well::ProducerCMode::WRAT)) { if (controls.hasControl(Well::ProducerCMode::WRAT)) {
water_rate = std::min(controls.water_rate, water_rate); water_rate = std::min(static_cast<Scalar>(controls.water_rate), water_rate);
} }
if (controls.hasControl(Well::ProducerCMode::LRAT)) { if (controls.hasControl(Well::ProducerCMode::LRAT)) {
double liquid_rate = oil_rate + water_rate; Scalar liquid_rate = oil_rate + water_rate;
double liquid_rate_lim = std::min(controls.liquid_rate, liquid_rate); Scalar liquid_rate_lim = std::min(static_cast<Scalar>(controls.liquid_rate), liquid_rate);
water_rate = water_rate / liquid_rate * liquid_rate_lim; water_rate = water_rate / liquid_rate * liquid_rate_lim;
oil_rate = oil_rate / liquid_rate * liquid_rate_lim; oil_rate = oil_rate / liquid_rate * liquid_rate_lim;
} }
@ -531,11 +553,12 @@ getProducerWellRates_(const Well* well, int well_index)
return {oil_rate, gas_rate, water_rate, oil_pot, gas_pot, water_pot}; return {oil_rate, gas_rate, water_rate, oil_pot, gas_pot, water_pot};
} }
std::tuple<double, double, double, double, double, double, double> template<class Scalar>
GasLiftGroupInfo:: std::tuple<Scalar, Scalar, Scalar, Scalar, Scalar, Scalar, Scalar>
GasLiftGroupInfo<Scalar>::
initializeGroupRatesRecursive_(const Group& group) initializeGroupRatesRecursive_(const Group& group)
{ {
std::array<double,7> rates{}; std::array<Scalar,7> rates{};
if (this->debug) debugStartInitializeGroup(group.name()); if (this->debug) debugStartInitializeGroup(group.name());
auto& [oil_rate, water_rate, gas_rate, oil_potential, water_potential, gas_potential, alq] = rates; auto& [oil_rate, water_rate, gas_rate, oil_potential, water_potential, gas_potential, alq] = rates;
if (group.wellgroup()) { if (group.wellgroup()) {
@ -554,7 +577,7 @@ initializeGroupRatesRecursive_(const Group &group)
if (well->isProducer()) { if (well->isProducer()) {
auto [sw_oil_rate, sw_gas_rate, sw_water_rate, sw_oil_pot, sw_gas_pot, sw_water_pot] = getProducerWellRates_(well, 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); auto sw_alq = this->well_state_.getALQ(well_name);
double factor = well->getEfficiencyFactor(); Scalar factor = well->getEfficiencyFactor();
oil_rate += (factor * sw_oil_rate); oil_rate += (factor * sw_oil_rate);
gas_rate += (factor * sw_gas_rate); gas_rate += (factor * sw_gas_rate);
water_rate += (factor * sw_water_rate); water_rate += (factor * sw_water_rate);
@ -595,7 +618,7 @@ initializeGroupRatesRecursive_(const Group &group)
} }
} }
if (this->debug) debugEndInitializeGroup(group.name()); if (this->debug) debugEndInitializeGroup(group.name());
std::optional<double> oil_target, gas_target, water_target, liquid_target, max_total_gas, max_alq; std::optional<Scalar> oil_target, gas_target, water_target, liquid_target, max_total_gas, max_alq;
const auto controls = group.productionControls(this->summary_state_); const auto controls = group.productionControls(this->summary_state_);
if (group.has_control(Group::ProductionCMode::LRAT)) { if (group.has_control(Group::ProductionCMode::LRAT)) {
liquid_target = controls.liquid_target; liquid_target = controls.liquid_target;
@ -623,8 +646,8 @@ initializeGroupRatesRecursive_(const Group &group)
if (water_target) if (water_target)
water_rate = std::min(water_rate, *water_target); water_rate = std::min(water_rate, *water_target);
if (liquid_target) { if (liquid_target) {
double liquid_rate = oil_rate + water_rate; Scalar liquid_rate = oil_rate + water_rate;
double liquid_rate_limited = std::min(liquid_rate, *liquid_target); Scalar liquid_rate_limited = std::min(liquid_rate, *liquid_target);
oil_rate = oil_rate / liquid_rate * liquid_rate_limited; oil_rate = oil_rate / liquid_rate * liquid_rate_limited;
water_rate = water_rate / liquid_rate * liquid_rate_limited; water_rate = water_rate / liquid_rate * liquid_rate_limited;
} }
@ -641,15 +664,14 @@ initializeGroupRatesRecursive_(const Group &group)
return std::make_tuple(oil_rate, gas_rate, water_rate, oil_potential, gas_potential, water_potential, alq); return std::make_tuple(oil_rate, gas_rate, water_rate, oil_potential, gas_potential, water_potential, alq);
} }
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
initializeWell2GroupMapRecursive_( initializeWell2GroupMapRecursive_(const Group& group,
const Group &group,
std::vector<std::string>& group_names, std::vector<std::string>& group_names,
std::vector<double> &group_efficiency, std::vector<Scalar>& group_efficiency,
double cur_efficiency) Scalar cur_efficiency)
{ {
double gfac = group.getGroupEfficiencyFactor(); Scalar gfac = group.getGroupEfficiencyFactor();
cur_efficiency = gfac * cur_efficiency; cur_efficiency = gfac * cur_efficiency;
for (auto &item : group_efficiency) { for (auto &item : group_efficiency) {
item *= gfac; item *= gfac;
@ -668,7 +690,7 @@ initializeWell2GroupMapRecursive_(
if (checkDoGasLiftOptimization_(well_name)) { if (checkDoGasLiftOptimization_(well_name)) {
const auto &well = this->schedule_.getWell( const auto &well = this->schedule_.getWell(
well_name, this->report_step_idx_); well_name, this->report_step_idx_);
double wfac = well.getEfficiencyFactor(); Scalar wfac = well.getEfficiencyFactor();
auto [itr, success] = this->well_group_map_.insert( auto [itr, success] = this->well_group_map_.insert(
{well_name, /*empty vector*/ {}}); {well_name, /*empty vector*/ {}});
assert(success); assert(success);
@ -678,7 +700,7 @@ initializeWell2GroupMapRecursive_(
for (auto iter1 = group_names.begin(); for (auto iter1 = group_names.begin();
iter1 != group_names.end(); ++iter1) iter1 != group_names.end(); ++iter1)
{ {
double efficiency = (*iter2) * wfac; Scalar efficiency = (*iter2) * wfac;
vec.emplace_back(/*group_name=*/*iter1, efficiency); vec.emplace_back(/*group_name=*/*iter1, efficiency);
++iter2; ++iter2;
} }
@ -701,14 +723,12 @@ initializeWell2GroupMapRecursive_(
} }
} }
// TODO: It would be more efficient if the group idx map was build once // TODO: It would be more efficient if the group idx map was build once
// per time step (or better: once per report step) and saved e.g. in // per time step (or better: once per report step) and saved e.g. in
// the well state object, instead of rebuilding here for each of // the well state object, instead of rebuilding here for each of
// NUPCOL well iteration for each time step. // NUPCOL well iteration for each time step.
void template<class Scalar>
GasLiftGroupInfo:: void GasLiftGroupInfo<Scalar>::
updateGroupIdxMap_(const std::string& group_name) updateGroupIdxMap_(const std::string& group_name)
{ {
if (this->group_idx_.count(group_name) == 0) { if (this->group_idx_.count(group_name) == 0) {
@ -718,4 +738,6 @@ updateGroupIdxMap_(const std::string &group_name)
} }
} }
template class GasLiftGroupInfo<double>;
} // namespace Opm } // namespace Opm

View File

@ -29,8 +29,7 @@
#include <tuple> #include <tuple>
#include <vector> #include <vector>
namespace Opm namespace Opm {
{
class DeferredLogger; class DeferredLogger;
class GasLiftOpt; class GasLiftOpt;
@ -41,7 +40,8 @@ class SummaryState;
class Well; class Well;
template<class Scalar> class WellState; template<class Scalar> class WellState;
class GasLiftGroupInfo : public GasLiftCommon template<class Scalar>
class GasLiftGroupInfo : public GasLiftCommon<Scalar>
{ {
protected: protected:
class GroupRates; class GroupRates;
@ -51,7 +51,7 @@ protected:
// factors of the child groups of the group all the way down // factors of the child groups of the group all the way down
// to the well group. // to the well group.
using Well2GroupMap = using Well2GroupMap =
std::map<std::string, std::vector<std::pair<std::string,double>>>; std::map<std::string, std::vector<std::pair<std::string,Scalar>>>;
using GroupRateMap = using GroupRateMap =
std::map<std::string, GroupRates>; std::map<std::string, GroupRates>;
using GroupIdxMap = std::map<std::string, int>; using GroupIdxMap = std::map<std::string, int>;
@ -62,128 +62,155 @@ protected:
static const int Water = BlackoilPhases::Aqua; static const int Water = BlackoilPhases::Aqua;
static const int Oil = BlackoilPhases::Liquid; static const int Oil = BlackoilPhases::Liquid;
static const int Gas = BlackoilPhases::Vapour; static const int Gas = BlackoilPhases::Vapour;
public: public:
enum class Rate {oil, gas, water, liquid}; enum class Rate {oil, gas, water, liquid};
using GLiftEclWells = std::map<std::string,std::pair<const Well *,int>>; using GLiftEclWells = std::map<std::string,std::pair<const Well *,int>>;
GasLiftGroupInfo( GasLiftGroupInfo(GLiftEclWells& ecl_wells,
GLiftEclWells& ecl_wells,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summary_state, const SummaryState& summary_state,
const int report_step_idx, const int report_step_idx,
const int iteration_idx, const int iteration_idx,
const PhaseUsage& phase_usage, const PhaseUsage& phase_usage,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
WellState<double>& well_state, WellState<Scalar>& well_state,
const GroupState<double>& group_state, const GroupState<Scalar>& group_state,
const Parallel::Communication& comm, const Parallel::Communication& comm,
bool glift_debug bool glift_debug);
);
std::vector<std::pair<std::string,double>>& getWellGroups(
const std::string& well_name);
double alqRate(const std::string& group_name); std::vector<std::pair<std::string,Scalar>>&
double gasRate(const std::string& group_name) const; getWellGroups(const std::string& well_name);
double gasPotential(const std::string& group_name) const;
double waterPotential(const std::string& group_name) const; Scalar alqRate(const std::string& group_name);
double oilPotential(const std::string& group_name) const; Scalar gasRate(const std::string& group_name) const;
Scalar gasPotential(const std::string& group_name) const;
Scalar waterPotential(const std::string& group_name) const;
Scalar oilPotential(const std::string& group_name) const;
int getGroupIdx(const std::string& group_name); int getGroupIdx(const std::string& group_name);
double getRate(Rate rate_type, const std::string& group_name) const; Scalar getRate(Rate rate_type, const std::string& group_name) const;
double getPotential(Rate rate_type, const std::string& group_name) const; Scalar getPotential(Rate rate_type, const std::string& group_name) const;
std::tuple<double,double,double,double> getRates(const int group_idx) const; std::tuple<Scalar,Scalar,Scalar,Scalar> getRates(const int group_idx) const;
std::optional<double> gasTarget(const std::string& group_name) const; std::optional<Scalar> gasTarget(const std::string& group_name) const;
std::optional<double> getTarget( std::optional<Scalar> getTarget(Rate rate_type, const std::string& group_name) const;
Rate rate_type, const std::string& group_name) const;
const std::string& groupIdxToName(int group_idx) const; const std::string& groupIdxToName(int group_idx) const;
bool hasAnyTarget(const std::string& group_name) const; bool hasAnyTarget(const std::string& group_name) const;
bool hasWell(const std::string& well_name); bool hasWell(const std::string& well_name);
void initialize(); void initialize();
std::optional<double> liquidTarget(const std::string& group_name) const; std::optional<Scalar> liquidTarget(const std::string& group_name) const;
std::optional<double> maxAlq(const std::string& group_name); std::optional<Scalar> maxAlq(const std::string& group_name);
std::optional<double> maxTotalGasRate(const std::string& group_name); std::optional<Scalar> maxTotalGasRate(const std::string& group_name);
double oilRate(const std::string& group_name) const; Scalar oilRate(const std::string& group_name) const;
std::optional<double> oilTarget(const std::string& group_name) const; std::optional<Scalar> oilTarget(const std::string& group_name) const;
static const std::string rateToString(Rate rate); static const std::string rateToString(Rate rate);
double waterRate(const std::string& group_name) const; Scalar waterRate(const std::string& group_name) const;
std::optional<double> waterTarget(const std::string& group_name) const; std::optional<Scalar> waterTarget(const std::string& group_name) const;
void update(const std::string& well_name, void update(const std::string& well_name,
double delta_oil, double delta_gas, double delta_water, double delta_alq); Scalar delta_oil,
void updateRate(int idx, double oil_rate, double gas_rate, double water_rate, double alq); Scalar delta_gas,
Scalar delta_water,
Scalar delta_alq);
void updateRate(int idx,
Scalar oil_rate,
Scalar gas_rate,
Scalar water_rate,
Scalar alq);
const Well2GroupMap& wellGroupMap() { return well_group_map_; } const Well2GroupMap& wellGroupMap() { return well_group_map_; }
protected: protected:
bool checkDoGasLiftOptimization_(const std::string& well_name); bool checkDoGasLiftOptimization_(const std::string& well_name);
bool checkNewtonIterationIdxOk_(const std::string& well_name); bool checkNewtonIterationIdxOk_(const std::string& well_name);
void debugDisplayWellContribution_( void debugDisplayWellContribution_(const std::string& gr_name,
const std::string& gr_name, const std::string& well_name, const std::string& well_name,
double eff_factor, Scalar eff_factor,
double well_oil_rate, double well_gas_rate, double well_water_rate, Scalar well_oil_rate,
double well_alq, Scalar well_gas_rate,
double oil_rate, double gas_rate, double water_rate, Scalar well_water_rate,
double alq Scalar well_alq,
) const; Scalar oil_rate,
Scalar gas_rate,
Scalar water_rate,
Scalar alq) const;
void debugDisplayUpdatedGroupRates(const std::string& name, void debugDisplayUpdatedGroupRates(const std::string& name,
double oil_rate, double gas_rate, double water_rate, double alq) const; Scalar oil_rate,
Scalar gas_rate,
Scalar water_rate,
Scalar alq) const;
void debugEndInitializeGroup(const std::string& name) const; void debugEndInitializeGroup(const std::string& name) const;
void debugStartInitializeGroup(const std::string& name) const; void debugStartInitializeGroup(const std::string& name) const;
void displayDebugMessage_(const std::string& msg) const override; void displayDebugMessage_(const std::string& msg) const override;
void displayDebugMessage_(const std::string& msg, const std::string& well_name); void displayDebugMessage_(const std::string& msg, const std::string& well_name);
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,
std::vector<double>& group_efficiency, double cur_efficiency);
void updateGroupIdxMap_(const std::string& group_name);
std::tuple<Scalar, Scalar, Scalar, Scalar, Scalar, Scalar>
getProducerWellRates_(const Well* well, const int index);
std::tuple<Scalar, Scalar, Scalar, Scalar, Scalar, Scalar, Scalar>
initializeGroupRatesRecursive_(const Group &group);
void initializeWell2GroupMapRecursive_(const Group& group,
std::vector<std::string>& group_names,
std::vector<Scalar>& group_efficiency,
Scalar cur_efficiency);
void updateGroupIdxMap_(const std::string& group_name);
class GroupRates { class GroupRates {
public: public:
GroupRates( double oil_rate, double gas_rate, double water_rate, double alq, GroupRates(Scalar oil_rate,
double oil_potential, double gas_potential, double water_potential, Scalar gas_rate,
std::optional<double> oil_target, Scalar water_rate,
std::optional<double> gas_target, Scalar alq,
std::optional<double> water_target, Scalar oil_potential,
std::optional<double> liquid_target, Scalar gas_potential,
std::optional<double> total_gas, Scalar water_potential,
std::optional<double> max_alq std::optional<Scalar> oil_target,
) : std::optional<Scalar> gas_target,
oil_rate_{oil_rate}, std::optional<Scalar> water_target,
gas_rate_{gas_rate}, std::optional<Scalar> liquid_target,
water_rate_{water_rate}, std::optional<Scalar> total_gas,
alq_{alq}, std::optional<Scalar> max_alq)
oil_potential_{oil_potential}, : oil_rate_{oil_rate}
gas_potential_{gas_potential}, , gas_rate_{gas_rate}
water_potential_{water_potential}, , water_rate_{water_rate}
oil_target_{oil_target}, , alq_{alq}
gas_target_{gas_target}, , oil_potential_{oil_potential}
water_target_{water_target}, , gas_potential_{gas_potential}
liquid_target_{liquid_target}, , water_potential_{water_potential}
total_gas_{total_gas}, , oil_target_{oil_target}
max_alq_{max_alq} , gas_target_{gas_target}
, water_target_{water_target}
, liquid_target_{liquid_target}
, total_gas_{total_gas}
, max_alq_{max_alq}
{} {}
double alq() const { return alq_; }
void assign(double oil_rate, double gas_rate, double water_rate, double alq) Scalar alq() const { return alq_; }
void assign(Scalar oil_rate,
Scalar gas_rate,
Scalar water_rate,
Scalar alq)
{ {
oil_rate_ = oil_rate; oil_rate_ = oil_rate;
gas_rate_ = gas_rate; gas_rate_ = gas_rate;
water_rate_ = water_rate; water_rate_ = water_rate;
alq_ = alq; alq_ = alq;
} }
double gasRate() const { return gas_rate_; } Scalar gasRate() const { return gas_rate_; }
double waterRate() const { return water_rate_; } Scalar waterRate() const { return water_rate_; }
std::optional<double> gasTarget() const { return gas_target_; } std::optional<Scalar> gasTarget() const { return gas_target_; }
std::optional<double> waterTarget() const { return water_target_; } std::optional<Scalar> waterTarget() const { return water_target_; }
std::optional<double> maxAlq() const { return max_alq_; } std::optional<Scalar> maxAlq() const { return max_alq_; }
std::optional<double> maxTotalGasRate() const { return total_gas_; } std::optional<Scalar > maxTotalGasRate() const { return total_gas_; }
double oilRate() const { return oil_rate_; } Scalar oilRate() const { return oil_rate_; }
std::optional<double> oilTarget() const { return oil_target_; } std::optional<Scalar> oilTarget() const { return oil_target_; }
std::optional<double> liquidTarget() const { return liquid_target_; } std::optional<Scalar> liquidTarget() const { return liquid_target_; }
double oilPotential() const { return oil_potential_; } Scalar oilPotential() const { return oil_potential_; }
double gasPotential() const { return gas_potential_; } Scalar gasPotential() const { return gas_potential_; }
double waterPotential() const { return water_potential_; } Scalar waterPotential() const { return water_potential_; }
void update(double delta_oil, double delta_gas, double delta_water, double delta_alq) void update(Scalar delta_oil,
Scalar delta_gas,
Scalar delta_water,
Scalar delta_alq)
{ {
oil_rate_ += delta_oil; oil_rate_ += delta_oil;
gas_rate_ += delta_gas; gas_rate_ += delta_gas;
@ -192,20 +219,21 @@ protected:
// Note. We don't updata the potentials at this point. They // Note. We don't updata the potentials at this point. They
// are only needed initially. // are only needed initially.
} }
private: private:
double oil_rate_; Scalar oil_rate_;
double gas_rate_; Scalar gas_rate_;
double water_rate_; Scalar water_rate_;
double alq_; Scalar alq_;
double oil_potential_; Scalar oil_potential_;
double gas_potential_; Scalar gas_potential_;
double water_potential_; Scalar water_potential_;
std::optional<double> oil_target_; std::optional<Scalar> oil_target_;
std::optional<double> gas_target_; std::optional<Scalar> gas_target_;
std::optional<double> water_target_; std::optional<Scalar> water_target_;
std::optional<double> liquid_target_; std::optional<Scalar> liquid_target_;
std::optional<double> total_gas_; std::optional<Scalar> total_gas_;
std::optional<double> max_alq_; std::optional<Scalar> max_alq_;
}; };
GLiftEclWells& ecl_wells_; GLiftEclWells& ecl_wells_;
@ -221,7 +249,6 @@ protected:
int next_group_idx_ = 0; int next_group_idx_ = 0;
// Optimize only wells under THP control // Optimize only wells under THP control
bool optimize_only_thp_wells_ = false; bool optimize_only_thp_wells_ = false;
}; };
} // namespace Opm } // namespace Opm

View File

@ -28,42 +28,44 @@
#include <opm/simulators/wells/WellInterface.hpp> #include <opm/simulators/wells/WellInterface.hpp>
#include <optional> #include <optional>
#include <vector>
#include <utility>
namespace Opm namespace Opm {
{
template<class TypeTag> template<class TypeTag>
class GasLiftSingleWell : public GasLiftSingleWellGeneric class GasLiftSingleWell : public GasLiftSingleWellGeneric<GetPropType<TypeTag, Properties::Scalar>>
{ {
using Scalar = GetPropType<TypeTag, Properties::Scalar>; using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using Simulator = GetPropType<TypeTag, Properties::Simulator>; using Simulator = GetPropType<TypeTag, Properties::Simulator>;
using GLiftSyncGroups = typename GasLiftSingleWellGeneric::GLiftSyncGroups; using GLiftSyncGroups = typename GasLiftSingleWellGeneric<Scalar>::GLiftSyncGroups;
using BasicRates = typename GasLiftSingleWellGeneric<Scalar>::BasicRates;
public: public:
GasLiftSingleWell( GasLiftSingleWell(const WellInterface<TypeTag>& well,
const WellInterface<TypeTag> &well,
const Simulator& simulator, const Simulator& simulator,
const SummaryState& summary_state, const SummaryState& summary_state,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
WellState<Scalar>& well_state, WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state, const GroupState<Scalar>& group_state,
GasLiftGroupInfo &group_info, GasLiftGroupInfo<Scalar>& group_info,
GLiftSyncGroups& sync_groups, GLiftSyncGroups& sync_groups,
const Parallel::Communication& comm, const Parallel::Communication& comm,
bool glift_debug bool glift_debug);
);
const WellInterfaceGeneric& getWell() const override { return well_; } const WellInterfaceGeneric& getWell() const override { return well_; }
private: private:
std::optional<double> computeBhpAtThpLimit_(double alq, bool debug_ouput=true) const override; std::optional<Scalar>
BasicRates computeWellRates_( computeBhpAtThpLimit_(Scalar alq,
double bhp, bool bhp_is_limited, bool debug_output=true) const override; bool debug_ouput = true) const override;
BasicRates computeWellRates_(Scalar bhp,
bool bhp_is_limited,
bool debug_output = true) const override;
void setAlqMaxRate_(const GasLiftWell& well); void setAlqMaxRate_(const GasLiftWell& well);
void setupPhaseVariables_(); void setupPhaseVariables_();
bool checkThpControl_() const override; bool checkThpControl_() const override;
const Simulator& simulator_; const Simulator& simulator_;
const WellInterface<TypeTag>& well_; const WellInterface<TypeTag>& well_;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -33,55 +33,63 @@
#include <tuple> #include <tuple>
#include <utility> #include <utility>
namespace Opm namespace Opm {
{
class DeferredLogger; class DeferredLogger;
class GasLiftWell; class GasLiftWell;
class GasLiftWellState; template<class Scalar> class GasLiftWellState;
class Schedule; class Schedule;
class SummaryState; class SummaryState;
class WellInterfaceGeneric; class WellInterfaceGeneric;
template<class Scalar> class WellState; template<class Scalar> class WellState;
template<class Scalar> class GroupState; template<class Scalar> class GroupState;
class GasLiftSingleWellGeneric : public GasLiftCommon template<class Scalar>
class GasLiftSingleWellGeneric : public GasLiftCommon<Scalar>
{ {
protected: protected:
static constexpr int Water = BlackoilPhases::Aqua; static constexpr int Water = BlackoilPhases::Aqua;
static constexpr int Oil = BlackoilPhases::Liquid; static constexpr int Oil = BlackoilPhases::Liquid;
static constexpr int Gas = BlackoilPhases::Vapour; static constexpr int Gas = BlackoilPhases::Vapour;
static constexpr int NUM_PHASES = 3; static constexpr int NUM_PHASES = 3;
static constexpr double ALQ_EPSILON = 1e-8; static constexpr Scalar ALQ_EPSILON = 1e-8;
public: public:
using GLiftSyncGroups = std::set<int>; using GLiftSyncGroups = std::set<int>;
using Rate = GasLiftGroupInfo::Rate; using Rate = typename GasLiftGroupInfo<Scalar>::Rate;
using MessageType = typename GasLiftCommon<Scalar>::MessageType;
struct GradInfo struct GradInfo
{ {
GradInfo() { } GradInfo() = default;
GradInfo(Scalar grad_,
Scalar new_oil_rate_,
bool oil_is_limited_,
Scalar new_gas_rate_,
bool gas_is_limited_,
Scalar new_water_rate_,
bool water_is_limited_,
Scalar alq_,
bool alq_is_limited_)
: grad{grad_}
, new_oil_rate{new_oil_rate_}
, oil_is_limited{oil_is_limited_}
, new_gas_rate{new_gas_rate_}
, gas_is_limited{gas_is_limited_}
, new_water_rate{new_water_rate_}
, water_is_limited{water_is_limited_}
, alq{alq_}
, alq_is_limited{alq_is_limited_}
{}
GradInfo(double grad_, double new_oil_rate_, bool oil_is_limited_, Scalar grad;
double new_gas_rate_, bool gas_is_limited_, Scalar new_oil_rate;
double new_water_rate_, bool water_is_limited_,
double alq_, bool alq_is_limited_) :
grad{grad_},
new_oil_rate{new_oil_rate_},
oil_is_limited{oil_is_limited_},
new_gas_rate{new_gas_rate_},
gas_is_limited{gas_is_limited_},
new_water_rate{new_water_rate_},
water_is_limited{water_is_limited_},
alq{alq_},
alq_is_limited{alq_is_limited_} {}
double grad;
double new_oil_rate;
bool oil_is_limited; bool oil_is_limited;
double new_gas_rate; Scalar new_gas_rate;
bool gas_is_limited; bool gas_is_limited;
double new_water_rate; Scalar new_water_rate;
bool water_is_limited; bool water_is_limited;
double alq; Scalar alq;
bool alq_is_limited; bool alq_is_limited;
}; };
@ -89,33 +97,31 @@ public:
const std::string& name() const { return well_name_; } const std::string& name() const { return well_name_; }
std::optional<GradInfo> calcIncOrDecGradient(double oil_rate, double gas_rate, std::optional<GradInfo> calcIncOrDecGradient(Scalar oil_rate,
double water_rate, Scalar gas_rate,
double alq, Scalar water_rate,
Scalar alq,
const std::string& gr_name_dont_limit, const std::string& gr_name_dont_limit,
bool increase, bool increase,
bool debug_output = true bool debug_output = true) const;
) const;
std::unique_ptr<GasLiftWellState> runOptimize(const int iteration_idx); std::unique_ptr<GasLiftWellState<Scalar>> runOptimize(const int iteration_idx);
virtual const WellInterfaceGeneric& getWell() const = 0; virtual const WellInterfaceGeneric& getWell() const = 0;
protected: protected:
GasLiftSingleWellGeneric( GasLiftSingleWellGeneric(DeferredLogger& deferred_logger,
DeferredLogger& deferred_logger, WellState<Scalar>& well_state,
WellState<double>& well_state, const GroupState<Scalar>& group_state,
const GroupState<double>& group_state,
const Well& ecl_well, const Well& ecl_well,
const SummaryState& summary_state, const SummaryState& summary_state,
GasLiftGroupInfo& group_info, GasLiftGroupInfo<Scalar>& group_info,
const PhaseUsage& phase_usage, const PhaseUsage& phase_usage,
const Schedule& schedule, const Schedule& schedule,
const int report_step_idx, const int report_step_idx,
GLiftSyncGroups& sync_groups, GLiftSyncGroups& sync_groups,
const Parallel::Communication& comm, const Parallel::Communication& comm,
bool glift_debug bool glift_debug);
);
struct LimitedRates; struct LimitedRates;
struct BasicRates struct BasicRates
@ -126,24 +132,33 @@ protected:
water{rates.water}, water{rates.water},
bhp_is_limited{rates.bhp_is_limited} bhp_is_limited{rates.bhp_is_limited}
{} {}
BasicRates(double oil_, double gas_, double water_, bool bhp_is_limited_) :
oil{oil_}, BasicRates(Scalar oil_,
gas{gas_}, Scalar gas_,
water{water_}, Scalar water_,
bhp_is_limited{bhp_is_limited_} bool bhp_is_limited_)
: oil{oil_}
, gas{gas_}
, water{water_}
, bhp_is_limited{bhp_is_limited_}
{} {}
BasicRates& operator=(const BasicRates& rates) {
BasicRates& operator=(const BasicRates& rates)
{
oil = rates.oil; oil = rates.oil;
gas = rates.gas; gas = rates.gas;
water = rates.water; water = rates.water;
bhp_is_limited = rates.bhp_is_limited; bhp_is_limited = rates.bhp_is_limited;
return *this; return *this;
} }
// This copy constructor cannot be defined inline here since LimitedRates // This copy constructor cannot be defined inline here since LimitedRates
// has not been defined yet (it is defined below). Instead it is defined in // has not been defined yet (it is defined below). Instead it is defined in
// in the .cpp file // in the .cpp file
BasicRates(const LimitedRates& rates); BasicRates(const LimitedRates& rates);
double operator[](Rate rate_type) const {
Scalar operator[](Rate rate_type) const
{
switch (rate_type) { switch (rate_type) {
case Rate::oil: case Rate::oil:
return this->oil; return this->oil;
@ -158,46 +173,49 @@ protected:
} }
} }
double oil, gas, water; Scalar oil, gas, water;
bool bhp_is_limited; bool bhp_is_limited;
}; };
struct LimitedRates : public BasicRates struct LimitedRates : public BasicRates
{ {
enum class LimitType {well, group, none}; enum class LimitType {well, group, none};
LimitedRates( LimitedRates(Scalar oil_,
double oil_, double gas_, double water_, Scalar gas_,
bool oil_is_limited_, bool gas_is_limited_, Scalar water_,
bool water_is_limited_, bool bhp_is_limited_, bool oil_is_limited_,
bool gas_is_limited_,
bool water_is_limited_,
bool bhp_is_limited_,
std::optional<Rate> oil_limiting_target_, std::optional<Rate> oil_limiting_target_,
std::optional<Rate> water_limiting_target_ std ::optional<Rate> water_limiting_target_)
) : : BasicRates(oil_, gas_, water_, bhp_is_limited_)
BasicRates(oil_, gas_, water_, bhp_is_limited_), , oil_is_limited{oil_is_limited_}
oil_is_limited{oil_is_limited_}, , gas_is_limited{gas_is_limited_}
gas_is_limited{gas_is_limited_}, , water_is_limited{water_is_limited_}
water_is_limited{water_is_limited_}, , oil_limiting_target{oil_limiting_target_}
oil_limiting_target{oil_limiting_target_}, , water_limiting_target{water_limiting_target_}
water_limiting_target{water_limiting_target_}
{ {
set_initial_limit_type_(); set_initial_limit_type_();
} }
LimitedRates( LimitedRates(const BasicRates& rates,
const BasicRates& rates, bool oil_is_limited_,
bool oil_is_limited_, bool gas_is_limited_, bool gas_is_limited_,
bool water_is_limited_ bool water_is_limited_)
) : : BasicRates(rates)
BasicRates(rates), , oil_is_limited{oil_is_limited_}
oil_is_limited{oil_is_limited_}, , gas_is_limited{gas_is_limited_}
gas_is_limited{gas_is_limited_}, , water_is_limited{water_is_limited_}
water_is_limited{water_is_limited_}
{ {
set_initial_limit_type_(); set_initial_limit_type_();
} }
bool limited() const { bool limited() const
{
return oil_is_limited || gas_is_limited || water_is_limited; return oil_is_limited || gas_is_limited || water_is_limited;
} }
// For a given ALQ value, were the rates limited due to group targets // For a given ALQ value, were the rates limited due to group targets
// or due to well targets? // or due to well targets?
LimitType limit_type; LimitType limit_type;
@ -206,145 +224,221 @@ protected:
bool water_is_limited; bool water_is_limited;
std::optional<Rate> oil_limiting_target; std::optional<Rate> oil_limiting_target;
std::optional<Rate> water_limiting_target; std::optional<Rate> water_limiting_target;
private: private:
void set_initial_limit_type_() { void set_initial_limit_type_()
{
limit_type = limited() ? LimitType::well : LimitType::none; limit_type = limited() ? LimitType::well : LimitType::none;
} }
}; };
struct OptimizeState struct OptimizeState
{ {
OptimizeState( GasLiftSingleWellGeneric& parent_, bool increase_ ) : OptimizeState( GasLiftSingleWellGeneric& parent_, bool increase_ )
parent{parent_}, : parent{parent_}
increase{increase_}, , increase{increase_}
it{0}, , it{0}
stop_iteration{false}, , stop_iteration{false}
bhp{-1} , bhp{-1}
{} {}
GasLiftSingleWellGeneric& parent; GasLiftSingleWellGeneric& parent;
bool increase; bool increase;
int it; int it;
bool stop_iteration; bool stop_iteration;
double bhp; Scalar bhp;
std::pair<std::optional<double>,bool> addOrSubtractAlqIncrement(double alq); std::pair<std::optional<Scalar>,bool> addOrSubtractAlqIncrement(Scalar alq);
double calcEcoGradient(double oil_rate, double new_oil_rate, Scalar calcEcoGradient(Scalar oil_rate,
double gas_rate, double new_gas_rate); Scalar new_oil_rate,
bool checkAlqOutsideLimits(double alq, double oil_rate); Scalar gas_rate,
bool checkEcoGradient(double gradient); Scalar new_gas_rate);
bool checkOilRateExceedsTarget(double oil_rate);
bool checkAlqOutsideLimits(Scalar alq, Scalar oil_rate);
bool checkEcoGradient(Scalar gradient);
bool checkOilRateExceedsTarget(Scalar oil_rate);
bool checkRatesViolated(const LimitedRates& rates) const; bool checkRatesViolated(const LimitedRates& rates) const;
void debugShowIterationInfo(double alq);
double getBhpWithLimit();
void warn_(std::string msg) {parent.displayWarning_(msg);}
};
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_( void debugShowIterationInfo(Scalar alq);
double alq, bool increase) const;
double calcEcoGradient_(double oil_rate, double new_oil_rate, Scalar getBhpWithLimit();
double gas_rate, double new_gas_rate, bool increase) const;
bool checkALQequal_(double alq1, double alq2) const; void warn_(const std::string& msg) { parent.displayWarning_(msg); }
bool checkGroupTargetsViolated( };
const BasicRates& rates, const BasicRates& new_rates) const;
bool checkInitialALQmodified_(double alq, double initial_alq) const; bool checkGroupALQrateExceeded(Scalar delta_alq,
const std::string& gr_name_dont_limit = "") const;
bool checkGroupTotalRateExceeded(Scalar delta_alq,
Scalar delta_gas_rate) const;
std::pair<std::optional<Scalar>, bool>
addOrSubtractAlqIncrement_(Scalar alq, bool increase) const;
Scalar calcEcoGradient_(Scalar oil_rate, Scalar new_oil_rate,
Scalar gas_rate, Scalar new_gas_rate, bool increase) const;
bool checkALQequal_(Scalar alq1, Scalar alq2) const;
bool checkGroupTargetsViolated(const BasicRates& rates,
const BasicRates& new_rates) const;
bool checkInitialALQmodified_(Scalar alq, Scalar initial_alq) const;
virtual bool checkThpControl_() const = 0; virtual bool checkThpControl_() const = 0;
virtual std::optional<double> computeBhpAtThpLimit_(double alq, bool debug_output = true) const = 0; virtual std::optional<Scalar > computeBhpAtThpLimit_(Scalar alq,
std::pair<std::optional<double>,double> computeConvergedBhpAtThpLimitByMaybeIncreasingALQ_() const; bool debug_output = true) const = 0;
std::pair<std::optional<BasicRates>,double> computeInitialWellRates_() const;
std::optional<LimitedRates> computeLimitedWellRatesWithALQ_(double alq) const; std::pair<std::optional<Scalar>,Scalar>
virtual BasicRates computeWellRates_(double bhp, bool bhp_is_limited, bool debug_output = true) const = 0; computeConvergedBhpAtThpLimitByMaybeIncreasingALQ_() const;
std::optional<BasicRates> computeWellRatesWithALQ_(double alq) const;
void debugCheckNegativeGradient_(double grad, double alq, double new_alq, std::pair<std::optional<BasicRates>,Scalar>
double oil_rate, double new_oil_rate, computeInitialWellRates_() const;
double gas_rate, double new_gas_rate,
std::optional<LimitedRates>
computeLimitedWellRatesWithALQ_(Scalar alq) const;
virtual BasicRates computeWellRates_(Scalar bhp,
bool bhp_is_limited,
bool debug_output = true) const = 0;
std::optional<BasicRates> computeWellRatesWithALQ_(Scalar alq) const;
void debugCheckNegativeGradient_(Scalar grad, Scalar alq, Scalar new_alq,
Scalar oil_rate, Scalar new_oil_rate,
Scalar gas_rate, Scalar new_gas_rate,
bool increase) const; bool increase) const;
void debugPrintWellStateRates() const; void debugPrintWellStateRates() const;
void debugShowAlqIncreaseDecreaseCounts_(); void debugShowAlqIncreaseDecreaseCounts_();
void debugShowBhpAlqTable_(); void debugShowBhpAlqTable_();
void debugShowLimitingTargets_(const LimitedRates& rates) const; void debugShowLimitingTargets_(const LimitedRates& rates) const;
void debugShowProducerControlMode() const; void debugShowProducerControlMode() const;
void debugShowStartIteration_(double alq, bool increase, double oil_rate); void debugShowStartIteration_(Scalar alq, bool increase, Scalar oil_rate);
void debugShowTargets_(); void debugShowTargets_();
void displayDebugMessage_(const std::string& msg) const override; void displayDebugMessage_(const std::string& msg) const override;
void displayWarning_(const std::string& warning); void displayWarning_(const std::string& warning);
std::pair<double, bool> getBhpWithLimit_(double bhp) const;
std::pair<double, bool> getGasRateWithLimit_( std::pair<Scalar, bool> getBhpWithLimit_(Scalar bhp) const;
const BasicRates& rates) const; std::pair<Scalar, bool> getGasRateWithLimit_(const BasicRates& rates) const;
std::pair<double, bool> getGasRateWithGroupLimit_( std::pair<Scalar, bool> getGasRateWithGroupLimit_(Scalar new_gas_rate,
double new_gas_rate, double gas_rate, const std::string& gr_name_dont_limit) const; Scalar gas_rate,
std::pair<std::optional<LimitedRates>,double> getInitialRatesWithLimit_() const; const std::string& gr_name_dont_limit) const;
std::pair<std::optional<LimitedRates>,Scalar >
getInitialRatesWithLimit_() const;
LimitedRates getLimitedRatesFromRates_(const BasicRates& rates) const; LimitedRates getLimitedRatesFromRates_(const BasicRates& rates) const;
std::tuple<double,double,bool,bool> getLiquidRateWithGroupLimit_(
const double new_oil_rate, const double oil_rate, std::tuple<Scalar,Scalar,bool,bool>
const double new_water_rate, const double water_rate, const std::string& gr_name_dont_limit) const; getLiquidRateWithGroupLimit_(const Scalar new_oil_rate,
std::pair<double, bool> getOilRateWithGroupLimit_( const Scalar oil_rate,
double new_oil_rate, double oil_rate, const std::string& gr_name_dont_limit) const; const Scalar new_water_rate,
std::pair<double, bool> getOilRateWithLimit_(const BasicRates& rates) const; const Scalar water_rate,
std::pair<double, std::optional<Rate>> getOilRateWithLimit2_( const std::string& gr_name_dont_limit) const;
const BasicRates& rates) const;
double getProductionTarget_(Rate rate) const; std::pair<Scalar, bool>
double getRate_(Rate rate_type, const BasicRates& rates) const; getOilRateWithGroupLimit_(Scalar new_oil_rate,
std::pair<double, std::optional<Rate>> getRateWithLimit_( Scalar oil_rate,
Rate rate_type, const BasicRates& rates) const; const std::string& gr_name_dont_limit) const;
std::tuple<double, const std::string*, double> getRateWithGroupLimit_(
Rate rate_type, const double new_rate, const double old_rate, const std::string& gr_name_dont_limit) const; std::pair<Scalar, bool> getOilRateWithLimit_(const BasicRates& rates) const;
std::pair<double, bool> getWaterRateWithGroupLimit_(
double new_water_rate, double water_rate, const std::string& gr_name_dont_limit) const; std::pair<Scalar, std::optional<Rate>>
std::pair<double, bool> getWaterRateWithLimit_(const BasicRates& rates) const; getOilRateWithLimit2_(const BasicRates& rates) const;
std::pair<double, std::optional<Rate>> getWaterRateWithLimit2_(
const BasicRates& rates) const; Scalar getProductionTarget_(Rate rate) const;
Scalar getRate_(Rate rate_type, const BasicRates& rates) const;
std::pair<Scalar, std::optional<Rate>>
getRateWithLimit_(Rate rate_type, const BasicRates& rates) const;
std::tuple<Scalar, const std::string*, Scalar>
getRateWithGroupLimit_(Rate rate_type,
const Scalar new_rate,
const Scalar old_rate,
const std::string& gr_name_dont_limit) const;
std::pair<Scalar, bool>
getWaterRateWithGroupLimit_(Scalar new_water_rate,
Scalar water_rate,
const std::string& gr_name_dont_limit) const;
std::pair<Scalar, bool> getWaterRateWithLimit_(const BasicRates& rates) const;
std::pair<Scalar, std::optional<Rate>>
getWaterRateWithLimit2_(const BasicRates& rates) const;
BasicRates getWellStateRates_() const; BasicRates getWellStateRates_() const;
bool hasProductionControl_(Rate rate) const; bool hasProductionControl_(Rate rate) const;
std::pair<LimitedRates, double> increaseALQtoPositiveOilRate_(
double alq, const LimitedRates& orig_rates) const; std::pair<LimitedRates, Scalar>
std::pair<LimitedRates, double> increaseALQtoMinALQ_( increaseALQtoPositiveOilRate_(Scalar alq,
double alq, const LimitedRates& orig_rates) const; const LimitedRates& orig_rates) const;
void logSuccess_(double alq,
std::pair<LimitedRates, Scalar>
increaseALQtoMinALQ_(Scalar alq,
const LimitedRates& orig_rates) const;
void logSuccess_(Scalar alq,
const int iteration_idx); const int iteration_idx);
std::pair<LimitedRates, double> maybeAdjustALQbeforeOptimizeLoop_(
const LimitedRates& rates, double alq, bool increase) const; std::pair<LimitedRates, Scalar>
std::pair<LimitedRates, double> reduceALQtoGroupAlqLimits_( maybeAdjustALQbeforeOptimizeLoop_(const LimitedRates& rates,
double alq, const LimitedRates& rates) const; Scalar alq,
std::pair<LimitedRates, double> reduceALQtoGroupTarget( bool increase) const;
double alq, const LimitedRates& rates) const;
std::pair<LimitedRates, double> reduceALQtoWellTarget_( std::pair<LimitedRates, Scalar>
double alq, const LimitedRates& rates) const; reduceALQtoGroupAlqLimits_(Scalar alq,
std::unique_ptr<GasLiftWellState> runOptimize1_(); const LimitedRates& rates) const;
std::unique_ptr<GasLiftWellState> runOptimize2_();
std::unique_ptr<GasLiftWellState> runOptimizeLoop_(bool increase); std::pair<LimitedRates, Scalar>
reduceALQtoGroupTarget(Scalar alq,
const LimitedRates& rates) const;
std::pair<LimitedRates, Scalar>
reduceALQtoWellTarget_(Scalar alq,
const LimitedRates& rates) const;
std::unique_ptr<GasLiftWellState<Scalar>> runOptimize1_();
std::unique_ptr<GasLiftWellState<Scalar>> runOptimize2_();
std::unique_ptr<GasLiftWellState<Scalar>> runOptimizeLoop_(bool increase);
void setAlqMinRate_(const GasLiftWell& well); void setAlqMinRate_(const GasLiftWell& well);
std::unique_ptr<GasLiftWellState> tryIncreaseLiftGas_(); std::unique_ptr<GasLiftWellState<Scalar>> tryIncreaseLiftGas_();
std::unique_ptr<GasLiftWellState> tryDecreaseLiftGas_(); std::unique_ptr<GasLiftWellState<Scalar>> tryDecreaseLiftGas_();
void updateGroupRates_(
const LimitedRates& rates, void updateGroupRates_(const LimitedRates& rates,
const LimitedRates& new_rates, const LimitedRates& new_rates,
double delta_alq) const; Scalar delta_alq) const;
LimitedRates updateRatesToGroupLimits_(
const BasicRates& rates, const LimitedRates& new_rates, const std::string& gr_name = "") const; LimitedRates
updateRatesToGroupLimits_(const BasicRates& rates,
const LimitedRates& new_rates,
const std::string& gr_name = "") const;
void updateWellStateAlqFixedValue_(const GasLiftWell& well); void updateWellStateAlqFixedValue_(const GasLiftWell& well);
bool useFixedAlq_(const GasLiftWell& well); bool useFixedAlq_(const GasLiftWell& well);
void debugInfoGroupRatesExceedTarget(
Rate rate_type, const std::string& gr_name, double rate, double target) const; void debugInfoGroupRatesExceedTarget(Rate rate_type,
const std::string& gr_name,
Scalar rate,
Scalar target) const;
void warnMaxIterationsExceeded_(); void warnMaxIterationsExceeded_();
const Well& ecl_well_; const Well& ecl_well_;
const SummaryState& summary_state_; const SummaryState& summary_state_;
GasLiftGroupInfo& group_info_; GasLiftGroupInfo<Scalar>& group_info_;
const PhaseUsage& phase_usage_; const PhaseUsage& phase_usage_;
GLiftSyncGroups& sync_groups_; GLiftSyncGroups& sync_groups_;
const WellProductionControls controls_; const WellProductionControls controls_;
double increment_; Scalar increment_;
double max_alq_; Scalar max_alq_;
double min_alq_; Scalar min_alq_;
double orig_alq_; Scalar orig_alq_;
double alpha_w_; Scalar alpha_w_;
double alpha_g_; Scalar alpha_g_;
double eco_grad_; Scalar eco_grad_;
int gas_pos_; int gas_pos_;
int oil_pos_; int oil_pos_;

View File

@ -27,6 +27,9 @@
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp> #include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <string>
#include <vector>
namespace Opm { namespace Opm {
template<typename TypeTag> template<typename TypeTag>
@ -37,15 +40,13 @@ GasLiftSingleWell(const WellInterface<TypeTag> &well,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
WellState<Scalar>& well_state, WellState<Scalar>& well_state,
const GroupState<Scalar>& group_state, const GroupState<Scalar>& group_state,
GasLiftGroupInfo &group_info, GasLiftGroupInfo<Scalar>& group_info,
GLiftSyncGroups &sync_groups, GLiftSyncGroups &sync_groups,
const Parallel::Communication& comm, const Parallel::Communication& comm,
bool glift_debug bool glift_debug)
)
// The parent class GasLiftSingleWellGeneric contains all stuff // The parent class GasLiftSingleWellGeneric contains all stuff
// that is not dependent on TypeTag // that is not dependent on TypeTag
: GasLiftSingleWellGeneric( : GasLiftSingleWellGeneric<Scalar>(deferred_logger,
deferred_logger,
well_state, well_state,
group_state, group_state,
well.wellEcl(), well.wellEcl(),
@ -56,14 +57,13 @@ GasLiftSingleWell(const WellInterface<TypeTag> &well,
simulator.episodeIndex(), simulator.episodeIndex(),
sync_groups, sync_groups,
comm, comm,
glift_debug glift_debug)
)
, simulator_{simulator} , simulator_{simulator}
, well_{well} , well_{well}
{ {
const auto& gl_well = *gl_well_; const auto& gl_well = *this->gl_well_;
if(useFixedAlq_(gl_well)) { if (this->useFixedAlq_(gl_well)) {
updateWellStateAlqFixedValue_(gl_well); this->updateWellStateAlqFixedValue_(gl_well);
this->optimize_ = false; // lift gas supply is fixed this->optimize_ = false; // lift gas supply is fixed
} }
else { else {
@ -78,13 +78,13 @@ GasLiftSingleWell(const WellInterface<TypeTag> &well,
// default value is used. // default value is used.
this->orig_alq_ = this->well_state_.getALQ(this->well_name_); this->orig_alq_ = this->well_state_.getALQ(this->well_name_);
if (this->optimize_) { if (this->optimize_) {
setAlqMinRate_(gl_well); this->setAlqMinRate_(gl_well);
// NOTE: According to item 4 in WLIFTOPT, this value does not // NOTE: According to item 4 in WLIFTOPT, this value does not
// have to be positive. // have to be positive.
// TODO: Does it make sense to have a negative value? // TODO: Does it make sense to have a negative value?
this->alpha_w_ = gl_well.weight_factor(); this->alpha_w_ = gl_well.weight_factor();
if (this->alpha_w_ <= 0 ) { if (this->alpha_w_ <= 0 ) {
displayWarning_("Nonpositive value for alpha_w ignored"); this->displayWarning_("Nonpositive value for alpha_w ignored");
this->alpha_w_ = 1.0; this->alpha_w_ = 1.0;
} }
@ -107,23 +107,25 @@ GasLiftSingleWell(const WellInterface<TypeTag> &well,
****************************************/ ****************************************/
template<typename TypeTag> template<typename TypeTag>
GasLiftSingleWellGeneric::BasicRates typename GasLiftSingleWell<TypeTag>::BasicRates
GasLiftSingleWell<TypeTag>:: GasLiftSingleWell<TypeTag>::
computeWellRates_( double bhp, bool bhp_is_limited, bool debug_output ) const computeWellRates_(Scalar bhp, bool bhp_is_limited, bool debug_output ) const
{ {
std::vector<double> potentials(NUM_PHASES, 0.0); std::vector<Scalar> potentials(this->NUM_PHASES, 0.0);
this->well_.computeWellRatesWithBhp( this->well_.computeWellRatesWithBhp(this->simulator_,
this->simulator_, bhp, potentials, this->deferred_logger_); bhp,
potentials,
this->deferred_logger_);
if (debug_output) { if (debug_output) {
const std::string msg = fmt::format("computed well potentials given bhp {}, " const std::string msg = fmt::format("computed well potentials given bhp {}, "
"oil: {}, gas: {}, water: {}", bhp, "oil: {}, gas: {}, water: {}", bhp,
-potentials[this->oil_pos_], -potentials[this->gas_pos_], -potentials[this->oil_pos_], -potentials[this->gas_pos_],
-potentials[this->water_pos_]); -potentials[this->water_pos_]);
displayDebugMessage_(msg); this->displayDebugMessage_(msg);
} }
for (auto& potential : potentials) { for (auto& potential : potentials) {
potential = std::min(0.0, potential); potential = std::min(Scalar{0.0}, potential);
} }
return {-potentials[this->oil_pos_], return {-potentials[this->oil_pos_],
-potentials[this->gas_pos_], -potentials[this->gas_pos_],
@ -133,9 +135,9 @@ computeWellRates_( double bhp, bool bhp_is_limited, bool debug_output ) const
} }
template<typename TypeTag> template<typename TypeTag>
std::optional<double> std::optional<typename GasLiftSingleWell<TypeTag>::Scalar>
GasLiftSingleWell<TypeTag>:: GasLiftSingleWell<TypeTag>::
computeBhpAtThpLimit_(double alq, bool debug_output) const computeBhpAtThpLimit_(Scalar alq, bool debug_output) const
{ {
auto bhp_at_thp_limit = this->well_.computeBhpAtThpLimitProdWithAlq( auto bhp_at_thp_limit = this->well_.computeBhpAtThpLimitProdWithAlq(
this->simulator_, this->simulator_,
@ -150,7 +152,7 @@ computeBhpAtThpLimit_(double alq, bool debug_output) const
" Using bhp limit instead", " Using bhp limit instead",
*bhp_at_thp_limit, this->controls_.bhp_limit, alq *bhp_at_thp_limit, this->controls_.bhp_limit, alq
); );
displayDebugMessage_(msg); this->displayDebugMessage_(msg);
} }
bhp_at_thp_limit = this->controls_.bhp_limit; bhp_at_thp_limit = this->controls_.bhp_limit;
} }
@ -159,7 +161,7 @@ computeBhpAtThpLimit_(double alq, bool debug_output) const
else { else {
const std::string msg = fmt::format( const std::string msg = fmt::format(
"Failed in getting converged bhp potential from thp limit (ALQ = {})", alq); "Failed in getting converged bhp potential from thp limit (ALQ = {})", alq);
displayDebugMessage_(msg); this->displayDebugMessage_(msg);
} }
return bhp_at_thp_limit; return bhp_at_thp_limit;
} }
@ -198,9 +200,9 @@ setupPhaseVariables_()
} }
} }
assert(num_phases_ok); assert(num_phases_ok);
this->oil_pos_ = pu.phase_pos[Oil]; this->oil_pos_ = pu.phase_pos[this->Oil];
this->gas_pos_ = pu.phase_pos[Gas]; this->gas_pos_ = pu.phase_pos[this->Gas];
this->water_pos_ = pu.phase_pos[Water]; this->water_pos_ = pu.phase_pos[this->Water];
} }
template<typename TypeTag> template<typename TypeTag>
@ -240,7 +242,7 @@ checkThpControl_() const
thp_control = thp_control || well.thpLimitViolatedButNotSwitched(); thp_control = thp_control || well.thpLimitViolatedButNotSwitched();
if (this->debug) { if (this->debug) {
if (!thp_control) { if (!thp_control) {
displayDebugMessage_("Well is not under THP control, skipping iteration.."); this->displayDebugMessage_("Well is not under THP control, skipping iteration..");
} }
} }
return thp_control; return thp_control;

View File

@ -39,21 +39,20 @@
namespace Opm { namespace Opm {
GasLiftStage2::GasLiftStage2( template<class Scalar>
const int report_step_idx, GasLiftStage2<Scalar>::GasLiftStage2(const int report_step_idx,
const Parallel::Communication& comm, const Parallel::Communication& comm,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summary_state, const SummaryState& summary_state,
DeferredLogger &deferred_logger, DeferredLogger &deferred_logger,
WellState<double>& well_state, WellState<Scalar>& well_state,
const GroupState<double>& group_state, const GroupState<Scalar>& group_state,
GLiftProdWells &prod_wells, GLiftProdWells &prod_wells,
GLiftOptWells &glift_wells, GLiftOptWells &glift_wells,
GasLiftGroupInfo& group_info, GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap &state_map, GLiftWellStateMap &state_map,
bool glift_debug bool glift_debug)
) : : GasLiftCommon<Scalar>(well_state, group_state, deferred_logger, comm, glift_debug)
GasLiftCommon(well_state, group_state, deferred_logger, comm, glift_debug)
, prod_wells_{prod_wells} , prod_wells_{prod_wells}
, stage1_wells_{glift_wells} , stage1_wells_{glift_wells}
, group_info_{group_info} , group_info_{group_info}
@ -80,14 +79,11 @@ GasLiftStage2::GasLiftStage2(
// currently has the largest weighted incremental gradient. The // currently has the largest weighted incremental gradient. The
// procedure takes account of any limits on the group production rate // procedure takes account of any limits on the group production rate
// or lift gas supply applied to any level of group, including the FIELD level group. // or lift gas supply applied to any level of group, including the FIELD level group.
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::runOptimize()
runOptimize()
{ {
const auto& group = this->schedule_.getGroup("FIELD", this->report_step_idx_); const auto& group = this->schedule_.getGroup("FIELD", this->report_step_idx_);
optimizeGroupsRecursive_(group); optimizeGroupsRecursive_(group);
} }
@ -100,16 +96,18 @@ runOptimize()
// saved in "grad_map") // saved in "grad_map")
// INPUT: grad_map : map of incremental (if "add" is true) or decremental // INPUT: grad_map : map of incremental (if "add" is true) or decremental
// (if "add" is false) GradInfo structs for each well name. // (if "add" is false) GradInfo structs for each well name.
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
addOrRemoveALQincrement_(GradMap &grad_map, const std::string& well_name, bool add) addOrRemoveALQincrement_(GradMap &grad_map,
const std::string& well_name,
bool add)
{ {
// only applies to wells in the well_state_map (i.e. wells on this rank) // only applies to wells in the well_state_map (i.e. wells on this rank)
auto it = this->well_state_map_.find(well_name); auto it = this->well_state_map_.find(well_name);
if (it == this->well_state_map_.end()) if (it == this->well_state_map_.end())
return; return;
GasLiftWellState &state = *(it->second.get()); GasLiftWellState<Scalar>& state = *(it->second.get());
const GradInfo& gi = grad_map.at(well_name); const GradInfo& gi = grad_map.at(well_name);
if (this->debug) { if (this->debug) {
auto new_alq = gi.alq; auto new_alq = gi.alq;
@ -121,11 +119,12 @@ addOrRemoveALQincrement_(GradMap &grad_map, const std::string& well_name, bool a
} }
state.update(gi.new_oil_rate, gi.oil_is_limited, state.update(gi.new_oil_rate, gi.oil_is_limited,
gi.new_gas_rate, gi.gas_is_limited, gi.new_gas_rate, gi.gas_is_limited,
gi.alq, gi.alq_is_limited, gi.new_water_rate, gi.water_is_limited, add); gi.alq, gi.alq_is_limited,
gi.new_water_rate, gi.water_is_limited, add);
this->well_state_.setALQ(well_name, gi.alq); this->well_state_.setALQ(well_name, gi.alq);
const auto& pu = this->well_state_.phaseUsage(); const auto& pu = this->well_state_.phaseUsage();
std::vector<double> well_pot(pu.num_phases, 0.0); std::vector<Scalar> well_pot(pu.num_phases, 0.0);
if (pu.phase_used[BlackoilPhases::PhaseIndex::Liquid]) if (pu.phase_used[BlackoilPhases::PhaseIndex::Liquid])
well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Liquid]] = gi.new_oil_rate; well_pot[pu.phase_pos[BlackoilPhases::PhaseIndex::Liquid]] = gi.new_oil_rate;
if (pu.phase_used[BlackoilPhases::PhaseIndex::Aqua]) if (pu.phase_used[BlackoilPhases::PhaseIndex::Aqua])
@ -136,16 +135,18 @@ addOrRemoveALQincrement_(GradMap &grad_map, const std::string& well_name, bool a
this->well_state_[well_name].well_potentials = well_pot; this->well_state_[well_name].well_potentials = well_pot;
} }
std::optional<GasLiftStage2::GradInfo> template<class Scalar>
GasLiftStage2:: std::optional<typename GasLiftStage2<Scalar>::GradInfo>
calcIncOrDecGrad_( GasLiftStage2<Scalar>::
const std::string well_name, const GasLiftSingleWell &gs_well, const std::string& gr_name_dont_limit, bool increase) calcIncOrDecGrad_(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) // only applies to wells in the well_state_map (i.e. wells on this rank)
if (this->well_state_map_.count(well_name) == 0) if (this->well_state_map_.count(well_name) == 0)
return std::nullopt; return std::nullopt;
GasLiftWellState &state = *(this->well_state_map_.at(well_name).get()); GasLiftWellState<Scalar>& state = *(this->well_state_map_.at(well_name).get());
if (checkRateAlreadyLimited_(well_name, state, increase)) { if (checkRateAlreadyLimited_(well_name, state, increase)) {
return std::nullopt; return std::nullopt;
} }
@ -179,14 +180,18 @@ calcIncOrDecGrad_(
} }
} }
bool template<class Scalar>
GasLiftStage2:: bool GasLiftStage2<Scalar>::
checkRateAlreadyLimited_(const std::string& well_name, GasLiftWellState &state, bool increase) checkRateAlreadyLimited_(const std::string& well_name,
GasLiftWellState<Scalar>& state,
bool increase)
{ {
auto current_increase = state.increase(); auto current_increase = state.increase();
bool do_check = false; bool do_check = false;
if (current_increase) { if (current_increase) {
if (*current_increase == increase) do_check = true; if (*current_increase == increase) {
do_check = true;
}
} }
else { else {
// If current_increase is not defined, it means that stage1 // If current_increase is not defined, it means that stage1
@ -196,10 +201,13 @@ checkRateAlreadyLimited_(const std::string& well_name, GasLiftWellState &state,
// cause the new rates not to be limited. However, if // cause the new rates not to be limited. However, if
// "increase" is false, subtracting ALQ can make the new rates // "increase" is false, subtracting ALQ can make the new rates
// not limited. // not limited.
if (increase) do_check = true; if (increase) {
do_check = true;
}
} }
if (do_check) { if (do_check) {
if (state.gasIsLimited() || state.oilIsLimited() || state.alqIsLimited() || state.waterIsLimited()) { if (state.gasIsLimited() || state.oilIsLimited() ||
state.alqIsLimited() || state.waterIsLimited()) {
const std::string msg = fmt::format( const std::string msg = fmt::format(
"Well {} : alq = {} : skipping {} gradient since {} was limited in previous step", "Well {} : alq = {} : skipping {} gradient since {} was limited in previous step",
well_name, well_name,
@ -214,8 +222,9 @@ checkRateAlreadyLimited_(const std::string& well_name, GasLiftWellState &state,
return false; return false;
} }
GasLiftStage2::GradInfo template<class Scalar>
GasLiftStage2:: typename GasLiftStage2<Scalar>::GradInfo
GasLiftStage2<Scalar>::
deleteGrad_(const std::string& name, bool increase) deleteGrad_(const std::string& name, bool increase)
{ {
GradMap &map = increase ? this->inc_grads_ : this->dec_grads_; GradMap &map = increase ? this->inc_grads_ : this->dec_grads_;
@ -224,55 +233,57 @@ deleteGrad_(const std::string &name, bool increase)
return value; return value;
} }
GasLiftStage2::GradInfo template<class Scalar>
GasLiftStage2:: typename GasLiftStage2<Scalar>::GradInfo
GasLiftStage2<Scalar>::
deleteDecGradItem_(const std::string& name) deleteDecGradItem_(const std::string& name)
{ {
return deleteGrad_(name, /*increase=*/false); return deleteGrad_(name, /*increase=*/false);
} }
GasLiftStage2::GradInfo template<class Scalar>
GasLiftStage2:: typename GasLiftStage2<Scalar>::GradInfo
GasLiftStage2<Scalar>::
deleteIncGradItem_(const std::string& name) deleteIncGradItem_(const std::string& name)
{ {
return deleteGrad_(name, /*increase=*/true); return deleteGrad_(name, /*increase=*/true);
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
displayWarning_(const std::string& msg, const std::string& group_name) displayWarning_(const std::string& msg, const std::string& group_name)
{ {
const std::string message = fmt::format("GROUP: {} : {}", group_name, msg); const std::string message = fmt::format("GROUP: {} : {}", group_name, msg);
displayWarning_(message); displayWarning_(message);
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
displayWarning_(const std::string& msg) displayWarning_(const std::string& msg)
{ {
logMessage_(/*prefix=*/"GLIFT2", msg, MessageType::WARNING); this->logMessage_(/*prefix=*/"GLIFT2", msg, MessageType::WARNING);
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
displayDebugMessage_(const std::string& msg) const displayDebugMessage_(const std::string& msg) const
{ {
if (this->debug) { if (this->debug) {
logMessage_(/*prefix=*/"GLIFT2", msg); this->logMessage_(/*prefix=*/"GLIFT2", msg);
} }
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
displayDebugMessage2B_(const std::string& msg) displayDebugMessage2B_(const std::string& msg)
{ {
if (this->debug) { if (this->debug) {
logMessage_(/*prefix=*/"GLIFT2B", msg); this->logMessage_(/*prefix=*/"GLIFT2B", msg);
} }
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
displayDebugMessage_(const std::string& msg, const std::string& group_name) displayDebugMessage_(const std::string& msg, const std::string& group_name)
{ {
if (this->debug) { if (this->debug) {
@ -282,8 +293,9 @@ displayDebugMessage_(const std::string &msg, const std::string &group_name)
} }
} }
std::tuple<double, double, double, double> template<class Scalar>
GasLiftStage2:: std::tuple<Scalar, Scalar, Scalar, Scalar>
GasLiftStage2<Scalar>::
getCurrentGroupRates_(const Group& group) getCurrentGroupRates_(const Group& group)
{ {
return {this->group_info_.oilRate(group.name()), return {this->group_info_.oilRate(group.name()),
@ -292,8 +304,9 @@ getCurrentGroupRates_(const Group &group)
this->group_info_.alqRate(group.name())}; this->group_info_.alqRate(group.name())};
} }
std::optional<double> template<class Scalar>
GasLiftStage2::getGroupMaxALQ_(const Group &group) std::optional<Scalar>
GasLiftStage2<Scalar>::getGroupMaxALQ_(const Group& group)
{ {
if (this->glo_.has_group(group.name())) { if (this->glo_.has_group(group.name())) {
const auto& gl_group = this->glo_.group(group.name()); const auto& gl_group = this->glo_.group(group.name());
@ -302,8 +315,9 @@ GasLiftStage2::getGroupMaxALQ_(const Group &group)
return std::nullopt; // If GLIFTOPT is missing from schedule, assume unlimited alq return std::nullopt; // If GLIFTOPT is missing from schedule, assume unlimited alq
} }
std::optional<double> template<class Scalar>
GasLiftStage2::getGroupMaxTotalGas_(const Group &group) std::optional<Scalar>
GasLiftStage2<Scalar>::getGroupMaxTotalGas_(const Group& group)
{ {
if (this->glo_.has_group(group.name())) { if (this->glo_.has_group(group.name())) {
const auto& gl_group = this->glo_.group(group.name()); const auto& gl_group = this->glo_.group(group.name());
@ -320,8 +334,9 @@ GasLiftStage2::getGroupMaxTotalGas_(const Group &group)
// NOTE: This means that wells are located at the leaf nodes of the tree, and // NOTE: This means that wells are located at the leaf nodes of the tree, and
// groups are located at the other nodes (not leaf nodes) of the tree // groups are located at the other nodes (not leaf nodes) of the tree
// //
std::vector<GasLiftSingleWellGeneric*> template<class Scalar>
GasLiftStage2:: std::vector<GasLiftSingleWellGeneric<Scalar>*>
GasLiftStage2<Scalar>::
getGroupGliftWells_(const Group& group) getGroupGliftWells_(const Group& group)
{ {
std::vector<GasLiftSingleWell*> wells; std::vector<GasLiftSingleWell*> wells;
@ -329,8 +344,8 @@ getGroupGliftWells_(const Group &group)
return wells; return wells;
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
getGroupGliftWellsRecursive_(const Group& group, getGroupGliftWellsRecursive_(const Group& group,
std::vector<GasLiftSingleWell*> &wells) std::vector<GasLiftSingleWell*> &wells)
{ {
@ -349,8 +364,8 @@ getGroupGliftWellsRecursive_(const Group &group,
} }
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
mpiSyncGlobalGradVector_(std::vector<GradPair>& grads_global) const mpiSyncGlobalGradVector_(std::vector<GradPair>& grads_global) const
{ {
if (this->comm_.size() == 1) if (this->comm_.size() == 1)
@ -365,10 +380,10 @@ mpiSyncGlobalGradVector_(std::vector<GradPair> &grads_global) const
mpiSyncLocalToGlobalGradVector_(grads_local, grads_global); mpiSyncLocalToGlobalGradVector_(grads_local, grads_global);
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
mpiSyncLocalToGlobalGradVector_( mpiSyncLocalToGlobalGradVector_(const std::vector<GradPair>& grads_local,
const std::vector<GradPair> &grads_local, std::vector<GradPair> &grads_global) const std::vector<GradPair>& grads_global) const
{ {
assert(this->comm_.size() > 1); // The parent should check if comm. size is > 1 assert(this->comm_.size() > 1); // The parent should check if comm. size is > 1
using Pair = std::pair<int, double>; using Pair = std::pair<int, double>;
@ -400,13 +415,13 @@ mpiSyncLocalToGlobalGradVector_(
for (std::size_t i = 0; i < grads_global_tmp.size(); ++i) { for (std::size_t i = 0; i < grads_global_tmp.size(); ++i) {
grads_global.emplace_back( grads_global.emplace_back(
std::make_pair( std::make_pair(
well_state_.globalIdxToWellName(grads_global_tmp[i].first), this->well_state_.globalIdxToWellName(grads_global_tmp[i].first),
grads_global_tmp[i].second)); grads_global_tmp[i].second));
} }
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
optimizeGroup_(const Group& group) optimizeGroup_(const Group& group)
{ {
const auto& group_name = group.name(); const auto& group_name = group.name();
@ -431,8 +446,8 @@ optimizeGroup_(const Group &group)
} }
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
optimizeGroupsRecursive_(const Group& group) optimizeGroupsRecursive_(const Group& group)
{ {
for (const std::string& group_name : group.groups()) { for (const std::string& group_name : group.groups()) {
@ -445,15 +460,16 @@ optimizeGroupsRecursive_(const Group &group)
optimizeGroup_(group); optimizeGroup_(group);
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
recalculateGradientAndUpdateData_( recalculateGradientAndUpdateData_(GradPairItr& grad_itr,
GradPairItr &grad_itr, const std::string& gr_name_dont_limit, bool increase, const std::string& gr_name_dont_limit,
bool increase,
//incremental and decremental gradients, if 'grads' are incremental, then //incremental and decremental gradients, if 'grads' are incremental, then
// 'other_grads' are decremental, or conversely, if 'grads' are decremental, then // 'other_grads' are decremental, or conversely, if 'grads' are decremental, then
// 'other_grads' are incremental // 'other_grads' are incremental
std::vector<GradPair> &grads, std::vector<GradPair> &other_grads) std::vector<GradPair>& grads,
std::vector<GradPair>& other_grads)
{ {
// NOTE: We make a copy of the name string instead of taking a reference // NOTE: We make a copy of the name string instead of taking a reference
// since we may have to erase grad_itr (in the "else" condition below) // since we may have to erase grad_itr (in the "else" condition below)
@ -547,10 +563,12 @@ recalculateGradientAndUpdateData_(
// just do it once for the topmost group "PLAT-A" and then skip redistribution for // just do it once for the topmost group "PLAT-A" and then skip redistribution for
// all sub groups of "PLAT-A" // all sub groups of "PLAT-A"
// //
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
redistributeALQ_(std::vector<GasLiftSingleWell *> &wells, const Group &group, redistributeALQ_(std::vector<GasLiftSingleWell*>& wells,
std::vector<GradPair> &inc_grads, std::vector<GradPair> &dec_grads) const Group& group,
std::vector<GradPair>& inc_grads,
std::vector<GradPair>& dec_grads)
{ {
OptimizeState state {*this, group}; OptimizeState state {*this, group};
if (this->comm_.size() == 1) { if (this->comm_.size() == 1) {
@ -613,10 +631,11 @@ redistributeALQ_(std::vector<GasLiftSingleWell *> &wells, const Group &group,
// Lift gas increments are removed in turn from the well that currently has // Lift gas increments are removed in turn from the well that currently has
// the smallest weighted decremental gradient, until there is no surplus // the smallest weighted decremental gradient, until there is no surplus
// lift gas in the group. // lift gas in the group.
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
removeSurplusALQ_(const Group& group, removeSurplusALQ_(const Group& group,
std::vector<GradPair> &inc_grads, std::vector<GradPair> &dec_grads) std::vector<GradPair>& inc_grads,
std::vector<GradPair>& dec_grads)
{ {
if (dec_grads.empty()) { if (dec_grads.empty()) {
displayDebugMessage_("no wells to remove ALQ from. Skipping"); displayDebugMessage_("no wells to remove ALQ from. Skipping");
@ -642,8 +661,12 @@ removeSurplusALQ_(const Group &group,
displayDebugMessage_(msg); displayDebugMessage_(msg);
} }
SurplusState state {*this, group, oil_rate, gas_rate, water_rate, alq, SurplusState state {*this, group, oil_rate, gas_rate, water_rate, alq,
min_eco_grad, controls.oil_target, controls.gas_target, controls.water_target, static_cast<Scalar>(min_eco_grad),
controls.liquid_target, max_glift, max_totalgas }; static_cast<Scalar>(controls.oil_target),
static_cast<Scalar>(controls.gas_target),
static_cast<Scalar>(controls.water_target),
static_cast<Scalar>(controls.liquid_target),
max_glift, max_totalgas };
while (!stop_iteration) { while (!stop_iteration) {
if (dec_grads.size() >= 2) { if (dec_grads.size() >= 2) {
@ -707,8 +730,8 @@ removeSurplusALQ_(const Group &group,
} }
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
saveGrad_(GradMap& map, const std::string& name, GradInfo& grad) saveGrad_(GradMap& map, const std::string& name, GradInfo& grad)
{ {
if (auto it = map.find(name); it == map.end()) { if (auto it = map.find(name); it == map.end()) {
@ -720,22 +743,22 @@ saveGrad_(GradMap &map, const std::string &name, GradInfo &grad)
} }
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
saveDecGrad_(const std::string& name, GradInfo& grad) saveDecGrad_(const std::string& name, GradInfo& grad)
{ {
saveGrad_(this->dec_grads_, name, grad); saveGrad_(this->dec_grads_, name, grad);
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
saveIncGrad_(const std::string& name, GradInfo& grad) saveIncGrad_(const std::string& name, GradInfo& grad)
{ {
saveGrad_(this->inc_grads_, name, grad); saveGrad_(this->inc_grads_, name, grad);
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
sortGradients_(std::vector<GradPair>& grads) sortGradients_(std::vector<GradPair>& grads)
{ {
auto cmp = [](GradPair a, GradPair b) { auto cmp = [](GradPair a, GradPair b) {
@ -744,8 +767,9 @@ sortGradients_(std::vector<GradPair> &grads)
std::sort(grads.begin(), grads.end(), cmp); std::sort(grads.begin(), grads.end(), cmp);
} }
std::optional<GasLiftStage2::GradInfo> template<class Scalar>
GasLiftStage2:: std::optional<typename GasLiftStage2<Scalar>::GradInfo>
GasLiftStage2<Scalar>::
updateGrad_(const std::string& name, GradInfo& grad, bool increase) updateGrad_(const std::string& name, GradInfo& grad, bool increase)
{ {
GradMap& map = increase ? this->inc_grads_ : this->dec_grads_; GradMap& map = increase ? this->inc_grads_ : this->dec_grads_;
@ -757,9 +781,11 @@ updateGrad_(const std::string &name, GradInfo &grad, bool increase)
return old_value; return old_value;
} }
void template<class Scalar>
GasLiftStage2:: void GasLiftStage2<Scalar>::
updateGradVector_(const std::string &name, std::vector<GradPair> &grads, double grad) updateGradVector_(const std::string& name,
std::vector<GradPair>& grads,
Scalar grad)
{ {
for (auto itr = grads.begin(); itr != grads.end(); itr++) { for (auto itr = grads.begin(); itr != grads.end(); itr++) {
if (itr->first == name) { if (itr->first == name) {
@ -776,10 +802,11 @@ updateGradVector_(const std::string &name, std::vector<GradPair> &grads, double
* Public methods declared in OptimizeState * Public methods declared in OptimizeState
***********************************************/ ***********************************************/
void template<class Scalar>
GasLiftStage2::OptimizeState:: void GasLiftStage2<Scalar>::OptimizeState::
calculateEcoGradients(std::vector<GasLiftSingleWell*>& wells, calculateEcoGradients(std::vector<GasLiftSingleWell*>& wells,
std::vector<GradPair> &inc_grads, std::vector<GradPair> &dec_grads) std::vector<GradPair>& inc_grads,
std::vector<GradPair>& dec_grads)
{ {
for (auto well_ptr : wells) { for (auto well_ptr : wells) {
const auto& gs_well = *well_ptr; // gs = GasLiftSingleWell const auto& gs_well = *well_ptr; // gs = GasLiftSingleWell
@ -797,9 +824,8 @@ calculateEcoGradients(std::vector<GasLiftSingleWell *> &wells,
} }
} }
template<class Scalar>
bool bool GasLiftStage2<Scalar>::OptimizeState::
GasLiftStage2::OptimizeState::
checkAtLeastTwoWells(std::vector<GasLiftSingleWell*>& wells) checkAtLeastTwoWells(std::vector<GasLiftSingleWell*>& wells)
{ {
int numberOfwells = 0; int numberOfwells = 0;
@ -819,18 +845,20 @@ checkAtLeastTwoWells(std::vector<GasLiftSingleWell *> &wells)
return true; return true;
} }
void template<class Scalar>
GasLiftStage2::OptimizeState:: void GasLiftStage2<Scalar>::OptimizeState::
debugShowIterationInfo() debugShowIterationInfo()
{ {
const std::string msg = fmt::format("redistribute ALQ iteration {}", this->it); const std::string msg = fmt::format("redistribute ALQ iteration {}", this->it);
displayDebugMessage_(msg); displayDebugMessage_(msg);
} }
std::pair<std::optional<GasLiftStage2::GradPairItr>, template<class Scalar>
std::optional<GasLiftStage2::GradPairItr>> std::pair<std::optional<typename GasLiftStage2<Scalar>::GradPairItr>,
GasLiftStage2::OptimizeState:: std::optional<typename GasLiftStage2<Scalar>::GradPairItr>>
getEcoGradients(std::vector<GradPair> &inc_grads, std::vector<GradPair> &dec_grads) GasLiftStage2<Scalar>::OptimizeState::
getEcoGradients(std::vector<GradPair>& inc_grads,
std::vector<GradPair>& dec_grads)
{ {
if (!inc_grads.empty() && !dec_grads.empty()) { if (!inc_grads.empty() && !dec_grads.empty()) {
this->parent.sortGradients_(inc_grads); this->parent.sortGradients_(inc_grads);
@ -869,11 +897,12 @@ getEcoGradients(std::vector<GradPair> &inc_grads, std::vector<GradPair> &dec_gra
// a new decremental gradient given the new ALQ. The new incremental gradient // a new decremental gradient given the new ALQ. The new incremental gradient
// for this well is set equal to the current decremental gradient // for this well is set equal to the current decremental gradient
// (before the ALQ is subtracted) // (before the ALQ is subtracted)
void template<class Scalar>
GasLiftStage2::OptimizeState:: void GasLiftStage2<Scalar>::OptimizeState::
recalculateGradients( recalculateGradients(std::vector<GradPair>& inc_grads,
std::vector<GradPair> &inc_grads, std::vector<GradPair> &dec_grads, std::vector<GradPair>& dec_grads,
GradPairItr &min_dec_grad_itr, GradPairItr &max_inc_grad_itr) GradPairItr& min_dec_grad_itr,
GradPairItr& max_inc_grad_itr)
{ {
this->parent.recalculateGradientAndUpdateData_( this->parent.recalculateGradientAndUpdateData_(
max_inc_grad_itr, this->group.name(), /*increase=*/true, inc_grads, dec_grads); max_inc_grad_itr, this->group.name(), /*increase=*/true, inc_grads, dec_grads);
@ -886,9 +915,10 @@ recalculateGradients(
} }
// Take one ALQ increment from well1, and give it to well2 // Take one ALQ increment from well1, and give it to well2
void template<class Scalar>
GasLiftStage2::OptimizeState:: void GasLiftStage2<Scalar>::OptimizeState::
redistributeALQ( GradPairItr &min_dec_grad, GradPairItr &max_inc_grad) redistributeALQ(GradPairItr& min_dec_grad,
GradPairItr& max_inc_grad)
{ {
const std::string msg = fmt::format( const std::string msg = fmt::format(
"redistributing ALQ from well {} (dec gradient: {}) " "redistributing ALQ from well {} (dec gradient: {}) "
@ -906,15 +936,15 @@ GasLiftStage2::OptimizeState::
* Private methods declared in OptimizeState * Private methods declared in OptimizeState
**********************************************/ **********************************************/
void template<class Scalar>
GasLiftStage2::OptimizeState:: void GasLiftStage2<Scalar>::OptimizeState::
displayDebugMessage_(const std::string& msg) displayDebugMessage_(const std::string& msg)
{ {
this->parent.displayDebugMessage_(msg, this->group.name()); this->parent.displayDebugMessage_(msg, this->group.name());
} }
void template<class Scalar>
GasLiftStage2::OptimizeState:: void GasLiftStage2<Scalar>::OptimizeState::
displayWarning_(const std::string& msg) displayWarning_(const std::string& msg)
{ {
this->parent.displayWarning_(msg, this->group.name()); this->parent.displayWarning_(msg, this->group.name());
@ -924,9 +954,11 @@ displayWarning_(const std::string &msg)
* Public methods declared in SurplusState * Public methods declared in SurplusState
**********************************************/ **********************************************/
void template<class Scalar>
GasLiftStage2::SurplusState:: void GasLiftStage2<Scalar>::SurplusState::
addOrRemoveALQincrement(GradMap &grad_map, const std::string& well_name, bool add) 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", const std::string msg = fmt::format("group: {} : well {} : {} ALQ increment",
@ -936,12 +968,12 @@ addOrRemoveALQincrement(GradMap &grad_map, const std::string& well_name, bool ad
this->parent.addOrRemoveALQincrement_(grad_map, well_name, add); this->parent.addOrRemoveALQincrement_(grad_map, well_name, add);
} }
bool template<class Scalar>
GasLiftStage2::SurplusState:: bool GasLiftStage2<Scalar>::SurplusState::
checkALQlimit() checkALQlimit()
{ {
if (this->max_glift) { if (this->max_glift) {
double max_alq = *(this->max_glift); Scalar max_alq = *(this->max_glift);
if ((max_alq) < (this->alq) ) { if ((max_alq) < (this->alq) ) {
if (this->parent.debug) { if (this->parent.debug) {
const std::string msg = fmt::format("group: {} : " const std::string msg = fmt::format("group: {} : "
@ -953,8 +985,8 @@ checkALQlimit()
} }
} }
if (this->max_total_gas) { if (this->max_total_gas) {
double max_total = *(this->max_total_gas); Scalar max_total = *(this->max_total_gas);
double total_gas_rate = (this->alq + this->gas_rate); Scalar total_gas_rate = (this->alq + this->gas_rate);
if ((max_total) < total_gas_rate ) { if ((max_total) < total_gas_rate ) {
if (this->parent.debug) { if (this->parent.debug) {
const std::string msg = fmt::format("group: {} : " const std::string msg = fmt::format("group: {} : "
@ -968,9 +1000,9 @@ checkALQlimit()
return false; return false;
} }
bool template<class Scalar>
GasLiftStage2::SurplusState:: bool GasLiftStage2<Scalar>::SurplusState::
checkEcoGradient(const std::string &well_name, double eco_grad) checkEcoGradient(const std::string& well_name, Scalar eco_grad)
{ {
if (eco_grad < this->min_eco_grad) { if (eco_grad < this->min_eco_grad) {
if (this->parent.debug) { if (this->parent.debug) {
@ -986,9 +1018,9 @@ checkEcoGradient(const std::string &well_name, double eco_grad)
} }
} }
bool template<class Scalar>
GasLiftStage2::SurplusState:: bool GasLiftStage2<Scalar>::SurplusState::
checkGasTarget(double delta_gas) checkGasTarget(Scalar delta_gas)
{ {
if (this->group.has_control(Group::ProductionCMode::GRAT)) { if (this->group.has_control(Group::ProductionCMode::GRAT)) {
// the change in gas rate is added to the gas rate to make sure the // the change in gas rate is added to the gas rate to make sure the
@ -1007,9 +1039,10 @@ checkGasTarget(double delta_gas)
} }
return false; return false;
} }
bool
GasLiftStage2::SurplusState:: template<class Scalar>
checkLiquidTarget(double delta_liquid) bool GasLiftStage2<Scalar>::SurplusState::
checkLiquidTarget(Scalar delta_liquid)
{ {
if (this->group.has_control(Group::ProductionCMode::LRAT)) { if (this->group.has_control(Group::ProductionCMode::LRAT)) {
// the change in liquid rate is added to the liquid rate to make sure the // the change in liquid rate is added to the liquid rate to make sure the
@ -1030,9 +1063,9 @@ checkLiquidTarget(double delta_liquid)
return false; return false;
} }
bool template<class Scalar>
GasLiftStage2::SurplusState:: bool GasLiftStage2<Scalar>::SurplusState::
checkOilTarget(double delta_oil) checkOilTarget(Scalar delta_oil)
{ {
if (this->group.has_control(Group::ProductionCMode::ORAT)) { if (this->group.has_control(Group::ProductionCMode::ORAT)) {
// the change in oil rate is added to the oil rate to make sure the // the change in oil rate is added to the oil rate to make sure the
@ -1052,9 +1085,9 @@ checkOilTarget(double delta_oil)
return false; return false;
} }
bool template<class Scalar>
GasLiftStage2::SurplusState:: bool GasLiftStage2<Scalar>::SurplusState::
checkWaterTarget(double delta_water) checkWaterTarget(Scalar delta_water)
{ {
if (this->group.has_control(Group::ProductionCMode::WRAT)) { if (this->group.has_control(Group::ProductionCMode::WRAT)) {
// the change in water rate is added to the water rate to make sure the // the change in water rate is added to the water rate to make sure the
@ -1074,21 +1107,22 @@ checkWaterTarget(double delta_water)
return false; return false;
} }
std::array<double, 4> template<class Scalar>
GasLiftStage2::SurplusState:: std::array<Scalar, 4>
GasLiftStage2<Scalar>::SurplusState::
computeDelta(const std::string& well_name) computeDelta(const std::string& well_name)
{ {
std::array<double, 4> delta = {0.0, 0.0, 0.0, 0.0}; std::array<Scalar, 4> delta = {0.0, 0.0, 0.0, 0.0};
// compute the delta on wells on own rank // compute the delta on wells on own rank
if (this->parent.well_state_map_.count(well_name) > 0) { if (this->parent.well_state_map_.count(well_name) > 0) {
const GradInfo& gi = this->parent.dec_grads_.at(well_name); const GradInfo& gi = this->parent.dec_grads_.at(well_name);
GasLiftWellState &state = *(this->parent.well_state_map_.at(well_name).get()); GasLiftWellState<Scalar>& state = *(this->parent.well_state_map_.at(well_name).get());
GasLiftSingleWell& gs_well = *(this->parent.stage1_wells_.at(well_name).get()); GasLiftSingleWell& gs_well = *(this->parent.stage1_wells_.at(well_name).get());
const WellInterfaceGeneric& well = gs_well.getWell(); const WellInterfaceGeneric& well = gs_well.getWell();
// only get deltas for wells owned by this rank // only get deltas for wells owned by this rank
if (this->parent.well_state_.wellIsOwned(well.indexOfWell(), well_name)) { if (this->parent.well_state_.wellIsOwned(well.indexOfWell(), well_name)) {
const auto& well_ecl = well.wellEcl(); const auto& well_ecl = well.wellEcl();
double factor = well_ecl.getEfficiencyFactor(); Scalar factor = well_ecl.getEfficiencyFactor();
auto& [delta_oil, delta_gas, delta_water, delta_alq] = delta; auto& [delta_oil, delta_gas, delta_water, delta_alq] = delta;
delta_oil = factor * (gi.new_oil_rate - state.oilRate()); delta_oil = factor * (gi.new_oil_rate - state.oilRate());
delta_gas = factor * (gi.new_gas_rate - state.gasRate()); delta_gas = factor * (gi.new_gas_rate - state.gasRate());
@ -1103,9 +1137,9 @@ computeDelta(const std::string &well_name)
return delta; return delta;
} }
void template<class Scalar>
GasLiftStage2::SurplusState:: void GasLiftStage2<Scalar>::SurplusState::
updateRates(const std::array<double, 4>& delta) updateRates(const std::array<Scalar, 4>& delta)
{ {
const auto& [delta_oil, delta_gas, delta_water, delta_alq] = delta; const auto& [delta_oil, delta_gas, delta_water, delta_alq] = delta;
this->oil_rate += delta_oil; this->oil_rate += delta_oil;
@ -1114,5 +1148,6 @@ updateRates(const std::array<double, 4>& delta)
this->alq += delta_alq; this->alq += delta_alq;
} }
template class GasLiftStage2<double>;
} // namespace Opm } // namespace Opm

View File

@ -30,96 +30,124 @@
#include <tuple> #include <tuple>
#include <vector> #include <vector>
namespace Opm namespace Opm {
{
class DeferredLogger; class DeferredLogger;
class GasLiftOpt; class GasLiftOpt;
class GasLiftWellState; template<class Scalar> class GasLiftWellState;
class Group; class Group;
template<class Scalar> class GroupState; template<class Scalar> class GroupState;
class Schedule; class Schedule;
class WellInterfaceGeneric; class WellInterfaceGeneric;
template<class Scalar> class WellState; template<class Scalar> class WellState;
class GasLiftStage2 : public GasLiftCommon { template<class Scalar>
using GasLiftSingleWell = GasLiftSingleWellGeneric; class GasLiftStage2 : public GasLiftCommon<Scalar>
{
using GasLiftSingleWell = GasLiftSingleWellGeneric<Scalar>;
using GLiftOptWells = std::map<std::string,std::unique_ptr<GasLiftSingleWell>>; using GLiftOptWells = std::map<std::string,std::unique_ptr<GasLiftSingleWell>>;
using GLiftProdWells = std::map<std::string,const WellInterfaceGeneric*>; using GLiftProdWells = std::map<std::string,const WellInterfaceGeneric*>;
using GLiftWellStateMap = std::map<std::string,std::unique_ptr<GasLiftWellState>>; using GLiftWellStateMap = std::map<std::string,std::unique_ptr<GasLiftWellState<Scalar>>>;
using GradPair = std::pair<std::string, double>; using GradPair = std::pair<std::string, Scalar>;
using GradPairItr = std::vector<GradPair>::iterator; using GradPairItr = typename std::vector<GradPair>::iterator;
using GradInfo = typename GasLiftSingleWellGeneric::GradInfo; using GradInfo = typename GasLiftSingleWellGeneric<Scalar>::GradInfo;
using GradMap = std::map<std::string, GradInfo>; using GradMap = std::map<std::string, GradInfo>;
using MPIComm = typename Dune::MPIHelper::MPICommunicator; using MessageType = typename GasLiftCommon<Scalar>::MessageType;
static const int Water = BlackoilPhases::Aqua; static const int Water = BlackoilPhases::Aqua;
static const int Oil = BlackoilPhases::Liquid; static const int Oil = BlackoilPhases::Liquid;
static const int Gas = BlackoilPhases::Vapour; static const int Gas = BlackoilPhases::Vapour;
public: public:
GasLiftStage2( GasLiftStage2(const int report_step_idx,
const int report_step_idx,
const Parallel::Communication& comm, const Parallel::Communication& comm,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summary_state, const SummaryState& summary_state,
DeferredLogger& deferred_logger, DeferredLogger& deferred_logger,
WellState<double>& well_state, WellState<Scalar>& well_state,
const GroupState<double>& group_state, const GroupState<Scalar>& group_state,
GLiftProdWells& prod_wells, GLiftProdWells& prod_wells,
GLiftOptWells& glift_wells, GLiftOptWells& glift_wells,
GasLiftGroupInfo& group_info, GasLiftGroupInfo<Scalar>& group_info,
GLiftWellStateMap& state_map, GLiftWellStateMap& state_map,
bool glift_debug bool glift_debug);
);
void runOptimize(); void runOptimize();
protected: protected:
void addOrRemoveALQincrement_( void addOrRemoveALQincrement_(GradMap& grad_map,
GradMap& grad_map, const std::string& well_name, bool add); const std::string& well_name,
std::optional<GradInfo> calcIncOrDecGrad_( bool add);
const std::string name, const GasLiftSingleWell& gs_well, const std::string& gr_name_dont_limit, bool increase);
bool checkRateAlreadyLimited_(const std::string& well_name, GasLiftWellState& state, bool increase); std::optional<GradInfo> calcIncOrDecGrad_(const std::string name,
const GasLiftSingleWell& gs_well,
const std::string& gr_name_dont_limit,
bool increase);
bool checkRateAlreadyLimited_(const std::string& well_name,
GasLiftWellState<Scalar>& state,
bool increase);
GradInfo deleteDecGradItem_(const std::string& name); GradInfo deleteDecGradItem_(const std::string& name);
GradInfo deleteIncGradItem_(const std::string& name); GradInfo deleteIncGradItem_(const std::string& name);
GradInfo deleteGrad_(const std::string& name, bool increase); GradInfo deleteGrad_(const std::string& name, bool increase);
void displayDebugMessage_(const std::string& msg) const override; void displayDebugMessage_(const std::string& msg) const override;
void displayDebugMessage2B_(const std::string& msg); void displayDebugMessage2B_(const std::string& msg);
void displayDebugMessage_(const std::string& msg, const std::string& group_name); void displayDebugMessage_(const std::string& msg,
void displayWarning_(const std::string& msg, const std::string& group_name); const std::string& group_name);
void displayWarning_(const std::string& msg,
const std::string& group_name);
void displayWarning_(const std::string& msg); void displayWarning_(const std::string& msg);
std::tuple<double, double, double, double> getCurrentGroupRates_(const Group& group);
std::optional<double> getGroupMaxALQ_(const Group &group); std::tuple<Scalar, Scalar, Scalar, Scalar>
std::optional<double> getGroupMaxTotalGas_(const Group &group); getCurrentGroupRates_(const Group& group);
std::vector<GasLiftSingleWell *> getGroupGliftWells_(
const Group& group); std::optional<Scalar> getGroupMaxALQ_(const Group& group);
void getGroupGliftWellsRecursive_( std::optional<Scalar> getGroupMaxTotalGas_(const Group& group);
const Group& group, std::vector<GasLiftSingleWell *>& wells);
std::vector<GasLiftSingleWell*> getGroupGliftWells_(const Group& group);
void getGroupGliftWellsRecursive_(const Group& group,
std::vector<GasLiftSingleWell*>& wells);
void optimizeGroup_(const Group& group); void optimizeGroup_(const Group& group);
void optimizeGroupsRecursive_(const Group& group); void optimizeGroupsRecursive_(const Group& group);
void recalculateGradientAndUpdateData_(
GradPairItr& grad_itr, const std::string& gr_name_dont_limit, bool increase, void recalculateGradientAndUpdateData_(GradPairItr& grad_itr,
std::vector<GradPair>& grads, std::vector<GradPair>& other_grads); const std::string& gr_name_dont_limit,
void redistributeALQ_( bool increase,
std::vector<GasLiftSingleWell *>& wells, const Group& group, std::vector<GradPair>& grads,
std::vector<GradPair>& inc_grads, std::vector<GradPair>& dec_grads); std::vector<GradPair>& other_grads);
void removeSurplusALQ_(
void redistributeALQ_(std::vector<GasLiftSingleWell*>& wells,
const Group& group, const Group& group,
std::vector<GradPair>& inc_grads, std::vector<GradPair>& dec_grads); std::vector<GradPair>& inc_grads,
std::vector<GradPair>& dec_grads);
void removeSurplusALQ_(const Group& group,
std::vector<GradPair>& inc_grads,
std::vector<GradPair>& dec_grads);
void saveGrad_(GradMap& map, const std::string& name, GradInfo& grad); void saveGrad_(GradMap& map, const std::string& name, GradInfo& grad);
void saveDecGrad_(const std::string& name, GradInfo& grad); void saveDecGrad_(const std::string& name, GradInfo& grad);
void saveIncGrad_(const std::string& name, GradInfo& grad); void saveIncGrad_(const std::string& name, GradInfo& grad);
void sortGradients_(std::vector<GradPair>& grads); void sortGradients_(std::vector<GradPair>& grads);
std::optional<GradInfo> updateGrad_(
const std::string& name, GradInfo& grad, bool increase);
void updateGradVector_(
const std::string& name, std::vector<GradPair>& grads, double grad);
void mpiSyncGlobalGradVector_(std::vector<GradPair>& grads_global) const;
void mpiSyncLocalToGlobalGradVector_(
const std::vector<GradPair>& grads_local,
std::vector<GradPair>& grads_global) const;
std::optional<GradInfo> updateGrad_(const std::string& name,
GradInfo& grad, bool increase);
void updateGradVector_(const std::string& name,
std::vector<GradPair>& grads,
Scalar grad);
void mpiSyncGlobalGradVector_(std::vector<GradPair>& grads_global) const;
void mpiSyncLocalToGlobalGradVector_(const std::vector<GradPair>& grads_local,
std::vector<GradPair>& grads_global) const;
GLiftProdWells& prod_wells_; GLiftProdWells& prod_wells_;
GLiftOptWells& stage1_wells_; GLiftOptWells& stage1_wells_;
GasLiftGroupInfo& group_info_; GasLiftGroupInfo<Scalar>& group_info_;
GLiftWellStateMap& well_state_map_; GLiftWellStateMap& well_state_map_;
int report_step_idx_; int report_step_idx_;
@ -131,12 +159,14 @@ protected:
int max_iterations_ = 1000; int max_iterations_ = 1000;
//int time_step_idx_; //int time_step_idx_;
struct OptimizeState { struct OptimizeState
OptimizeState(GasLiftStage2& parent_, const Group& group_ ) : {
parent{parent_}, OptimizeState(GasLiftStage2& parent_, const Group& group_)
group{group_}, : parent{parent_}
it{0} , group{group_}
, it{0}
{} {}
GasLiftStage2& parent; GasLiftStage2& parent;
const Group& group; const Group& group;
int it; int it;
@ -145,70 +175,90 @@ protected:
using GradPair = typename GasLiftStage2::GradPair; using GradPair = typename GasLiftStage2::GradPair;
using GradPairItr = typename GasLiftStage2::GradPairItr; using GradPairItr = typename GasLiftStage2::GradPairItr;
using GradMap = typename GasLiftStage2::GradMap; using GradMap = typename GasLiftStage2::GradMap;
void calculateEcoGradients(std::vector<GasLiftSingleWell*>& wells, void calculateEcoGradients(std::vector<GasLiftSingleWell*>& wells,
std::vector<GradPair>& inc_grads, std::vector<GradPair>& dec_grads); std::vector<GradPair>& inc_grads,
std::vector<GradPair>& dec_grads);
bool checkAtLeastTwoWells(std::vector<GasLiftSingleWell*>& wells); bool checkAtLeastTwoWells(std::vector<GasLiftSingleWell*>& wells);
void debugShowIterationInfo(); void debugShowIterationInfo();
std::pair<std::optional<GradPairItr>,std::optional<GradPairItr>> std::pair<std::optional<GradPairItr>,std::optional<GradPairItr>>
getEcoGradients( getEcoGradients(std::vector<GradPair>& inc_grads,
std::vector<GradPair>& inc_grads, std::vector<GradPair>& dec_grads); std::vector<GradPair>& dec_grads);
void recalculateGradients(
std::vector<GradPair>& inc_grads, std::vector<GradPair>& dec_grads, void recalculateGradients(std::vector<GradPair>& inc_grads,
GradPairItr& min_dec_grad_itr, GradPairItr &max_inc_grad_itr); std::vector<GradPair>& dec_grads,
void redistributeALQ( GradPairItr& min_dec_grad, GradPairItr& max_inc_grad); GradPairItr& min_dec_grad_itr,
GradPairItr &max_inc_grad_itr);
void redistributeALQ( GradPairItr& min_dec_grad,
GradPairItr& max_inc_grad);
private: private:
void displayDebugMessage_(const std::string& msg); void displayDebugMessage_(const std::string& msg);
void displayWarning_(const std::string& msg); void displayWarning_(const std::string& msg);
}; };
struct SurplusState { struct SurplusState
SurplusState( GasLiftStage2& parent_, const Group& group_, {
double oil_rate_, double gas_rate_, double water_rate_, double alq_, SurplusState(GasLiftStage2& parent_,
double min_eco_grad_, const Group& group_,
double oil_target_, double gas_target_, double water_target_, double liquid_target_, Scalar oil_rate_,
std::optional<double> max_glift_, std::optional<double> max_total_gas_) : Scalar gas_rate_,
parent{parent_}, Scalar water_rate_,
group{group_}, Scalar alq_,
oil_rate{oil_rate_}, Scalar min_eco_grad_,
gas_rate{gas_rate_}, Scalar oil_target_,
water_rate{water_rate_}, Scalar gas_target_,
alq{alq_}, Scalar water_target_,
min_eco_grad{min_eco_grad_}, Scalar liquid_target_,
oil_target{oil_target_}, std::optional<Scalar> max_glift_,
gas_target{gas_target_}, std::optional<Scalar> max_total_gas_)
water_target(water_target_), : parent{parent_}
liquid_target{liquid_target_}, , group{group_}
max_glift{max_glift_}, , oil_rate{oil_rate_}
max_total_gas{max_total_gas_}, , gas_rate{gas_rate_}
it{0} , 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; GasLiftStage2 &parent;
const Group &group; const Group &group;
double oil_rate; Scalar oil_rate;
double gas_rate; Scalar gas_rate;
double water_rate; Scalar water_rate;
double alq; Scalar alq;
const double min_eco_grad; const Scalar min_eco_grad;
const double oil_target; const Scalar oil_target;
const double gas_target; const Scalar gas_target;
const double water_target; const Scalar water_target;
const double liquid_target; const Scalar liquid_target;
std::optional<double> max_glift; std::optional<Scalar> max_glift;
std::optional<double> max_total_gas; std::optional<Scalar> max_total_gas;
int it; int it;
void addOrRemoveALQincrement( void addOrRemoveALQincrement(GradMap &grad_map,
GradMap &grad_map, const std::string& well_name, bool add); const std::string& well_name,
bool add);
bool checkALQlimit(); bool checkALQlimit();
bool checkEcoGradient(const std::string& well_name, double eco_grad); bool checkEcoGradient(const std::string& well_name, Scalar eco_grad);
bool checkGasTarget(double delta_gas); bool checkGasTarget(Scalar delta_gas);
bool checkLiquidTarget(double delta_liquid); bool checkLiquidTarget(Scalar delta_liquid);
bool checkOilTarget(double delta_oil); bool checkOilTarget(Scalar delta_oil);
bool checkWaterTarget(double delta_water); bool checkWaterTarget(Scalar delta_water);
std::array<double, 4> computeDelta(const std::string& name); std::array<Scalar, 4> computeDelta(const std::string& name);
void updateRates(const std::array<double, 4>& delta); void updateRates(const std::array<Scalar, 4>& delta);
}; };
}; };

View File

@ -23,40 +23,51 @@
#include <optional> #include <optional>
#include <utility> #include <utility>
namespace Opm namespace Opm {
{
template<class Scalar>
class GasLiftWellState class GasLiftWellState
{ {
public: public:
//GasLiftWellState() { } GasLiftWellState(Scalar oil_rate,
GasLiftWellState(double oil_rate, bool oil_is_limited, bool oil_is_limited,
double gas_rate, bool gas_is_limited, Scalar gas_rate,
double alq, bool alq_is_limited, double water_rate, bool water_is_limited, std::optional<bool> increase) : bool gas_is_limited,
oil_rate_{oil_rate}, Scalar alq,
oil_is_limited_{oil_is_limited}, bool alq_is_limited,
gas_rate_{gas_rate}, Scalar water_rate,
gas_is_limited_{gas_is_limited}, bool water_is_limited,
alq_{alq}, std::optional<bool> increase)
alq_is_limited_{alq_is_limited}, : oil_rate_{oil_rate}
water_rate_{water_rate}, , oil_is_limited_{oil_is_limited}
water_is_limited_{water_is_limited}, , gas_rate_{gas_rate}
increase_{increase} , gas_is_limited_{gas_is_limited}
, 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_; }
Scalar alq() const { return alq_; }
bool alqChanged() { return increase_.has_value(); } bool alqChanged() { return increase_.has_value(); }
bool alqIsLimited() const { return alq_is_limited_; } bool alqIsLimited() const { return alq_is_limited_; }
bool gasIsLimited() const { return gas_is_limited_; } bool gasIsLimited() const { return gas_is_limited_; }
double gasRate() const { return gas_rate_; } Scalar gasRate() const { return gas_rate_; }
std::pair<double, double> getRates() { return {oil_rate_, gas_rate_}; } std::pair<Scalar, Scalar> getRates() { return {oil_rate_, gas_rate_}; }
std::optional<bool> increase() const { return increase_; } std::optional<bool> increase() const { return increase_; }
bool oilIsLimited() const { return oil_is_limited_; } bool oilIsLimited() const { return oil_is_limited_; }
double oilRate() const { return oil_rate_; } Scalar oilRate() const { return oil_rate_; }
double waterRate() const { return water_rate_; } Scalar waterRate() const { return water_rate_; }
bool waterIsLimited() const { return water_is_limited_; } bool waterIsLimited() const { return water_is_limited_; }
void update(double oil_rate, bool oil_is_limited, void update(Scalar oil_rate,
double gas_rate, bool gas_is_limited, bool oil_is_limited,
double alq, bool alq_is_limited, double water_rate, Scalar gas_rate,
double water_is_limited, bool gas_is_limited,
Scalar alq,
bool alq_is_limited,
Scalar water_rate,
Scalar water_is_limited,
bool increase) bool increase)
{ {
oil_rate_ = oil_rate; oil_rate_ = oil_rate;
@ -69,14 +80,15 @@ namespace Opm
water_is_limited_ = water_is_limited; water_is_limited_ = water_is_limited;
increase_ = increase; increase_ = increase;
} }
private: private:
double oil_rate_; Scalar oil_rate_;
bool oil_is_limited_; bool oil_is_limited_;
double gas_rate_; Scalar gas_rate_;
bool gas_is_limited_; bool gas_is_limited_;
double alq_; Scalar alq_;
bool alq_is_limited_; bool alq_is_limited_;
double water_rate_; Scalar water_rate_;
bool water_is_limited_; bool water_is_limited_;
std::optional<bool> increase_; std::optional<bool> increase_;
}; };

View File

@ -80,6 +80,7 @@ public:
using Grid = GetPropType<TypeTag, Properties::Grid>; using Grid = GetPropType<TypeTag, Properties::Grid>;
using Simulator = GetPropType<TypeTag, Properties::Simulator>; using Simulator = GetPropType<TypeTag, Properties::Simulator>;
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>; using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
using Indices = GetPropType<TypeTag, Properties::Indices>; using Indices = GetPropType<TypeTag, Properties::Indices>;
using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>; using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
@ -91,9 +92,7 @@ public:
using GLiftProdWells = typename BlackoilWellModel<TypeTag>::GLiftProdWells; using GLiftProdWells = typename BlackoilWellModel<TypeTag>::GLiftProdWells;
using GLiftWellStateMap = using GLiftWellStateMap =
typename BlackoilWellModel<TypeTag>::GLiftWellStateMap; typename BlackoilWellModel<TypeTag>::GLiftWellStateMap;
using GLiftSyncGroups = typename GasLiftSingleWellGeneric::GLiftSyncGroups; using GLiftSyncGroups = typename GasLiftSingleWellGeneric<Scalar>::GLiftSyncGroups;
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using VectorBlockType = Dune::FieldVector<Scalar, Indices::numEq>; using VectorBlockType = Dune::FieldVector<Scalar, Indices::numEq>;
using MatrixBlockType = Dune::FieldMatrix<Scalar, Indices::numEq, Indices::numEq>; using MatrixBlockType = Dune::FieldMatrix<Scalar, Indices::numEq, Indices::numEq>;

View File

@ -126,8 +126,8 @@ BOOST_AUTO_TEST_CASE(G1)
using WellState = Opm::WellState<double>; using WellState = Opm::WellState<double>;
using StdWell = Opm::StandardWell<TypeTag>; using StdWell = Opm::StandardWell<TypeTag>;
using GasLiftSingleWell = Opm::GasLiftSingleWell<TypeTag>; using GasLiftSingleWell = Opm::GasLiftSingleWell<TypeTag>;
using GasLiftGroupInfo = Opm::GasLiftGroupInfo; using GasLiftGroupInfo = Opm::GasLiftGroupInfo<double>;
using GasLiftSingleWellGeneric = Opm::GasLiftSingleWellGeneric; using GasLiftSingleWellGeneric = Opm::GasLiftSingleWellGeneric<double>;
using GLiftEclWells = typename GasLiftGroupInfo::GLiftEclWells; using GLiftEclWells = typename GasLiftGroupInfo::GLiftEclWells;
const std::string filename = "GLIFT1.DATA"; const std::string filename = "GLIFT1.DATA";
using GLiftSyncGroups = typename GasLiftSingleWellGeneric::GLiftSyncGroups; using GLiftSyncGroups = typename GasLiftSingleWellGeneric::GLiftSyncGroups;