mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Implements gas lift optimization for groups.
Extends PR #2824 to include support for GLIFTOPT (item 2, maximum lift gas supply for a group) and group production constraints. The optimization is split into two phases. First the wells are optimized separately (as in PR #2824). In this phase LIFTOPT and WLIFTOPT constraints (e.g. maxmimum lift gas injection for a well, minimum economic gradient) are considered together with well production constraints. Then, in the next phase the wells are optimized in groups. Here, the ALQ distribution from the first phase is used as a starting point. If a group has any production rate constraints, and/or a limit on its total rate of lift gas supply, lift gas is redistributed to the wells that gain the most benefit from it by considering which wells that currently has the largest weighted incremental gradient (i.e. increase in oil rate compared to increase in ALQ).
This commit is contained in:
@@ -275,7 +275,7 @@ namespace Opm
|
||||
return primary_variables_evaluation_[SFrac];
|
||||
}
|
||||
}
|
||||
else if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
||||
else if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) && compIdx == Indices::canonicalToActiveComponentIndex(FluidSystem::gasCompIdx)) {
|
||||
return primary_variables_evaluation_[GFrac];
|
||||
}
|
||||
@@ -300,7 +300,7 @@ namespace Opm
|
||||
|
||||
well_fraction -= primary_variables_evaluation_[GFrac];
|
||||
}
|
||||
|
||||
|
||||
return well_fraction;
|
||||
}
|
||||
|
||||
@@ -1115,7 +1115,7 @@ namespace Opm
|
||||
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
|
||||
F[pu.phase_pos[Oil]] = 1.0;
|
||||
|
||||
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
||||
F[pu.phase_pos[Water]] = primary_variables_[WFrac];
|
||||
F[pu.phase_pos[Oil]] -= F[pu.phase_pos[Water]];
|
||||
@@ -1213,7 +1213,7 @@ namespace Opm
|
||||
std::vector<double> F(number_of_phases_, 0.0);
|
||||
double F_solvent = 0.0;
|
||||
if ( FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) ) {
|
||||
const int oil_pos = pu.phase_pos[Oil];
|
||||
const int oil_pos = pu.phase_pos[Oil];
|
||||
F[oil_pos] = 1.0;
|
||||
|
||||
if ( FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) ) {
|
||||
@@ -1234,7 +1234,7 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
else if ( FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) ) {
|
||||
const int water_pos = pu.phase_pos[Water];
|
||||
const int water_pos = pu.phase_pos[Water];
|
||||
F[water_pos] = 1.0;
|
||||
|
||||
if ( FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) ) {
|
||||
@@ -1244,7 +1244,7 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
else if ( FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) ) {
|
||||
const int gas_pos = pu.phase_pos[Gas];
|
||||
const int gas_pos = pu.phase_pos[Gas];
|
||||
F[gas_pos] = 1.0;
|
||||
}
|
||||
|
||||
@@ -2696,19 +2696,31 @@ namespace Opm
|
||||
gliftDebug("Optimization disabled in WellState", deferred_logger);
|
||||
return false;
|
||||
}
|
||||
const int well_index = index_of_well_;
|
||||
const Well::ProducerCMode& control_mode
|
||||
= well_state.currentProductionControls()[well_index];
|
||||
if (control_mode != Well::ProducerCMode::THP ) {
|
||||
gliftDebug("Not THP control", deferred_logger);
|
||||
if (well_state.gliftCheckAlqOscillation(name())) {
|
||||
gliftDebug("further optimization skipped due to oscillation in ALQ",
|
||||
deferred_logger);
|
||||
return false;
|
||||
}
|
||||
if (this->glift_optimize_only_thp_wells) {
|
||||
const int well_index = index_of_well_;
|
||||
const Well::ProducerCMode& control_mode
|
||||
= well_state.currentProductionControls()[well_index];
|
||||
if (control_mode != Well::ProducerCMode::THP ) {
|
||||
gliftDebug("Not THP control", deferred_logger);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!checkGliftNewtonIterationIdxOk(ebos_simulator, deferred_logger)) {
|
||||
return false;
|
||||
}
|
||||
const int report_step_idx = ebos_simulator.episodeIndex();
|
||||
const Opm::Schedule& schedule = ebos_simulator.vanguard().schedule();
|
||||
const GasLiftOpt& glo = schedule.glo(report_step_idx);
|
||||
if (!glo.has_well(name())) {
|
||||
gliftDebug("Gas Lift not activated: WLIFTOPT is probably missing",
|
||||
deferred_logger);
|
||||
return false;
|
||||
}
|
||||
auto increment = glo.gaslift_increment();
|
||||
// NOTE: According to the manual: LIFTOPT, item 1, :
|
||||
// "Increment size for lift gas injection rate. Lift gas is
|
||||
@@ -2771,7 +2783,7 @@ namespace Opm
|
||||
{
|
||||
if (this->glift_debug) {
|
||||
const std::string message = fmt::format(
|
||||
" GLIFT (DEBUG) : Well {} : {}", this->name(), msg);
|
||||
" GLIFT (DEBUG) : SW : Well {} : {}", this->name(), msg);
|
||||
deferred_logger.info(message);
|
||||
}
|
||||
}
|
||||
@@ -2819,30 +2831,37 @@ namespace Opm
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
maybeDoGasLiftOptimization(
|
||||
WellState& well_state,
|
||||
const Simulator& ebos_simulator,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
gasLiftOptimizationStage1(
|
||||
WellState& well_state,
|
||||
const Simulator& ebos_simulator,
|
||||
Opm::DeferredLogger& deferred_logger,
|
||||
GLiftProdWells &prod_wells,
|
||||
GLiftOptWells &glift_wells,
|
||||
GLiftWellStateMap &glift_state_map
|
||||
//std::map<std::string, WellInterface *> &prod_wells
|
||||
) const
|
||||
{
|
||||
const auto& well = well_ecl_;
|
||||
if (well.isProducer()) {
|
||||
const auto& summary_state = ebos_simulator.vanguard().summaryState();
|
||||
const Well::ProducerCMode& current_control
|
||||
= well_state.currentProductionControls()[this->index_of_well_];
|
||||
if ( this->Base::wellHasTHPConstraints(summary_state)
|
||||
&& current_control != Well::ProducerCMode::BHP ) {
|
||||
if ( this->Base::wellHasTHPConstraints(summary_state) ) {
|
||||
if (doGasLiftOptimize(well_state, ebos_simulator, deferred_logger)) {
|
||||
const auto& controls = well.productionControls(summary_state);
|
||||
GasLiftHandler glift {
|
||||
*this, ebos_simulator, summary_state,
|
||||
deferred_logger, well_state, controls };
|
||||
glift.runOptimize();
|
||||
std::unique_ptr<GasLiftSingleWell> glift
|
||||
= std::make_unique<GasLiftSingleWell>(
|
||||
*this, ebos_simulator, summary_state,
|
||||
deferred_logger, well_state);
|
||||
auto state = glift->runOptimize();
|
||||
if (state) {
|
||||
glift_state_map.insert({this->name(), std::move(state)});
|
||||
glift_wells.insert({this->name(), std::move(glift)});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
prod_wells.insert({this->name(), this});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user