mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Limit the other rates when a rate is limited
This commit is contained in:
parent
b42537155e
commit
6a30966500
@ -532,16 +532,21 @@ getProducerWellRates_(const Well* well, int well_index)
|
||||
|
||||
const auto controls = well->productionControls(this->summary_state_);
|
||||
Scalar oil_rate = oil_pot;
|
||||
if (controls.hasControl(Well::ProducerCMode::ORAT)) {
|
||||
oil_rate = std::min(static_cast<Scalar>(controls.oil_rate), oil_rate);
|
||||
}
|
||||
Scalar water_rate = water_pot;
|
||||
Scalar gas_rate = gas_pot;
|
||||
|
||||
if (controls.hasControl(Well::ProducerCMode::ORAT) && oil_rate > static_cast<Scalar>(controls.oil_rate)) {
|
||||
water_rate *= (static_cast<Scalar>(controls.oil_rate) / oil_rate);
|
||||
oil_rate = static_cast<Scalar>(controls.oil_rate);
|
||||
}
|
||||
|
||||
if (controls.hasControl(Well::ProducerCMode::GRAT)) {
|
||||
gas_rate = std::min(static_cast<Scalar>(controls.gas_rate), gas_rate);
|
||||
}
|
||||
Scalar water_rate = water_pot;
|
||||
if (controls.hasControl(Well::ProducerCMode::WRAT)) {
|
||||
water_rate = std::min(static_cast<Scalar>(controls.water_rate), water_rate);
|
||||
|
||||
if (controls.hasControl(Well::ProducerCMode::WRAT) && water_rate > static_cast<Scalar>(controls.water_rate)) {
|
||||
oil_rate *= (static_cast<Scalar>(controls.water_rate) / water_rate);
|
||||
water_rate = static_cast<Scalar>(controls.water_rate);
|
||||
}
|
||||
if (controls.hasControl(Well::ProducerCMode::LRAT)) {
|
||||
Scalar liquid_rate = oil_rate + water_rate;
|
||||
@ -650,12 +655,16 @@ initializeGroupRatesRecursive_(const Group& group)
|
||||
group.name(), oil_rate, gas_rate, water_rate, alq);
|
||||
}
|
||||
|
||||
if (oil_target)
|
||||
oil_rate = std::min(oil_rate, *oil_target);
|
||||
if (gas_target)
|
||||
gas_rate = std::min(gas_rate, *gas_target);
|
||||
if (water_target)
|
||||
water_rate = std::min(water_rate, *water_target);
|
||||
if (oil_target && oil_rate > *oil_target) {
|
||||
water_rate *= (*oil_target/oil_rate);
|
||||
oil_rate = *oil_target;
|
||||
}
|
||||
if (gas_target && gas_rate > *gas_target)
|
||||
gas_rate = *gas_target;
|
||||
if (water_target && water_rate > *water_target) {
|
||||
oil_rate *= (*water_target/water_rate);
|
||||
water_rate = *water_target;
|
||||
}
|
||||
if (liquid_target) {
|
||||
Scalar liquid_rate = oil_rate + water_rate;
|
||||
Scalar liquid_rate_limited = *liquid_target;
|
||||
|
@ -666,6 +666,13 @@ getRateWithLimit_(Rate rate_type, const BasicRates& rates) const
|
||||
// for why the rate was limited.
|
||||
std::optional<Rate> target_type;
|
||||
|
||||
Scalar rate2;
|
||||
if (rate_type == Rate::oil) {
|
||||
rate2 = getRate_(Rate::water, rates);
|
||||
} else {
|
||||
rate2 = getRate_(Rate::oil, rates);
|
||||
}
|
||||
|
||||
if (hasProductionControl_(rate_type)) {
|
||||
auto target = getProductionTarget_(rate_type);
|
||||
if (new_rate > target) {
|
||||
@ -675,42 +682,73 @@ getRateWithLimit_(Rate rate_type, const BasicRates& rates) const
|
||||
new_rate,
|
||||
target);
|
||||
displayDebugMessage_(msg);
|
||||
rate2 *= target/new_rate;
|
||||
new_rate = target;
|
||||
target_type = rate_type;
|
||||
target_type = rate_type;
|
||||
}
|
||||
}
|
||||
if (((rate_type == Rate::oil) || (rate_type == Rate::water)) && hasProductionControl_(Rate::liquid)) {
|
||||
Scalar rate2;
|
||||
if (((rate_type == Rate::oil) || (rate_type == Rate::water))) {
|
||||
if (rate_type == Rate::oil) {
|
||||
rate2 = getRate_(Rate::water, rates);
|
||||
if(hasProductionControl_(Rate::water)) {
|
||||
auto water_target = getProductionTarget_(Rate::water);
|
||||
if (rate2 > water_target) {
|
||||
new_rate *= (water_target / rate2);
|
||||
target_type = Rate::water;
|
||||
rate2 = water_target;
|
||||
const std::string msg = fmt::format("limiting {} rate to {} due to WRAT target: "
|
||||
"computed WRAT: {}, target WRAT: {}",
|
||||
GasLiftGroupInfo<Scalar>::rateToString(rate_type),
|
||||
new_rate,
|
||||
rate2,
|
||||
water_target);
|
||||
displayDebugMessage_(msg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rate2 = getRate_(Rate::oil, rates);
|
||||
if(hasProductionControl_(Rate::oil)) {
|
||||
auto oil_target = getProductionTarget_(Rate::oil);
|
||||
if (rate2 > oil_target) {
|
||||
new_rate *= (oil_target / rate2);
|
||||
target_type = Rate::oil;
|
||||
rate2 = oil_target;
|
||||
const std::string msg = fmt::format("limiting {} rate to {} due to ORAT target: "
|
||||
"computed ORAT: {}, target ORAT: {}",
|
||||
GasLiftGroupInfo<Scalar>::rateToString(rate_type),
|
||||
new_rate,
|
||||
rate2,
|
||||
oil_target);
|
||||
displayDebugMessage_(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: Since "new_rate" was first updated for ORAT or WRAT, see first "if"
|
||||
// statement in the method, the rate is limited due to LRAT only if
|
||||
// it becomes less than the rate limited by a WRAT or ORAT target..
|
||||
Scalar liq_rate = new_rate + rate2;
|
||||
|
||||
auto liq_target = getProductionTarget_(Rate::liquid);
|
||||
if (liq_rate > liq_target) {
|
||||
Scalar fraction = new_rate / liq_rate;
|
||||
// NOTE: since
|
||||
// fraction * liq_rate = new_rate,
|
||||
// we must have
|
||||
// fraction * liq_target < new_rate
|
||||
// since
|
||||
// liq_target < liq_rate
|
||||
// therefore new_rate will become less than it original was and
|
||||
// limited = true.
|
||||
new_rate = fraction * liq_target;
|
||||
target_type = Rate::liquid;
|
||||
const std::string msg = fmt::format("limiting {} rate to {} due to LRAT target: "
|
||||
"computed LRAT: {}, target LRAT: {}",
|
||||
GasLiftGroupInfo<Scalar>::rateToString(rate_type),
|
||||
new_rate,
|
||||
liq_rate,
|
||||
liq_target);
|
||||
displayDebugMessage_(msg);
|
||||
if(hasProductionControl_(Rate::liquid)) {
|
||||
// Note: Since "new_rate" was first updated for ORAT or WRAT, see first "if"
|
||||
// statement in the method, the rate is limited due to LRAT only if
|
||||
// it becomes less than the rate limited by a WRAT or ORAT target..
|
||||
Scalar liq_rate = new_rate + rate2;
|
||||
|
||||
auto liq_target = getProductionTarget_(Rate::liquid);
|
||||
if (liq_rate > liq_target) {
|
||||
Scalar fraction = new_rate / liq_rate;
|
||||
// NOTE: since
|
||||
// fraction * liq_rate = new_rate,
|
||||
// we must have
|
||||
// fraction * liq_target < new_rate
|
||||
// since
|
||||
// liq_target < liq_rate
|
||||
// therefore new_rate will become less than it original was and
|
||||
// limited = true.
|
||||
new_rate = fraction * liq_target;
|
||||
target_type = Rate::liquid;
|
||||
const std::string msg = fmt::format("limiting {} rate to {} due to LRAT target: "
|
||||
"computed LRAT: {}, target LRAT: {}",
|
||||
GasLiftGroupInfo<Scalar>::rateToString(rate_type),
|
||||
new_rate,
|
||||
liq_rate,
|
||||
liq_target);
|
||||
displayDebugMessage_(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Also check RESV target?
|
||||
@ -768,7 +806,7 @@ getLiquidRateWithGroupLimit_(const Scalar new_oil_rate,
|
||||
= getRateWithGroupLimit_(Rate::liquid, new_liquid_rate, liquid_rate, gr_name_dont_limit);
|
||||
bool limited = group_name != nullptr;
|
||||
if (limited) {
|
||||
Scalar oil_fraction = new_oil_rate / new_liquid_rate;
|
||||
Scalar oil_fraction = oil_rate / liquid_rate;
|
||||
Scalar delta_liquid = liquid_rate_limited - liquid_rate;
|
||||
auto limited_oil_rate = oil_rate + oil_fraction * delta_liquid;
|
||||
auto limited_water_rate = water_rate + (1.0 - oil_fraction) * delta_liquid;
|
||||
@ -862,6 +900,7 @@ getInitialRatesWithLimit_() const
|
||||
auto temp_rates = getLimitedRatesFromRates_(*rates);
|
||||
BasicRates old_rates = getWellStateRates_();
|
||||
limited_rates = updateRatesToGroupLimits_(old_rates, temp_rates);
|
||||
|
||||
initial_alq = alq;
|
||||
}
|
||||
return {limited_rates, initial_alq};
|
||||
@ -873,9 +912,10 @@ GasLiftSingleWellGeneric<Scalar>::
|
||||
getLimitedRatesFromRates_(const BasicRates& rates) const
|
||||
{
|
||||
auto [oil_rate, oil_limiting_target] = getOilRateWithLimit2_(rates);
|
||||
bool oil_is_limited = oil_limiting_target.has_value();
|
||||
auto [gas_rate, gas_is_limited] = getGasRateWithLimit_(rates);
|
||||
auto [water_rate, water_limiting_target] = getWaterRateWithLimit2_(rates);
|
||||
bool oil_is_limited = oil_limiting_target.has_value();
|
||||
|
||||
bool water_is_limited = water_limiting_target.has_value();
|
||||
return LimitedRates {oil_rate,
|
||||
gas_rate,
|
||||
@ -1447,13 +1487,16 @@ updateRatesToGroupLimits_(const BasicRates& old_rates,
|
||||
{
|
||||
LimitedRates new_rates = rates;
|
||||
auto [new_oil_rate, oil_is_limited] = getOilRateWithGroupLimit_(new_rates.oil, old_rates.oil, gr_name);
|
||||
auto mod_water_rate = new_rates.water;
|
||||
if (oil_is_limited) {
|
||||
new_rates.oil_limiting_target = Rate::oil;
|
||||
mod_water_rate *= (new_oil_rate / new_rates.oil);
|
||||
}
|
||||
auto [new_gas_rate, gas_is_limited] = getGasRateWithGroupLimit_(new_rates.gas, old_rates.gas, gr_name);
|
||||
auto [new_water_rate, water_is_limited] = getWaterRateWithGroupLimit_(new_rates.water, old_rates.water, gr_name);
|
||||
auto [new_water_rate, water_is_limited] = getWaterRateWithGroupLimit_(mod_water_rate, old_rates.water, gr_name);
|
||||
if (water_is_limited) {
|
||||
new_rates.water_limiting_target = Rate::water;
|
||||
new_oil_rate *= (new_water_rate / new_rates.water);
|
||||
}
|
||||
auto [new_oil_rate2, new_water_rate2, oil_is_limited2, water_is_limited2]
|
||||
= getLiquidRateWithGroupLimit_(new_oil_rate, old_rates.oil, new_water_rate, old_rates.water, gr_name);
|
||||
|
Loading…
Reference in New Issue
Block a user