47class GasLiftSingleWellGeneric :
public GasLiftCommon<Scalar, IndexTraits>
50 static constexpr int Water = IndexTraits::waterPhaseIdx;
51 static constexpr int Oil = IndexTraits::oilPhaseIdx;
52 static constexpr int Gas = IndexTraits::gasPhaseIdx;
53 static constexpr int NUM_PHASES = 3;
54 static constexpr Scalar ALQ_EPSILON = 1e-8;
57 using GLiftSyncGroups = std::set<int>;
58 using Rate =
typename GasLiftGroupInfo<Scalar, IndexTraits>::Rate;
59 using MessageType =
typename GasLiftCommon<Scalar, IndexTraits>::MessageType;
64 GradInfo(Scalar grad_,
71 Scalar new_water_rate_,
72 Scalar new_water_pot_,
73 bool water_is_limited_,
78 , new_oil_rate{new_oil_rate_}
79 , new_oil_pot{new_oil_pot_}
80 , oil_is_limited{oil_is_limited_}
81 , new_gas_rate{new_gas_rate_}
82 , new_gas_pot{new_gas_pot_}
83 , gas_is_limited{gas_is_limited_}
84 , new_water_rate{new_water_rate_}
85 , new_water_pot{new_water_pot_}
86 , water_is_limited{water_is_limited_}
88 , alq_is_limited{alq_is_limited_}
99 Scalar new_water_rate;
100 Scalar new_water_pot;
101 bool water_is_limited;
107 const std::string& name()
const {
return well_name_; }
110 const std::string& gr_name_dont_limit,
112 bool debug_output =
true)
const;
114 std::unique_ptr<GasLiftWellState<Scalar>> runOptimize(
const int iteration_idx);
116 std::pair<Scalar, bool> wellTestALQ();
124 const Well& ecl_well,
125 const SummaryState& summary_state,
127 const Schedule& schedule,
128 const int report_step_idx,
129 GLiftSyncGroups& sync_groups,
130 const Parallel::Communication& comm,
133 struct LimitedRatesAndBhp;
136 RatesAndBhp(
const RatesAndBhp& rates) :
141 bhp_is_limited{rates.bhp_is_limited}
144 RatesAndBhp(Scalar oil_,
148 bool bhp_is_limited_)
153 , bhp_is_limited{bhp_is_limited_}
156 RatesAndBhp& operator=(
const RatesAndBhp& rates)
162 bhp_is_limited = rates.bhp_is_limited;
171 Scalar operator[](Rate rate_type)
const
181 return this->oil + this->water;
183 throw std::runtime_error(
"This should not happen");
187 Scalar oil, gas, water, bhp;
191 struct LimitedRatesAndBhp :
public RatesAndBhp
193 enum class LimitType {well, group, none};
194 LimitedRatesAndBhp(Scalar oil_,
201 bool oil_is_limited_,
202 bool gas_is_limited_,
203 bool water_is_limited_,
204 bool bhp_is_limited_)
205 : RatesAndBhp(oil_, gas_, water_, bhp_, bhp_is_limited_)
208 , water_pot(water_pot_)
209 , oil_is_limited{oil_is_limited_}
210 , gas_is_limited{gas_is_limited_}
211 , water_is_limited{water_is_limited_}
213 set_initial_limit_type_();
216 LimitedRatesAndBhp(
const RatesAndBhp& rates,
220 bool oil_is_limited_,
221 bool gas_is_limited_,
222 bool water_is_limited_)
226 , water_pot(water_pot_)
227 , oil_is_limited{oil_is_limited_}
228 , gas_is_limited{gas_is_limited_}
229 , water_is_limited{water_is_limited_}
231 set_initial_limit_type_();
236 return oil_is_limited || gas_is_limited || water_is_limited;
241 LimitType limit_type;
247 bool water_is_limited;
250 void set_initial_limit_type_()
252 limit_type = limited() ? LimitType::well : LimitType::none;
258 OptimizeState( GasLiftSingleWellGeneric& parent_,
bool increase_ )
260 , increase{increase_}
262 , stop_iteration{
false}
266 GasLiftSingleWellGeneric& parent;
272 std::pair<std::optional<Scalar>,
bool> addOrSubtractAlqIncrement(Scalar alq);
273 Scalar calcEcoGradient(Scalar oil_rate,
276 Scalar new_gas_rate);
278 bool checkAlqOutsideLimits(Scalar alq, Scalar oil_rate);
279 bool checkEcoGradient(Scalar gradient);
280 bool checkOilRateExceedsTarget(Scalar oil_rate);
283 void debugShowIterationInfo(Scalar alq);
285 Scalar getBhpWithLimit();
287 void warn_(
const std::string& msg) { parent.displayWarning_(msg); }
290 bool checkGroupALQrateExceeded(Scalar delta_alq,
291 const std::string& gr_name_dont_limit =
"")
const;
292 bool checkGroupTotalRateExceeded(Scalar delta_alq,
293 Scalar delta_gas_rate,
294 const std::string& gr_name_dont_limit =
"")
const;
296 std::pair<std::optional<Scalar>,
bool>
297 addOrSubtractAlqIncrement_(Scalar alq,
bool increase)
const;
299 Scalar calcEcoGradient_(Scalar oil_rate, Scalar new_oil_rate,
300 Scalar gas_rate, Scalar new_gas_rate,
bool increase)
const;
302 bool checkALQequal_(Scalar alq1, Scalar alq2)
const;
304 bool checkGroupTargetsViolated(
const RatesAndBhp& rates,
306 bool checkInitialALQmodified_(Scalar alq, Scalar initial_alq)
const;
308 virtual bool checkThpControl_()
const = 0;
309 virtual std::optional<Scalar > computeBhpAtThpLimit_(Scalar alq, Scalar current_bhp,
310 bool debug_output =
true)
const = 0;
312 std::pair<std::optional<Scalar>,Scalar>
313 computeConvergedBhpAtThpLimitByMaybeIncreasingALQ_()
const;
315 std::pair<std::optional<RatesAndBhp>,Scalar>
316 computeInitialWellRates_()
const;
318 std::optional<LimitedRatesAndBhp>
319 computeLimitedWellRatesWithALQ_(Scalar alq, Scalar bhp)
const;
323 bool debug_output =
true)
const = 0;
325 std::optional<RatesAndBhp> computeWellRatesWithALQ_(Scalar alq, Scalar bhp)
const;
327 void debugCheckNegativeGradient_(Scalar grad, Scalar alq, Scalar new_alq,
328 Scalar oil_rate, Scalar new_oil_rate,
329 Scalar gas_rate, Scalar new_gas_rate,
330 bool increase)
const;
332 void debugPrintWellStateRates()
const;
333 void debugShowAlqIncreaseDecreaseCounts_();
334 void debugShowBhpAlqTable_();
336 void debugShowProducerControlMode()
const;
337 void debugShowStartIteration_(Scalar alq,
bool increase, Scalar oil_rate);
338 void debugShowTargets_();
339 void displayDebugMessage_(
const std::string& msg)
const override;
340 void displayWarning_(
const std::string& warning);
342 std::pair<Scalar, bool> getBhpWithLimit_(Scalar bhp)
const;
343 std::pair<Scalar, bool> getGasRateWithGroupLimit_(Scalar new_gas_rate,
345 const std::string& gr_name_dont_limit)
const;
347 std::pair<std::optional<LimitedRatesAndBhp>,Scalar >
348 getInitialRatesWithLimit_()
const;
353 Scalar getProductionTarget_(Rate rate)
const;
354 Scalar getRate_(Rate rate_type,
const RatesAndBhp& rates)
const;
356 std::pair<Scalar, std::optional<Rate>>
357 getRateWithLimit_(Rate rate_type,
const RatesAndBhp& rates)
const;
359 std::tuple<Scalar, const std::string*>
360 getRateWithGroupLimit_(Rate rate_type,
361 const Scalar new_rate,
362 const Scalar old_rate,
363 const std::string& gr_name_dont_limit)
const;
366 bool hasProductionControl_(Rate rate)
const;
368 std::pair<LimitedRatesAndBhp, Scalar>
369 increaseALQtoPositiveOilRate_(Scalar alq,
372 std::pair<LimitedRatesAndBhp, Scalar>
373 increaseALQtoMinALQ_(Scalar alq,
376 void logSuccess_(Scalar alq,
377 const int iteration_idx);
379 std::pair<LimitedRatesAndBhp, Scalar>
382 bool increase)
const;
384 std::pair<LimitedRatesAndBhp, Scalar>
385 reduceALQtoGroupAlqLimits_(Scalar alq,
388 std::pair<LimitedRatesAndBhp, Scalar>
389 reduceALQtoGroupTarget(Scalar alq,
392 std::pair<LimitedRatesAndBhp, Scalar>
393 reduceALQtoWellTarget_(Scalar alq,
396 std::unique_ptr<GasLiftWellState<Scalar>> runOptimize1_();
397 std::unique_ptr<GasLiftWellState<Scalar>> runOptimize2_();
398 std::unique_ptr<GasLiftWellState<Scalar>> runOptimizeLoop_(
bool increase);
400 void setAlqMinRate_(
const GasLiftWell& well);
401 std::unique_ptr<GasLiftWellState<Scalar>> tryIncreaseLiftGas_();
402 std::unique_ptr<GasLiftWellState<Scalar>> tryDecreaseLiftGas_();
406 Scalar delta_alq)
const;
409 updateRatesToGroupLimits_(
const RatesAndBhp& old_rates,
411 const std::string& gr_name =
"")
const;
413 void updateWellStateAlqFixedValue_(
const GasLiftWell& well);
414 bool useFixedAlq_(
const GasLiftWell& well);
416 void debugInfoGroupRatesExceedTarget(Rate rate_type,
417 const std::string& gr_name,
419 Scalar target)
const;
420 void warnMaxIterationsExceeded_();
422 const Well& ecl_well_;
423 const SummaryState& summary_state_;
425 GLiftSyncGroups& sync_groups_;
426 const WellProductionControls controls_;
443 std::string well_name_;
445 const GasLiftWell* gl_well_;
448 bool debug_limit_increase_decrease_;
449 bool debug_abort_if_decrease_and_oil_is_limited_ =
false;
450 bool debug_abort_if_increase_and_gas_is_limited_ =
false;