mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-12 06:55:35 -06:00
scale well rates after group switching
This commit is contained in:
parent
2dae87fb74
commit
b2341a84d6
@ -398,15 +398,15 @@ checkGroupConstraints(const Group& group,
|
|||||||
if (!group.hasInjectionControl(phase)) {
|
if (!group.hasInjectionControl(phase)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Group::InjectionCMode newControl = checkGroupInjectionConstraints(group, reportStepIdx, phase);
|
const auto& check = checkGroupInjectionConstraints(group, reportStepIdx, phase);
|
||||||
if (newControl != Group::InjectionCMode::NONE) {
|
if (check.first != Group::InjectionCMode::NONE) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (group.isProductionGroup()) {
|
if (group.isProductionGroup()) {
|
||||||
Group::ProductionCMode newControl = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger);
|
const auto& check = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger);
|
||||||
if (newControl != Group::ProductionCMode::NONE)
|
if (check.first != Group::ProductionCMode::NONE)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -420,7 +420,7 @@ checkGroupConstraints(const Group& group,
|
|||||||
return violated;
|
return violated;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::InjectionCMode
|
std::pair<Group::InjectionCMode, double>
|
||||||
BlackoilWellModelGeneric::
|
BlackoilWellModelGeneric::
|
||||||
checkGroupInjectionConstraints(const Group& group,
|
checkGroupInjectionConstraints(const Group& group,
|
||||||
const int reportStepIdx,
|
const int reportStepIdx,
|
||||||
@ -452,7 +452,10 @@ checkGroupInjectionConstraints(const Group& group,
|
|||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
|
|
||||||
if (controls.surface_max_rate < current_rate) {
|
if (controls.surface_max_rate < current_rate) {
|
||||||
return Group::InjectionCMode::RATE;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.surface_max_rate / current_rate;
|
||||||
|
return std::make_pair(Group::InjectionCMode::RATE, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -466,7 +469,10 @@ checkGroupInjectionConstraints(const Group& group,
|
|||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
|
|
||||||
if (controls.resv_max_rate < current_rate) {
|
if (controls.resv_max_rate < current_rate) {
|
||||||
return Group::InjectionCMode::RESV;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.resv_max_rate / current_rate;
|
||||||
|
return std::make_pair(Group::InjectionCMode::RESV, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,7 +494,10 @@ checkGroupInjectionConstraints(const Group& group,
|
|||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
|
|
||||||
if (controls.target_reinj_fraction*production_Rate < current_rate) {
|
if (controls.target_reinj_fraction*production_Rate < current_rate) {
|
||||||
return Group::InjectionCMode::REIN;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.target_reinj_fraction*production_Rate / current_rate;
|
||||||
|
return std::make_pair(Group::InjectionCMode::REIN, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -514,14 +523,17 @@ checkGroupInjectionConstraints(const Group& group,
|
|||||||
total_rate = comm_.sum(total_rate);
|
total_rate = comm_.sum(total_rate);
|
||||||
|
|
||||||
if (controls.target_void_fraction*voidage_rate < total_rate) {
|
if (controls.target_void_fraction*voidage_rate < total_rate) {
|
||||||
return Group::InjectionCMode::VREP;
|
double scale = 1.0;
|
||||||
|
if (total_rate > 1e-12)
|
||||||
|
scale = controls.target_void_fraction*voidage_rate / total_rate;
|
||||||
|
return std::make_pair(Group::InjectionCMode::VREP, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Group::InjectionCMode::NONE;
|
return std::make_pair(Group::InjectionCMode::NONE, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::ProductionCMode
|
std::pair<Group::ProductionCMode, double>
|
||||||
BlackoilWellModelGeneric::
|
BlackoilWellModelGeneric::
|
||||||
checkGroupProductionConstraints(const Group& group,
|
checkGroupProductionConstraints(const Group& group,
|
||||||
const int reportStepIdx,
|
const int reportStepIdx,
|
||||||
@ -543,7 +555,10 @@ checkGroupProductionConstraints(const Group& group,
|
|||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
|
|
||||||
if (controls.oil_target < current_rate ) {
|
if (controls.oil_target < current_rate ) {
|
||||||
return Group::ProductionCMode::ORAT;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.oil_target / current_rate;
|
||||||
|
return std::make_pair(Group::ProductionCMode::ORAT, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,7 +575,10 @@ checkGroupProductionConstraints(const Group& group,
|
|||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
|
|
||||||
if (controls.water_target < current_rate ) {
|
if (controls.water_target < current_rate ) {
|
||||||
return Group::ProductionCMode::WRAT;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.water_target / current_rate;
|
||||||
|
return std::make_pair(Group::ProductionCMode::WRAT, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -574,7 +592,10 @@ checkGroupProductionConstraints(const Group& group,
|
|||||||
// sum over all nodes
|
// sum over all nodes
|
||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
if (controls.gas_target < current_rate ) {
|
if (controls.gas_target < current_rate ) {
|
||||||
return Group::ProductionCMode::GRAT;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.gas_target / current_rate;
|
||||||
|
return std::make_pair(Group::ProductionCMode::GRAT, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,7 +611,10 @@ checkGroupProductionConstraints(const Group& group,
|
|||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
|
|
||||||
if (controls.liquid_target < current_rate ) {
|
if (controls.liquid_target < current_rate ) {
|
||||||
return Group::ProductionCMode::LRAT;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.liquid_target / current_rate;
|
||||||
|
return std::make_pair(Group::ProductionCMode::LRAT, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -612,7 +636,10 @@ checkGroupProductionConstraints(const Group& group,
|
|||||||
current_rate = comm_.sum(current_rate);
|
current_rate = comm_.sum(current_rate);
|
||||||
|
|
||||||
if (controls.resv_target < current_rate ) {
|
if (controls.resv_target < current_rate ) {
|
||||||
return Group::ProductionCMode::RESV;
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = controls.resv_target / current_rate;
|
||||||
|
return std::make_pair(Group::ProductionCMode::RESV, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,7 +647,7 @@ checkGroupProductionConstraints(const Group& group,
|
|||||||
{
|
{
|
||||||
OPM_DEFLOG_THROW(std::runtime_error, "Group " + group.name() + "PRBL control for production groups not implemented", deferred_logger);
|
OPM_DEFLOG_THROW(std::runtime_error, "Group " + group.name() + "PRBL control for production groups not implemented", deferred_logger);
|
||||||
}
|
}
|
||||||
return Group::ProductionCMode::NONE;
|
return std::make_pair(Group::ProductionCMode::NONE, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -808,6 +835,7 @@ checkGroupHigherConstraints(const Group& group,
|
|||||||
if (changed.first) {
|
if (changed.first) {
|
||||||
switched_groups.insert(group.name());
|
switched_groups.insert(group.name());
|
||||||
actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, deferred_logger);
|
actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, deferred_logger);
|
||||||
|
WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ true, this->groupState(), this->wellState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -845,6 +873,7 @@ checkGroupHigherConstraints(const Group& group,
|
|||||||
switched_groups.insert(group.name());
|
switched_groups.insert(group.name());
|
||||||
const auto exceed_action = group.productionControls(summaryState_).exceed_action;
|
const auto exceed_action = group.productionControls(summaryState_).exceed_action;
|
||||||
actionOnBrokenConstraints(group, exceed_action, Group::ProductionCMode::FLD, deferred_logger);
|
actionOnBrokenConstraints(group, exceed_action, Group::ProductionCMode::FLD, deferred_logger);
|
||||||
|
WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -870,21 +899,23 @@ updateGroupIndividualControl(const Group& group,
|
|||||||
if (!group.hasInjectionControl(phase)) {
|
if (!group.hasInjectionControl(phase)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Group::InjectionCMode newControl = checkGroupInjectionConstraints(group, reportStepIdx, phase);
|
const auto& changed = checkGroupInjectionConstraints(group, reportStepIdx, phase);
|
||||||
if (newControl != Group::InjectionCMode::NONE)
|
if (changed.first != Group::InjectionCMode::NONE)
|
||||||
{
|
{
|
||||||
switched_groups.insert(group.name());
|
switched_groups.insert(group.name());
|
||||||
actionOnBrokenConstraints(group, newControl, phase, deferred_logger);
|
actionOnBrokenConstraints(group, changed.first, phase, deferred_logger);
|
||||||
|
WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!skip && group.isProductionGroup()) {
|
if (!skip && group.isProductionGroup()) {
|
||||||
Group::ProductionCMode newControl = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger);
|
const auto& changed = checkGroupProductionConstraints(group, reportStepIdx, deferred_logger);
|
||||||
const auto controls = group.productionControls(summaryState_);
|
const auto controls = group.productionControls(summaryState_);
|
||||||
if (newControl != Group::ProductionCMode::NONE)
|
if (changed.first != Group::ProductionCMode::NONE)
|
||||||
{
|
{
|
||||||
switched_groups.insert(group.name());
|
switched_groups.insert(group.name());
|
||||||
actionOnBrokenConstraints(group, controls.exceed_action, newControl, deferred_logger);
|
actionOnBrokenConstraints(group, controls.exceed_action, changed.first, deferred_logger);
|
||||||
|
WellGroupHelpers::updateWellRatesFromGroupTargetScale(changed.second, group, schedule(), reportStepIdx, /* isInjector */ false, this->groupState(), this->wellState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,10 +286,10 @@ protected:
|
|||||||
const int reportStepIdx,
|
const int reportStepIdx,
|
||||||
DeferredLogger& deferred_logger) const;
|
DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
Group::InjectionCMode checkGroupInjectionConstraints(const Group& group,
|
std::pair<Group::InjectionCMode, double> checkGroupInjectionConstraints(const Group& group,
|
||||||
const int reportStepIdx,
|
const int reportStepIdx,
|
||||||
const Phase& phase) const;
|
const Phase& phase) const;
|
||||||
Group::ProductionCMode checkGroupProductionConstraints(const Group& group,
|
std::pair<Group::ProductionCMode, double> checkGroupProductionConstraints(const Group& group,
|
||||||
const int reportStepIdx,
|
const int reportStepIdx,
|
||||||
DeferredLogger& deferred_logger) const;
|
DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
|
@ -423,6 +423,76 @@ namespace WellGroupHelpers
|
|||||||
group_state.update_production_reduction_rates(group.name(), groupTargetReduction);
|
group_state.update_production_reduction_rates(group.name(), groupTargetReduction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateWellRatesFromGroupTargetScale(const double scale,
|
||||||
|
const Group& group,
|
||||||
|
const Schedule& schedule,
|
||||||
|
const int reportStepIdx,
|
||||||
|
bool isInjector,
|
||||||
|
const GroupState& group_state,
|
||||||
|
WellState& wellState) {
|
||||||
|
for (const std::string& groupName : group.groups()) {
|
||||||
|
bool individual_control = false;
|
||||||
|
if (isInjector) {
|
||||||
|
const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS};
|
||||||
|
for (Phase phase : all) {
|
||||||
|
const Group::InjectionCMode& currentGroupControl
|
||||||
|
= group_state.injection_control(groupName, phase);
|
||||||
|
individual_control = individual_control || (currentGroupControl != Group::InjectionCMode::FLD
|
||||||
|
&& currentGroupControl != Group::InjectionCMode::NONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const Group::ProductionCMode& currentGroupControl = group_state.production_control(groupName);
|
||||||
|
individual_control = (currentGroupControl != Group::ProductionCMode::FLD
|
||||||
|
&& currentGroupControl != Group::ProductionCMode::NONE);
|
||||||
|
}
|
||||||
|
if (!individual_control) {
|
||||||
|
const Group& groupTmp = schedule.getGroup(groupName, reportStepIdx);
|
||||||
|
updateWellRatesFromGroupTargetScale(scale, groupTmp, schedule, reportStepIdx, isInjector, group_state, wellState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int np = wellState.numPhases();
|
||||||
|
for (const std::string& wellName : group.wells()) {
|
||||||
|
const auto& wellTmp = schedule.getWell(wellName, reportStepIdx);
|
||||||
|
|
||||||
|
if (wellTmp.isProducer() && isInjector)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (wellTmp.isInjector() && !isInjector)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (wellTmp.getStatus() == Well::Status::SHUT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto& end = wellState.wellMap().end();
|
||||||
|
const auto& it = wellState.wellMap().find(wellName);
|
||||||
|
if (it == end) // the well is not found
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int well_index = it->second[0];
|
||||||
|
|
||||||
|
if (! wellState.wellIsOwned(well_index, wellName) ) // Only sum once
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scale rates
|
||||||
|
if (isInjector) {
|
||||||
|
if (wellState.currentInjectionControl(well_index) == Well::InjectorCMode::GRUP)
|
||||||
|
for (int phase = 0; phase < np; phase++) {
|
||||||
|
wellState.wellRates(well_index)[phase] *= scale;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (wellState.currentProductionControl(well_index) == Well::ProducerCMode::GRUP)
|
||||||
|
for (int phase = 0; phase < np; phase++) {
|
||||||
|
wellState.wellRates(well_index)[phase] *= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void updateVREPForGroups(const Group& group,
|
void updateVREPForGroups(const Group& group,
|
||||||
const Schedule& schedule,
|
const Schedule& schedule,
|
||||||
@ -1100,7 +1170,10 @@ namespace WellGroupHelpers
|
|||||||
}
|
}
|
||||||
// Avoid negative target rates comming from too large local reductions.
|
// Avoid negative target rates comming from too large local reductions.
|
||||||
const double target_rate = std::max(1e-12, target / efficiencyFactorInclGroup);
|
const double target_rate = std::max(1e-12, target / efficiencyFactorInclGroup);
|
||||||
return std::make_pair(current_rate > target_rate, target_rate / current_rate);
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = target_rate / current_rate;
|
||||||
|
return std::make_pair(current_rate > target_rate, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool, double> checkGroupConstraintsInj(const std::string& name,
|
std::pair<bool, double> checkGroupConstraintsInj(const std::string& name,
|
||||||
@ -1224,7 +1297,10 @@ namespace WellGroupHelpers
|
|||||||
}
|
}
|
||||||
// Avoid negative target rates comming from too large local reductions.
|
// Avoid negative target rates comming from too large local reductions.
|
||||||
const double target_rate = std::max(1e-12, target / efficiencyFactorInclGroup);
|
const double target_rate = std::max(1e-12, target / efficiencyFactorInclGroup);
|
||||||
return std::make_pair(current_rate > target_rate, target_rate / current_rate);
|
double scale = 1.0;
|
||||||
|
if (current_rate > 1e-12)
|
||||||
|
scale = target_rate / current_rate;
|
||||||
|
return std::make_pair(current_rate > target_rate, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Comm>
|
template <class Comm>
|
||||||
|
@ -158,6 +158,14 @@ namespace WellGroupHelpers
|
|||||||
WellState& wellState,
|
WellState& wellState,
|
||||||
GroupState& group_state);
|
GroupState& group_state);
|
||||||
|
|
||||||
|
void updateWellRatesFromGroupTargetScale(const double scale,
|
||||||
|
const Group& group,
|
||||||
|
const Schedule& schedule,
|
||||||
|
const int reportStepIdx,
|
||||||
|
bool isInjector,
|
||||||
|
const GroupState& group_state,
|
||||||
|
WellState& wellState);
|
||||||
|
|
||||||
void updateREINForGroups(const Group& group,
|
void updateREINForGroups(const Group& group,
|
||||||
const Schedule& schedule,
|
const Schedule& schedule,
|
||||||
const int reportStepIdx,
|
const int reportStepIdx,
|
||||||
|
Loading…
Reference in New Issue
Block a user