mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Handle guide-rate based well constraints from groups.
This commit is contained in:
parent
202235abe0
commit
27f62399f5
@ -348,7 +348,9 @@ namespace Opm {
|
||||
// xw to update Well State
|
||||
void recoverWellSolutionAndUpdateWellState(const BVector& x);
|
||||
|
||||
void updateWellControls(Opm::DeferredLogger& deferred_logger, const bool checkGroupControl, const bool checkCurrentGroupControl);
|
||||
void updateWellControls(Opm::DeferredLogger& deferred_logger, const bool checkGroupControls);
|
||||
|
||||
void updateAndCommunicateGroupData();
|
||||
|
||||
// setting the well_solutions_ based on well_state.
|
||||
void updatePrimaryVariables(Opm::DeferredLogger& deferred_logger);
|
||||
@ -421,7 +423,10 @@ namespace Opm {
|
||||
|
||||
const Well& getWellEcl(const std::string& well_name) const;
|
||||
|
||||
void checkGroupConstraints(const Group& group, const bool checkCurrentControl, Opm::DeferredLogger& deferred_logger);
|
||||
void updateGroupIndividualControls(Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups);
|
||||
void checkGroupConstraints(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups);
|
||||
void updateGroupHigherControls(Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups);
|
||||
void checkGroupHigherConstraints(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups);
|
||||
|
||||
void actionOnBrokenConstraints(const Group& group, const Group::ExceedAction& exceed_action, const Group::ProductionCMode& newControl, const int reportStepIdx, Opm::DeferredLogger& deferred_logger);
|
||||
|
||||
|
@ -381,7 +381,7 @@ namespace Opm {
|
||||
|
||||
//compute well guideRates
|
||||
const auto& comm = ebosSimulator_.vanguard().grid().comm();
|
||||
wellGroupHelpers::updateGuideRatesForWells(schedule(), phase_usage_, reportStepIdx, simulationTime, well_state_, comm, guideRate_.get());
|
||||
wellGroupHelpers::updateGuideRatesForWells(schedule(), phase_usage_, reportStepIdx, simulationTime, well_state_, comm, guideRate_.get());
|
||||
}
|
||||
|
||||
|
||||
@ -820,11 +820,7 @@ namespace Opm {
|
||||
calculateExplicitQuantities(local_deferredLogger);
|
||||
prepareTimeStep(local_deferredLogger);
|
||||
}
|
||||
// check the current group control in the beginning of an episode for the first two iterations. The first itertion is needed for changes in group/well controls and closing of wells etc.
|
||||
// a second check is needed for REIN and VREP controls since they depend on results from other wells.
|
||||
// This check can probably be made more sofisticated, but this simple rule seems to work
|
||||
bool checkCurrentGroupControls = (report_step_starts_ && iterationIdx < 2);
|
||||
updateWellControls(local_deferredLogger, /*allow for switching to group controls*/true, checkCurrentGroupControls);
|
||||
updateWellControls(local_deferredLogger, /* check group controls */ true);
|
||||
|
||||
// Set the well primary variables based on the value of well solutions
|
||||
initPrimaryVariablesEvaluation();
|
||||
@ -1065,7 +1061,7 @@ namespace Opm {
|
||||
// are active wells anywhere in the global domain.
|
||||
if( wellsActive() )
|
||||
{
|
||||
updateWellControls(deferred_logger, /*don't switch group controls*/false, /*don't check current group controls*/false);
|
||||
updateWellControls(deferred_logger, /*don't switch group controls*/false);
|
||||
initPrimaryVariablesEvaluation();
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
@ -1162,41 +1158,80 @@ namespace Opm {
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
updateWellControls(Opm::DeferredLogger& deferred_logger, const bool checkGroupControl, const bool checkCurrentGroupControl)
|
||||
updateWellControls(Opm::DeferredLogger& deferred_logger, const bool checkGroupControls)
|
||||
{
|
||||
// Even if there are no wells active locally, we cannot
|
||||
// return as the DeferredLogger uses global communication.
|
||||
// For no well active globally we simply return.
|
||||
if( !wellsActive() ) return ;
|
||||
|
||||
updateAndCommunicateGroupData();
|
||||
|
||||
std::set<std::string> switched_wells;
|
||||
std::set<std::string> switched_groups;
|
||||
|
||||
if (checkGroupControls) {
|
||||
// Check group individual constraints.
|
||||
updateGroupIndividualControls(deferred_logger, switched_groups);
|
||||
|
||||
// Check group's constraints from higher levels.
|
||||
updateGroupHigherControls(deferred_logger, switched_groups);
|
||||
|
||||
updateAndCommunicateGroupData();
|
||||
|
||||
// Check wells' group constraints and communicate.
|
||||
for (const auto& well : well_container_) {
|
||||
const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Group;
|
||||
const bool changed = well->updateWellControl(ebosSimulator_, mode, well_state_, deferred_logger);
|
||||
if (changed) {
|
||||
switched_wells.insert(well->name());
|
||||
}
|
||||
}
|
||||
updateAndCommunicateGroupData();
|
||||
}
|
||||
|
||||
// Check individual well constraints and communicate.
|
||||
for (const auto& well : well_container_) {
|
||||
if (switched_wells.count(well->name())) {
|
||||
continue;
|
||||
}
|
||||
const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
|
||||
well->updateWellControl(ebosSimulator_, mode, well_state_, deferred_logger);
|
||||
}
|
||||
updateAndCommunicateGroupData();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
updateAndCommunicateGroupData()
|
||||
{
|
||||
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
||||
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
|
||||
|
||||
// update group controls
|
||||
if (checkGroupControl) {
|
||||
checkGroupConstraints(fieldGroup, checkCurrentGroupControl, deferred_logger);
|
||||
}
|
||||
|
||||
for (const auto& well : well_container_) {
|
||||
well->updateWellControl(ebosSimulator_, well_state_, deferred_logger);
|
||||
}
|
||||
|
||||
const int nupcol = schedule().getNupcol(reportStepIdx);
|
||||
const int iterationIdx = ebosSimulator_.model().newtonMethod().numIterations();
|
||||
|
||||
// This builds some necessary lookup structures, so it must be called
|
||||
// before we copy to well_state_nupcol_.
|
||||
const auto& comm = ebosSimulator_.vanguard().grid().comm();
|
||||
well_state_.updateGlobalIsGrup(schedule(), reportStepIdx, comm);
|
||||
|
||||
if (iterationIdx < nupcol) {
|
||||
well_state_nupcol_ = well_state_;
|
||||
}
|
||||
|
||||
// the group target reduction rates needs to be update since wells may have swicthed to/from GRUP control
|
||||
// Currently the group targer reduction does not honor NUPCOL
|
||||
// Currently the group target reduction does not honor NUPCOL. TODO: is that true?
|
||||
std::vector<double> groupTargetReduction(numPhases(), 0.0);
|
||||
wellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ false, phase_usage_, well_state_nupcol_, well_state_, groupTargetReduction);
|
||||
std::vector<double> groupTargetReductionInj(numPhases(), 0.0);
|
||||
wellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ true, phase_usage_, well_state_nupcol_, well_state_, groupTargetReductionInj);
|
||||
|
||||
const auto& comm = ebosSimulator_.vanguard().grid().comm();
|
||||
well_state_.updateGlobalIsGrup(schedule(), reportStepIdx, comm);
|
||||
|
||||
const double simulationTime = ebosSimulator_.time();
|
||||
std::vector<double> pot(numPhases(), 0.0);
|
||||
wellGroupHelpers::updateGuideRateForGroups(fieldGroup, schedule(), phase_usage_, reportStepIdx, simulationTime, /*isInjector*/ false, well_state_, comm, guideRate_.get(), pot);
|
||||
@ -1268,7 +1303,7 @@ namespace Opm {
|
||||
summaryConfig.hasSummaryKey( "WGPP:" + well->name())) && well->isProducer());
|
||||
|
||||
const Well& eclWell = well->wellEcl();
|
||||
bool needPotentialsForGuideRate = eclWell.getGuideRatePhase() == Well::GuideRateTarget::UNDEFINED;
|
||||
bool needPotentialsForGuideRate = true;//eclWell.getGuideRatePhase() == Well::GuideRateTarget::UNDEFINED;
|
||||
if (write_restart_file || needed_for_summary || needPotentialsForGuideRate)
|
||||
{
|
||||
std::vector<double> potentials;
|
||||
@ -1692,17 +1727,35 @@ namespace Opm {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
checkGroupConstraints(const Group& group, const bool checkCurrentControl, Opm::DeferredLogger& deferred_logger) {
|
||||
updateGroupIndividualControls(Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups)
|
||||
{
|
||||
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
||||
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
|
||||
checkGroupConstraints(fieldGroup, deferred_logger, switched_groups);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
checkGroupConstraints(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups) {
|
||||
|
||||
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
||||
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
|
||||
const auto& comm = ebosSimulator_.vanguard().grid().comm();
|
||||
auto& well_state = well_state_;
|
||||
|
||||
if (group.isInjectionGroup())
|
||||
const bool skip = switched_groups.count(group.name());
|
||||
|
||||
if (!skip && group.isInjectionGroup())
|
||||
{
|
||||
|
||||
const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS};
|
||||
@ -1725,7 +1778,7 @@ namespace Opm {
|
||||
|
||||
if (controls.has_control(Group::InjectionCMode::RATE))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::InjectionCMode::RATE)
|
||||
if (currentControl != Group::InjectionCMode::RATE)
|
||||
{
|
||||
double current_rate = 0.0;
|
||||
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true);
|
||||
@ -1734,13 +1787,14 @@ namespace Opm {
|
||||
current_rate = comm.sum(current_rate);
|
||||
|
||||
if (controls.surface_max_rate < current_rate) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, Group::InjectionCMode::RATE, phase, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controls.has_control(Group::InjectionCMode::RESV))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::InjectionCMode::RESV)
|
||||
if (currentControl != Group::InjectionCMode::RESV)
|
||||
{
|
||||
double current_rate = 0.0;
|
||||
current_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true);
|
||||
@ -1748,13 +1802,14 @@ namespace Opm {
|
||||
current_rate = comm.sum(current_rate);
|
||||
|
||||
if (controls.resv_max_rate < current_rate) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, Group::InjectionCMode::RESV, phase, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controls.has_control(Group::InjectionCMode::REIN))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::InjectionCMode::REIN)
|
||||
if (currentControl != Group::InjectionCMode::REIN)
|
||||
{
|
||||
double production_Rate = 0.0;
|
||||
const Group& groupRein = schedule().getGroup(controls.reinj_group, reportStepIdx);
|
||||
@ -1770,13 +1825,14 @@ namespace Opm {
|
||||
current_rate = comm.sum(current_rate);
|
||||
|
||||
if (controls.target_reinj_fraction*production_Rate < current_rate) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, Group::InjectionCMode::REIN, phase,reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controls.has_control(Group::InjectionCMode::VREP))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::InjectionCMode::VREP)
|
||||
if (currentControl != Group::InjectionCMode::VREP)
|
||||
{
|
||||
double voidage_rate = 0.0;
|
||||
const Group& groupVoidage = schedule().getGroup(controls.voidage_group, reportStepIdx);
|
||||
@ -1796,6 +1852,7 @@ namespace Opm {
|
||||
total_rate = comm.sum(total_rate);
|
||||
|
||||
if (controls.target_void_fraction*voidage_rate < total_rate) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, Group::InjectionCMode::VREP, phase, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
@ -1838,13 +1895,13 @@ namespace Opm {
|
||||
}
|
||||
}
|
||||
|
||||
if (group.isProductionGroup()) {
|
||||
if (!skip && group.isProductionGroup()) {
|
||||
const auto controls = group.productionControls(summaryState);
|
||||
const Group::ProductionCMode& currentControl = well_state.currentProductionGroupControl(group.name());
|
||||
|
||||
if (group.has_control(Group::ProductionCMode::ORAT))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::ProductionCMode::ORAT)
|
||||
if (currentControl != Group::ProductionCMode::ORAT)
|
||||
{
|
||||
double current_rate = 0.0;
|
||||
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], false);
|
||||
@ -1853,6 +1910,7 @@ namespace Opm {
|
||||
current_rate = comm.sum(current_rate);
|
||||
|
||||
if (controls.oil_target < current_rate ) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, controls.exceed_action, Group::ProductionCMode::ORAT, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
@ -1860,7 +1918,7 @@ namespace Opm {
|
||||
|
||||
if (group.has_control(Group::ProductionCMode::WRAT))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::ProductionCMode::WRAT)
|
||||
if (currentControl != Group::ProductionCMode::WRAT)
|
||||
{
|
||||
|
||||
double current_rate = 0.0;
|
||||
@ -1870,13 +1928,14 @@ namespace Opm {
|
||||
current_rate = comm.sum(current_rate);
|
||||
|
||||
if (controls.water_target < current_rate ) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, controls.exceed_action, Group::ProductionCMode::WRAT, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (group.has_control(Group::ProductionCMode::GRAT))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::ProductionCMode::GRAT)
|
||||
if (currentControl != Group::ProductionCMode::GRAT)
|
||||
{
|
||||
double current_rate = 0.0;
|
||||
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Vapour], false);
|
||||
@ -1884,13 +1943,14 @@ namespace Opm {
|
||||
// sum over all nodes
|
||||
current_rate = comm.sum(current_rate);
|
||||
if (controls.gas_target < current_rate ) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, controls.exceed_action, Group::ProductionCMode::GRAT, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (group.has_control(Group::ProductionCMode::LRAT))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::ProductionCMode::LRAT)
|
||||
if (currentControl != Group::ProductionCMode::LRAT)
|
||||
{
|
||||
double current_rate = 0.0;
|
||||
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], false);
|
||||
@ -1900,6 +1960,7 @@ namespace Opm {
|
||||
current_rate = comm.sum(current_rate);
|
||||
|
||||
if (controls.liquid_target < current_rate ) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, controls.exceed_action, Group::ProductionCMode::LRAT, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
@ -1912,7 +1973,7 @@ namespace Opm {
|
||||
}
|
||||
if (group.has_control(Group::ProductionCMode::RESV))
|
||||
{
|
||||
if (checkCurrentControl || currentControl != Group::ProductionCMode::RESV)
|
||||
if (currentControl != Group::ProductionCMode::RESV)
|
||||
{
|
||||
double current_rate = 0.0;
|
||||
current_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Aqua], true);
|
||||
@ -1923,6 +1984,7 @@ namespace Opm {
|
||||
current_rate = comm.sum(current_rate);
|
||||
|
||||
if (controls.resv_target < current_rate ) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, controls.exceed_action, Group::ProductionCMode::RESV, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
@ -1940,7 +2002,7 @@ namespace Opm {
|
||||
|
||||
// call recursively down the group hiearchy
|
||||
for (const std::string& groupName : group.groups()) {
|
||||
checkGroupConstraints( schedule().getGroup(groupName, reportStepIdx), checkCurrentControl, deferred_logger);
|
||||
checkGroupConstraints( schedule().getGroup(groupName, reportStepIdx), deferred_logger, switched_groups);
|
||||
}
|
||||
|
||||
|
||||
@ -1984,9 +2046,6 @@ namespace Opm {
|
||||
well_state.setCurrentProductionGroupControl(group.name(), newControl);
|
||||
ss << "Switching control mode for group "<< group.name() << " to " << Group::ProductionCMode2String(newControl);
|
||||
}
|
||||
// Pass a dummy phase for producer groups. The topUpPhase is only relevant for injector groups
|
||||
const Phase topUpPhase = Phase::WATER;
|
||||
wellGroupHelpers::setGroupControl(group, schedule(), topUpPhase, reportStepIdx, false, well_state, ss);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -2023,13 +2082,128 @@ namespace Opm {
|
||||
}
|
||||
well_state.setCurrentInjectionGroupControl(controlPhase, group.name(), newControl);
|
||||
}
|
||||
wellGroupHelpers::setGroupControl(group, schedule(), controlPhase, reportStepIdx, /*isInjector*/true, well_state, ss);
|
||||
|
||||
if (!ss.str().empty())
|
||||
deferred_logger.info(ss.str());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
updateGroupHigherControls(Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups)
|
||||
{
|
||||
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
||||
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
|
||||
checkGroupHigherConstraints(fieldGroup, deferred_logger, switched_groups);
|
||||
}
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
checkGroupHigherConstraints(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups)
|
||||
{
|
||||
// Use the pvtRegionIdx from the top cell of the first well.
|
||||
// TODO fix this!
|
||||
// This is only used for converting RESV rates.
|
||||
// What is the proper approach?
|
||||
const int pvtreg = well_perf_data_.empty()
|
||||
? pvt_region_idx_[0]
|
||||
: pvt_region_idx_[well_perf_data_[0][0].cell_index];
|
||||
|
||||
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
||||
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
|
||||
|
||||
std::vector<double> rates(phase_usage_.num_phases, 0.0);
|
||||
const auto& comm = ebosSimulator_.vanguard().grid().comm();
|
||||
|
||||
const bool skip = switched_groups.count(group.name());
|
||||
|
||||
if (!skip && group.isInjectionGroup()) {
|
||||
// Obtain rates for group.
|
||||
for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) {
|
||||
const double local_current_rate = wellGroupHelpers::sumWellRates(
|
||||
group, schedule(), well_state_, reportStepIdx, phasePos, /* isInjector */ true);
|
||||
// Sum over all processes
|
||||
rates[phasePos] = comm.sum(local_current_rate);
|
||||
}
|
||||
const Phase all[] = { Phase::WATER, Phase::OIL, Phase::GAS };
|
||||
for (Phase phase : all) {
|
||||
// Check higher up only if under individual (not FLD) control.
|
||||
const Group::InjectionCMode& currentControl = well_state_.currentInjectionGroupControl(phase, group.name());
|
||||
if (currentControl != Group::InjectionCMode::FLD) {
|
||||
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
|
||||
const bool changed = wellGroupHelpers::checkGroupConstraintsInj(
|
||||
group.name(),
|
||||
group.parent(),
|
||||
parentGroup,
|
||||
well_state_,
|
||||
reportStepIdx,
|
||||
guideRate_.get(),
|
||||
rates.data(),
|
||||
phase,
|
||||
phase_usage_,
|
||||
group.getGroupEfficiencyFactor(),
|
||||
schedule(),
|
||||
summaryState,
|
||||
*rateConverter_,
|
||||
pvtreg,
|
||||
deferred_logger);
|
||||
if (changed) {
|
||||
switched_groups.insert(group.name());
|
||||
actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip && group.isProductionGroup()) {
|
||||
// Obtain rates for group.
|
||||
for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) {
|
||||
const double local_current_rate = wellGroupHelpers::sumWellRates(
|
||||
group, schedule(), well_state_, reportStepIdx, phasePos, /* isInjector */ false);
|
||||
// Sum over all processes
|
||||
rates[phasePos] = -comm.sum(local_current_rate);
|
||||
}
|
||||
// Check higher up only if under individual (not FLD) control.
|
||||
const Group::ProductionCMode& currentControl = well_state_.currentProductionGroupControl(group.name());
|
||||
if (currentControl != Group::ProductionCMode::FLD) {
|
||||
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
|
||||
const bool changed = wellGroupHelpers::checkGroupConstraintsProd(
|
||||
group.name(),
|
||||
group.parent(),
|
||||
parentGroup,
|
||||
well_state_,
|
||||
reportStepIdx,
|
||||
guideRate_.get(),
|
||||
rates.data(),
|
||||
phase_usage_,
|
||||
group.getGroupEfficiencyFactor(),
|
||||
schedule(),
|
||||
summaryState,
|
||||
*rateConverter_,
|
||||
pvtreg,
|
||||
deferred_logger);
|
||||
if (changed) {
|
||||
switched_groups.insert(group.name());
|
||||
const auto exceed_action = group.productionControls(summaryState).exceed_action;
|
||||
actionOnBrokenConstraints(group, exceed_action, Group::ProductionCMode::FLD, reportStepIdx, deferred_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// call recursively down the group hiearchy
|
||||
for (const std::string& groupName : group.groups()) {
|
||||
checkGroupHigherConstraints( schedule().getGroup(groupName, reportStepIdx), deferred_logger, switched_groups);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
|
@ -2115,6 +2115,21 @@ namespace Opm
|
||||
MultisegmentWell<TypeTag>::
|
||||
assembleGroupInjectionControl(const Group& group, const WellState& well_state, const Opm::Schedule& schedule, const SummaryState& summaryState, const InjectorType& injectorType, EvalWell& control_eq, double efficiencyFactor, Opm::DeferredLogger& deferred_logger)
|
||||
{
|
||||
|
||||
if (!group.isAvailableForGroupControl()) {
|
||||
// We cannot go any further up the hierarchy. This could
|
||||
// be the FIELD group, or any group for which this has
|
||||
// been set in GCONINJE or GCONPROD. If we are here
|
||||
// anyway, it is likely that the deck set inconsistent
|
||||
// requirements, such as GRUP control mode on a well with
|
||||
// no appropriate controls defined on any of its
|
||||
// containing groups. We will therefore use the wells' bhp
|
||||
// limit equation as a fallback.
|
||||
const auto& controls = well_ecl_.injectionControls(summaryState);
|
||||
control_eq = getSegmentPressure(0) - controls.bhp_limit;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& well = well_ecl_;
|
||||
const auto& pu = phaseUsage();
|
||||
|
||||
@ -2153,30 +2168,23 @@ namespace Opm
|
||||
}
|
||||
|
||||
const Group::InjectionCMode& currentGroupControl = well_state.currentInjectionGroupControl(injectionPhase, group.name());
|
||||
if (currentGroupControl == Group::InjectionCMode::FLD) {
|
||||
if (currentGroupControl == Group::InjectionCMode::FLD ||
|
||||
currentGroupControl == Group::InjectionCMode::NONE) {
|
||||
// Inject share of parents control
|
||||
const auto& parent = schedule.getGroup( group.parent(), current_step_ );
|
||||
if (group.getTransferGroupEfficiencyFactor())
|
||||
efficiencyFactor *= group.getGroupEfficiencyFactor();
|
||||
|
||||
efficiencyFactor *= group.getGroupEfficiencyFactor();
|
||||
|
||||
assembleGroupInjectionControl(parent, well_state, schedule, summaryState, injectorType, control_eq, efficiencyFactor, deferred_logger);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!group.isInjectionGroup() || currentGroupControl == Group::InjectionCMode::NONE) {
|
||||
// use bhp as control eq and let the updateControl code find a valid control
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
control_eq = getSegmentPressure(0) - controls.bhp_limit;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(group.hasInjectionControl(injectionPhase));
|
||||
const auto& groupcontrols = group.injectionControls(injectionPhase, summaryState);
|
||||
|
||||
const std::vector<double>& groupInjectionReductions = well_state.currentInjectionGroupReductionRates(group.name());
|
||||
double groupTargetReduction = groupInjectionReductions[phasePos];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, wellTarget, /*isInjector*/true);
|
||||
wellGroupHelpers::accumulateGroupInjectionPotentialFractions(well.groupName(), group.name(), schedule, well_state, pu, current_step_, injectionPhase, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromInjectionPotentials(well.name(), group.name(), schedule,well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(wellTarget), pu, injectionPhase,false);
|
||||
|
||||
switch(currentGroupControl) {
|
||||
case Group::InjectionCMode::NONE:
|
||||
@ -2187,8 +2195,8 @@ namespace Opm
|
||||
}
|
||||
case Group::InjectionCMode::RATE:
|
||||
{
|
||||
|
||||
control_eq = getSegmentGTotal(0) / scaling - fraction * (groupcontrols.surface_max_rate / efficiencyFactor - groupTargetReduction);
|
||||
double target = std::max(0.0, (groupcontrols.surface_max_rate - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getSegmentGTotal(0) / scaling - fraction * target;
|
||||
break;
|
||||
}
|
||||
case Group::InjectionCMode::RESV:
|
||||
@ -2196,7 +2204,7 @@ namespace Opm
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
Base::rateConverter_.calcCoeff(/*fipreg*/ 0, Base::pvtRegionIdx_, convert_coeff);
|
||||
double coeff = convert_coeff[phasePos];
|
||||
double target = std::max(0.0, (groupcontrols.resv_max_rate/coeff/efficiencyFactor - groupTargetReduction));
|
||||
double target = std::max(0.0, (groupcontrols.resv_max_rate/coeff - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getSegmentGTotal(0) / scaling - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -2204,7 +2212,7 @@ namespace Opm
|
||||
{
|
||||
double productionRate = well_state.currentInjectionREINRates(groupcontrols.reinj_group)[phasePos];
|
||||
productionRate /= efficiencyFactor;
|
||||
double target = std::max(0.0, (groupcontrols.target_reinj_fraction*productionRate - groupTargetReduction));
|
||||
double target = std::max(0.0, (groupcontrols.target_reinj_fraction*productionRate - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getSegmentGTotal(0) / scaling - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -2228,9 +2236,7 @@ namespace Opm
|
||||
|
||||
voidageRate -= injReduction;
|
||||
|
||||
voidageRate /= efficiencyFactor;
|
||||
|
||||
double target = std::max(0.0, ( voidageRate/coeff - groupTargetReduction));
|
||||
double target = std::max(0.0, ( voidageRate/coeff - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getSegmentGTotal(0) / scaling - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -2258,7 +2264,7 @@ namespace Opm
|
||||
inj_rate -= gconsale.sales_target;
|
||||
|
||||
inj_rate /= efficiencyFactor;
|
||||
double target = std::max(0.0, (inj_rate - groupTargetReduction));
|
||||
double target = std::max(0.0, (inj_rate - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getSegmentGTotal(0) /scaling - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -2283,17 +2289,30 @@ namespace Opm
|
||||
const auto pu = phaseUsage();
|
||||
|
||||
const Group::ProductionCMode& currentGroupControl = well_state.currentProductionGroupControl(group.name());
|
||||
|
||||
if (currentGroupControl == Group::ProductionCMode::FLD ) {
|
||||
// Produce share of parents control
|
||||
const auto& parent = schedule.getGroup( group.parent(), current_step_ );
|
||||
if (group.getTransferGroupEfficiencyFactor())
|
||||
if (currentGroupControl == Group::ProductionCMode::FLD ||
|
||||
currentGroupControl == Group::ProductionCMode::NONE) {
|
||||
if (!group.isAvailableForGroupControl()) {
|
||||
// We cannot go any further up the hierarchy. This could
|
||||
// be the FIELD group, or any group for which this has
|
||||
// been set in GCONINJE or GCONPROD. If we are here
|
||||
// anyway, it is likely that the deck set inconsistent
|
||||
// requirements, such as GRUP control mode on a well with
|
||||
// no appropriate controls defined on any of its
|
||||
// containing groups. We will therefore use the wells' bhp
|
||||
// limit equation as a fallback.
|
||||
const auto& controls = well_ecl_.productionControls(summaryState);
|
||||
control_eq = getSegmentPressure(0) - controls.bhp_limit;
|
||||
return;
|
||||
} else {
|
||||
// Produce share of parents control
|
||||
const auto& parent = schedule.getGroup( group.parent(), current_step_ );
|
||||
efficiencyFactor *= group.getGroupEfficiencyFactor();
|
||||
|
||||
assembleGroupProductionControl(parent, well_state, schedule, summaryState, control_eq, efficiencyFactor, deferred_logger);
|
||||
return;
|
||||
assembleGroupProductionControl(parent, well_state, schedule, summaryState, control_eq, efficiencyFactor, deferred_logger);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!group.isProductionGroup() || currentGroupControl == Group::ProductionCMode::NONE) {
|
||||
|
||||
if (!group.isProductionGroup()) {
|
||||
// use bhp as control eq and let the updateControl code find a vallied control
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
control_eq = getSegmentPressure(0) - controls.bhp_limit;
|
||||
@ -2313,10 +2332,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::ORAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Oil]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::OIL, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::OIL, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::OIL));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.oil_target / efficiencyFactor - groupTargetReduction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.oil_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
|
||||
const EvalWell& rate = -getSegmentRate(0, Indices::canonicalToActiveComponentIndex(FluidSystem::oilCompIdx));
|
||||
control_eq = rate - fraction * rate_target;
|
||||
@ -2325,10 +2343,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::WRAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Water]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::WAT, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::WAT, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::WAT));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.water_target / efficiencyFactor - groupTargetReduction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.gas_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx));
|
||||
const EvalWell& rate = -getSegmentRate(0, Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx));
|
||||
control_eq = rate - fraction * rate_target;
|
||||
@ -2337,9 +2354,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::GRAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Gas]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::GAS, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::GAS, fraction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.gas_target / efficiencyFactor - groupTargetReduction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::GAS));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.gas_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::gasCompIdx));
|
||||
const EvalWell& rate = -getSegmentRate(0, Indices::canonicalToActiveComponentIndex(FluidSystem::gasCompIdx));
|
||||
control_eq = rate - fraction * rate_target;
|
||||
@ -2348,12 +2365,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::LRAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Oil]] + groupTargetReductions[pu.phase_pos[Water]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::LIQ, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::LIQ, fraction);
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.liquid_target / efficiencyFactor - groupTargetReduction);
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::LIQ));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.liquid_target - groupTargetReduction) / efficiencyFactor; assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
|
||||
EvalWell rate = -getSegmentRate(0, Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx))
|
||||
-getSegmentRate(0, Indices::canonicalToActiveComponentIndex(FluidSystem::oilCompIdx));
|
||||
control_eq = rate - fraction * rate_target;
|
||||
|
@ -981,6 +981,20 @@ namespace Opm
|
||||
StandardWell<TypeTag>::
|
||||
assembleGroupInjectionControl(const Group& group, const WellState& well_state, const Opm::Schedule& schedule, const SummaryState& summaryState, const InjectorType& injectorType, EvalWell& control_eq, double efficiencyFactor, Opm::DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (!group.isAvailableForGroupControl()) {
|
||||
// We cannot go any further up the hierarchy. This could
|
||||
// be the FIELD group, or any group for which this has
|
||||
// been set in GCONINJE or GCONPROD. If we are here
|
||||
// anyway, it is likely that the deck set inconsistent
|
||||
// requirements, such as GRUP control mode on a well with
|
||||
// no appropriate controls defined on any of its
|
||||
// containing groups. We will therefore use the wells' bhp
|
||||
// limit equation as a fallback.
|
||||
const auto& controls = well_ecl_.injectionControls(summaryState);
|
||||
control_eq = getBhp() - controls.bhp_limit;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& well = well_ecl_;
|
||||
const auto pu = phaseUsage();
|
||||
|
||||
@ -1015,31 +1029,21 @@ namespace Opm
|
||||
}
|
||||
const Group::InjectionCMode& currentGroupControl = well_state.currentInjectionGroupControl(injectionPhase, group.name());
|
||||
|
||||
if (currentGroupControl == Group::InjectionCMode::FLD) {
|
||||
if (currentGroupControl == Group::InjectionCMode::FLD ||
|
||||
currentGroupControl == Group::InjectionCMode::NONE) {
|
||||
// Inject share of parents control
|
||||
const auto& parent = schedule.getGroup( group.parent(), current_step_ );
|
||||
if (group.getTransferGroupEfficiencyFactor())
|
||||
efficiencyFactor *= group.getGroupEfficiencyFactor();
|
||||
|
||||
efficiencyFactor *= group.getGroupEfficiencyFactor();
|
||||
assembleGroupInjectionControl(parent, well_state, schedule, summaryState, injectorType, control_eq, efficiencyFactor, deferred_logger);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!group.isInjectionGroup() || currentGroupControl == Group::InjectionCMode::NONE) {
|
||||
// use bhp as control eq and let the updateControl code find a valid control
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
control_eq = getBhp() - controls.bhp_limit;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(group.hasInjectionControl(injectionPhase));
|
||||
const auto& groupcontrols = group.injectionControls(injectionPhase, summaryState);
|
||||
|
||||
|
||||
const std::vector<double>& groupInjectionReductions = well_state.currentInjectionGroupReductionRates(group.name());
|
||||
double groupTargetReduction = groupInjectionReductions[phasePos];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, wellTarget, /*isInjector*/true);
|
||||
wellGroupHelpers::accumulateGroupInjectionPotentialFractions(well.groupName(), group.name(), schedule, well_state, pu, current_step_, injectionPhase, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromInjectionPotentials(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(wellTarget), pu, injectionPhase,false);
|
||||
switch(currentGroupControl) {
|
||||
case Group::InjectionCMode::NONE:
|
||||
{
|
||||
@ -1049,7 +1053,7 @@ namespace Opm
|
||||
}
|
||||
case Group::InjectionCMode::RATE:
|
||||
{
|
||||
double target = std::max(0.0, (groupcontrols.surface_max_rate / efficiencyFactor - groupTargetReduction) );
|
||||
double target = std::max(0.0, (groupcontrols.surface_max_rate - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getWQTotal() - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -1058,15 +1062,14 @@ namespace Opm
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
Base::rateConverter_.calcCoeff(/*fipreg*/ 0, Base::pvtRegionIdx_, convert_coeff);
|
||||
double coeff = convert_coeff[phasePos];
|
||||
double target = std::max(0.0, (groupcontrols.resv_max_rate/coeff/efficiencyFactor - groupTargetReduction));
|
||||
double target = std::max(0.0, (groupcontrols.resv_max_rate/coeff - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getWQTotal() - fraction * target;
|
||||
break;
|
||||
}
|
||||
case Group::InjectionCMode::REIN:
|
||||
{
|
||||
double productionRate = well_state.currentInjectionREINRates(groupcontrols.reinj_group)[phasePos];
|
||||
productionRate /= efficiencyFactor;
|
||||
double target = std::max(0.0, (groupcontrols.target_reinj_fraction*productionRate - groupTargetReduction));
|
||||
double target = std::max(0.0, (groupcontrols.target_reinj_fraction*productionRate - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getWQTotal() - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -1090,9 +1093,7 @@ namespace Opm
|
||||
|
||||
voidageRate -= injReduction;
|
||||
|
||||
voidageRate /= efficiencyFactor;
|
||||
|
||||
double target = std::max(0.0, ( voidageRate/coeff - groupTargetReduction));
|
||||
double target = std::max(0.0, ( voidageRate/coeff - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getWQTotal() - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -1119,8 +1120,7 @@ namespace Opm
|
||||
const auto& gconsale = schedule.gConSale(current_step_).get(group.name(), summaryState);
|
||||
inj_rate -= gconsale.sales_target;
|
||||
|
||||
inj_rate /= efficiencyFactor;
|
||||
double target = std::max(0.0, (inj_rate - groupTargetReduction));
|
||||
double target = std::max(0.0, (inj_rate - groupTargetReduction)) / efficiencyFactor;
|
||||
control_eq = getWQTotal() - fraction * target;
|
||||
break;
|
||||
}
|
||||
@ -1139,30 +1139,94 @@ namespace Opm
|
||||
StandardWell<TypeTag>::
|
||||
assembleGroupProductionControl(const Group& group, const WellState& well_state, const Opm::Schedule& schedule, const SummaryState& summaryState, EvalWell& control_eq, double efficiencyFactor, Opm::DeferredLogger& deferred_logger)
|
||||
{
|
||||
|
||||
const auto& well = well_ecl_;
|
||||
const auto pu = phaseUsage();
|
||||
|
||||
const Group::ProductionCMode& currentGroupControl = well_state.currentProductionGroupControl(group.name());
|
||||
if (currentGroupControl == Group::ProductionCMode::FLD) {
|
||||
// Produce share of parents control
|
||||
const auto& parent = schedule.getGroup( group.parent(), current_step_ );
|
||||
if (group.getTransferGroupEfficiencyFactor())
|
||||
if (currentGroupControl == Group::ProductionCMode::FLD ||
|
||||
currentGroupControl == Group::ProductionCMode::NONE) {
|
||||
if (!group.isAvailableForGroupControl()) {
|
||||
// We cannot go any further up the hierarchy. This could
|
||||
// be the FIELD group, or any group for which this has
|
||||
// been set in GCONINJE or GCONPROD. If we are here
|
||||
// anyway, it is likely that the deck set inconsistent
|
||||
// requirements, such as GRUP control mode on a well with
|
||||
// no appropriate controls defined on any of its
|
||||
// containing groups. We will therefore use the wells' bhp
|
||||
// limit equation as a fallback.
|
||||
const auto& controls = well_ecl_.productionControls(summaryState);
|
||||
control_eq = getBhp() - controls.bhp_limit;
|
||||
return;
|
||||
} else {
|
||||
// Produce share of parents control
|
||||
const auto& parent = schedule.getGroup( group.parent(), current_step_ );
|
||||
efficiencyFactor *= group.getGroupEfficiencyFactor();
|
||||
|
||||
assembleGroupProductionControl(parent, well_state, schedule, summaryState, control_eq, efficiencyFactor, deferred_logger);
|
||||
return;
|
||||
assembleGroupProductionControl(parent, well_state, schedule, summaryState, control_eq, efficiencyFactor, deferred_logger);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!group.isProductionGroup() || currentGroupControl == Group::ProductionCMode::NONE) {
|
||||
if (!group.isProductionGroup()) {
|
||||
// use bhp as control eq and let the updateControl code find a vallied control
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
control_eq = getBhp() - controls.bhp_limit;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& groupcontrols = group.productionControls(summaryState);
|
||||
// ------------------------------- New code start --------------------------------
|
||||
|
||||
// If we are here, we are at the topmost group to be visited in the recursion.
|
||||
// This is the group containing the control we will check against.
|
||||
wellGroupHelpers::TargetCalculator tcalc(currentGroupControl, pu, Base::rateConverter_, Base::pvtRegionIdx_);
|
||||
wellGroupHelpers::FractionCalculator fcalc(schedule, well_state, current_step_, Base::guide_rate_, tcalc.guideTargetMode());
|
||||
|
||||
auto localFraction = [&](const std::string& child) {
|
||||
return fcalc.localFraction(child, "");
|
||||
};
|
||||
|
||||
auto localReduction = [&](const std::string& group_name) {
|
||||
const std::vector<double>& groupTargetReductions = well_state.currentProductionGroupReductionRates(group_name);
|
||||
return tcalc.calcModeRateFromRates(groupTargetReductions);
|
||||
};
|
||||
|
||||
const double orig_target = tcalc.groupTarget(group.productionControls(summaryState));
|
||||
// Assume we have a chain of groups as follows: BOTTOM -> MIDDLE -> TOP.
|
||||
// Then ...
|
||||
// TODO finish explanation.
|
||||
const auto chain = wellGroupHelpers::groupChainTopBot(name(), group.name(), schedule, current_step_);
|
||||
// Because 'name' is the last of the elements, and not an ancestor, we subtract one below.
|
||||
const size_t num_ancestors = chain.size() - 1;
|
||||
double target = orig_target;
|
||||
for (size_t ii = 0; ii < num_ancestors; ++ii) {
|
||||
target -= localReduction(chain[ii]);
|
||||
// Next lines: different from in WellGroupHelpers.hpp
|
||||
// if (ii == num_ancestors - 1) {
|
||||
// // Final level. Add my reduction back.
|
||||
// target += current_rate*efficiencyFactor;
|
||||
// }
|
||||
target *= localFraction(chain[ii+1]);
|
||||
}
|
||||
const double target_rate = target / efficiencyFactor;
|
||||
|
||||
std::vector<EvalWell> rates(pu.num_phases);
|
||||
const int compIndices[3] = { FluidSystem::waterCompIdx, FluidSystem::oilCompIdx, FluidSystem::gasCompIdx };
|
||||
const BlackoilPhases::PhaseIndex phases[3] = { BlackoilPhases::Aqua, BlackoilPhases::Liquid, BlackoilPhases::Vapour };
|
||||
for (int canonical_phase = 0; canonical_phase < 3; ++canonical_phase) {
|
||||
const auto phase = phases[canonical_phase];
|
||||
if (pu.phase_used[phase]) {
|
||||
const auto compIdx = compIndices[canonical_phase];
|
||||
rates[pu.phase_pos[phase]] = getQs(Indices::canonicalToActiveComponentIndex(compIdx));
|
||||
}
|
||||
}
|
||||
const auto current_rate = -tcalc.calcModeRateFromRates(rates); // Switch sign since 'rates' are negative for producers.
|
||||
|
||||
control_eq = current_rate - target_rate;
|
||||
|
||||
// ------------------------------- New code end --------------------------------
|
||||
|
||||
|
||||
#if 0
|
||||
const auto& groupcontrols = group.productionControls(summaryState);
|
||||
const std::vector<double>& groupTargetReductions = well_state.currentProductionGroupReductionRates(group.name());
|
||||
|
||||
switch(currentGroupControl) {
|
||||
@ -1174,10 +1238,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::ORAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Oil]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::OIL, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::OIL, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::OIL));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.oil_target / efficiencyFactor - groupTargetReduction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.oil_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
|
||||
EvalWell rate = -getQs(Indices::canonicalToActiveComponentIndex(FluidSystem::oilCompIdx));
|
||||
control_eq = rate - fraction * rate_target;
|
||||
@ -1186,10 +1249,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::WRAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Water]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::WAT, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::WAT, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::WAT));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.water_target / efficiencyFactor - groupTargetReduction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.water_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx));
|
||||
EvalWell rate = -getQs(Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx));
|
||||
control_eq = rate - fraction * rate_target;
|
||||
@ -1198,10 +1260,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::GRAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Gas]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::GAS, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::GAS, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::GAS));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.gas_target / efficiencyFactor - groupTargetReduction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.gas_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::gasCompIdx));
|
||||
EvalWell rate = -getQs(Indices::canonicalToActiveComponentIndex(FluidSystem::gasCompIdx));
|
||||
control_eq = rate - fraction * rate_target;
|
||||
@ -1210,10 +1271,9 @@ namespace Opm
|
||||
case Group::ProductionCMode::LRAT:
|
||||
{
|
||||
double groupTargetReduction = groupTargetReductions[pu.phase_pos[Oil]] + groupTargetReductions[pu.phase_pos[Water]];
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::LIQ, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::LIQ, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::LIQ));
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.liquid_target / efficiencyFactor - groupTargetReduction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.liquid_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
|
||||
|
||||
EvalWell rate = -getQs(Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx))
|
||||
@ -1232,8 +1292,7 @@ namespace Opm
|
||||
+ groupTargetReductions[pu.phase_pos[Gas]]
|
||||
+ groupTargetReductions[pu.phase_pos[Water]];
|
||||
|
||||
double fraction = wellGroupHelpers::wellFractionFromGuideRates(well, schedule, well_state, current_step_, Base::guide_rate_, Well::GuideRateTarget::RES, /*isInjector*/false);
|
||||
wellGroupHelpers::accumulateGroupFractionsFromGuideRates(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, Group::GuideRateTarget::RES, fraction);
|
||||
double fraction = wellGroupHelpers::fractionFromGuideRates(well.name(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, GuideRateModel::convert_target(Well::GuideRateTarget::RES));
|
||||
|
||||
EvalWell total_rate(numWellEq_ + numEq, 0.); // reservoir rate
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
@ -1242,7 +1301,7 @@ namespace Opm
|
||||
total_rate -= getQs( flowPhaseToEbosCompIdx(phase) ) * convert_coeff[phase];
|
||||
}
|
||||
|
||||
const double rate_target = std::max(0.0, groupcontrols.resv_target/ efficiencyFactor - groupTargetReduction);
|
||||
const double rate_target = std::max(0.0, groupcontrols.resv_target - groupTargetReduction) / efficiencyFactor;
|
||||
assert(FluidSystem::phaseIsActive(FluidSystem::gasCompIdx));
|
||||
control_eq = total_rate - fraction * rate_target;
|
||||
break;
|
||||
@ -1262,6 +1321,7 @@ namespace Opm
|
||||
default:
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Unvallied group control specified for group " + well.groupName(), deferred_logger );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -201,7 +201,9 @@ namespace Opm
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const = 0;
|
||||
|
||||
void updateWellControl(const Simulator& ebos_simulator,
|
||||
enum class IndividualOrGroup { Individual, Group, Both };
|
||||
bool updateWellControl(const Simulator& ebos_simulator,
|
||||
const IndividualOrGroup iog,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) /* const */;
|
||||
|
||||
@ -478,10 +480,34 @@ namespace Opm
|
||||
// index calculations
|
||||
int well_productivity_index_logger_counter_;
|
||||
|
||||
bool checkConstraints(WellState& well_state, const SummaryState& summaryState);
|
||||
bool checkConstraints(WellState& well_state,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool checkIndividualConstraints(WellState& well_state,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool checkGroupConstraints(WellState& well_state,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool checkGroupConstraintsProd(const Group& group,
|
||||
const WellState& well_state,
|
||||
const double efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool checkGroupConstraintsInj(const Group& group,
|
||||
const WellState& well_state,
|
||||
const double efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -461,17 +461,19 @@ namespace Opm
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
updateWellControl(const Simulator& ebos_simulator,
|
||||
const IndividualOrGroup iog,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) /* const */
|
||||
{
|
||||
if (this->wellIsStopped()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& summaryState = ebos_simulator.vanguard().summaryState();
|
||||
const auto& schedule = ebos_simulator.vanguard().schedule();
|
||||
const auto& well = well_ecl_;
|
||||
std::string from;
|
||||
if (well.isInjector()) {
|
||||
@ -480,7 +482,15 @@ namespace Opm
|
||||
from = Well::ProducerCMode2String(well_state.currentProductionControls()[index_of_well_]);
|
||||
}
|
||||
|
||||
bool changed = checkConstraints(well_state, summaryState);
|
||||
bool changed = false;
|
||||
if (iog == IndividualOrGroup::Individual) {
|
||||
changed = checkIndividualConstraints(well_state, schedule, summaryState, deferred_logger);
|
||||
} else if (iog == IndividualOrGroup::Group) {
|
||||
changed = checkGroupConstraints(well_state, schedule, summaryState, deferred_logger);
|
||||
} else {
|
||||
assert(iog == IndividualOrGroup::Both);
|
||||
changed = checkConstraints(well_state, schedule, summaryState, deferred_logger);
|
||||
}
|
||||
|
||||
auto cc = Dune::MPIHelper::getCollectiveCommunication();
|
||||
|
||||
@ -503,6 +513,8 @@ namespace Opm
|
||||
updateWellStateWithTarget(ebos_simulator, well_state, deferred_logger);
|
||||
updatePrimaryVariables(well_state, deferred_logger);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@ -1436,20 +1448,40 @@ namespace Opm
|
||||
return operability_status_.isOperable();
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
checkConstraints(WellState& well_state, const SummaryState& summaryState) {
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::checkConstraints(WellState& well_state,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const bool ind_broken = checkIndividualConstraints(well_state, schedule, summaryState, deferred_logger);
|
||||
if (ind_broken) {
|
||||
return true;
|
||||
} else {
|
||||
return checkGroupConstraints(well_state, schedule, summaryState, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::checkIndividualConstraints(WellState& well_state,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const auto& well = well_ecl_;
|
||||
const PhaseUsage& pu = phaseUsage();
|
||||
const int well_index = index_of_well_;
|
||||
const auto wellrate_index = well_index * pu.num_phases;
|
||||
// bool changed = false;
|
||||
|
||||
// // Stopped wells can not change control
|
||||
// if (currentControl == "STOP")
|
||||
// return newControl;
|
||||
|
||||
if (well.isInjector()) {
|
||||
const auto controls = well.injectionControls(summaryState);
|
||||
@ -1633,4 +1665,155 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::checkGroupConstraints(WellState& well_state,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const auto& well = well_ecl_;
|
||||
const int well_index = index_of_well_;
|
||||
|
||||
if (well.isInjector()) {
|
||||
const auto controls = well.injectionControls(summaryState);
|
||||
Opm::Well::InjectorCMode& currentControl = well_state.currentInjectionControls()[well_index];
|
||||
|
||||
if (currentControl != Well::InjectorCMode::GRUP) {
|
||||
// This checks only the first encountered group limit,
|
||||
// in theory there could be several, and then we should
|
||||
// test all but the one currently applied. At that point,
|
||||
// this if-statement should be removed and we should always
|
||||
// check, skipping over only the single group parent whose
|
||||
// control is the active one for the well (if any).
|
||||
const auto& group = schedule.getGroup( well.groupName(), current_step_ );
|
||||
const double efficiencyFactor = well.getEfficiencyFactor();
|
||||
const bool group_constraint_broken = checkGroupConstraintsInj(
|
||||
group, well_state, efficiencyFactor, schedule, summaryState, deferred_logger);
|
||||
// If a group constraint was broken, we set the current well control to
|
||||
// be GRUP.
|
||||
if (group_constraint_broken) {
|
||||
well_state.currentInjectionControls()[index_of_well_] = Well::InjectorCMode::GRUP;
|
||||
}
|
||||
return group_constraint_broken;
|
||||
}
|
||||
}
|
||||
|
||||
if (well.isProducer( )) {
|
||||
const auto controls = well.productionControls(summaryState);
|
||||
Well::ProducerCMode& currentControl = well_state.currentProductionControls()[well_index];
|
||||
|
||||
if (currentControl != Well::ProducerCMode::GRUP) {
|
||||
// This checks only the first encountered group limit,
|
||||
// in theory there could be several, and then we should
|
||||
// test all but the one currently applied. At that point,
|
||||
// this if-statement should be removed and we should always
|
||||
// check, skipping over only the single group parent whose
|
||||
// control is the active one for the well (if any).
|
||||
const auto& group = schedule.getGroup( well.groupName(), current_step_ );
|
||||
const double efficiencyFactor = well.getEfficiencyFactor();
|
||||
const bool group_constraint_broken = checkGroupConstraintsProd(
|
||||
group, well_state, efficiencyFactor, schedule, summaryState, deferred_logger);
|
||||
// If a group constraint was broken, we set the current well control to
|
||||
// be GRUP.
|
||||
if (group_constraint_broken) {
|
||||
well_state.currentProductionControls()[index_of_well_] = Well::ProducerCMode::GRUP;
|
||||
}
|
||||
return group_constraint_broken;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::checkGroupConstraintsInj(const Group& group,
|
||||
const WellState& well_state,
|
||||
const double efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// Translate injector type from control to Phase.
|
||||
const auto& well_controls = well_ecl_.injectionControls(summaryState);
|
||||
auto injectorType = well_controls.injector_type;
|
||||
Phase injectionPhase;
|
||||
switch (injectorType) {
|
||||
case InjectorType::WATER:
|
||||
{
|
||||
injectionPhase = Phase::WATER;
|
||||
break;
|
||||
}
|
||||
case InjectorType::OIL:
|
||||
{
|
||||
injectionPhase = Phase::OIL;
|
||||
break;
|
||||
}
|
||||
case InjectorType::GAS:
|
||||
{
|
||||
injectionPhase = Phase::GAS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw("Expected WATER, OIL or GAS as type for injector " + name());
|
||||
}
|
||||
// Call check for the well's injection phase.
|
||||
return wellGroupHelpers::checkGroupConstraintsInj(name(),
|
||||
well_ecl_.groupName(),
|
||||
group,
|
||||
well_state,
|
||||
current_step_,
|
||||
guide_rate_,
|
||||
well_state.wellRates().data() + index_of_well_ * phaseUsage().num_phases,
|
||||
injectionPhase,
|
||||
phaseUsage(),
|
||||
efficiencyFactor,
|
||||
schedule,
|
||||
summaryState,
|
||||
rateConverter_,
|
||||
pvtRegionIdx_,
|
||||
deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::checkGroupConstraintsProd(const Group& group,
|
||||
const WellState& well_state,
|
||||
const double efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
return wellGroupHelpers::checkGroupConstraintsProd(name(),
|
||||
well_ecl_.groupName(),
|
||||
group,
|
||||
well_state,
|
||||
current_step_,
|
||||
guide_rate_,
|
||||
well_state.wellRates().data() + index_of_well_ * phaseUsage().num_phases,
|
||||
phaseUsage(),
|
||||
efficiencyFactor,
|
||||
schedule,
|
||||
summaryState,
|
||||
rateConverter_,
|
||||
pvtRegionIdx_,
|
||||
deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace Opm
|
||||
|
@ -883,24 +883,37 @@ namespace Opm
|
||||
}
|
||||
|
||||
template<class Comm>
|
||||
void updateGlobalIsGrup(const Schedule& schedule, const int reportStepIdx, const Comm& comm) {
|
||||
|
||||
int global_well_index = -1;
|
||||
void updateGlobalIsGrup(const Schedule& schedule, const int reportStepIdx, const Comm& comm)
|
||||
{
|
||||
std::fill(globalIsInjectionGrup_.begin(), globalIsInjectionGrup_.end(), 0);
|
||||
std::fill(globalIsProductionGrup_.begin(), globalIsProductionGrup_.end(), 0);
|
||||
int global_well_index = 0;
|
||||
const auto& end = wellMap().end();
|
||||
for (const auto& well : schedule.getWells(reportStepIdx)) {
|
||||
global_well_index ++;
|
||||
// Build global name->index map.
|
||||
wellNameToGlobalIdx_[well.name()] = global_well_index;
|
||||
|
||||
// For wells on this process...
|
||||
const auto& it = wellMap().find( well.name());
|
||||
if (it == end) // the well is not found
|
||||
continue;
|
||||
|
||||
int well_index = it->second[0];
|
||||
|
||||
if (well.isInjector())
|
||||
globalIsInjectionGrup_[global_well_index] = (currentInjectionControls()[well_index] == Well::InjectorCMode::GRUP);
|
||||
else
|
||||
globalIsProductionGrup_[global_well_index] = (currentProductionControls()[well_index] == Well::ProducerCMode::GRUP);
|
||||
if (it != end) {
|
||||
// ... set the GRUP/not GRUP states.
|
||||
const int well_index = it->second[0];
|
||||
if (!this->open_for_output_[well_index]) {
|
||||
// Well is shut.
|
||||
if (well.isInjector()) {
|
||||
globalIsInjectionGrup_[global_well_index] = 0;
|
||||
} else {
|
||||
globalIsProductionGrup_[global_well_index] = 0;
|
||||
}
|
||||
} else {
|
||||
if (well.isInjector()) {
|
||||
globalIsInjectionGrup_[global_well_index] = (currentInjectionControls()[well_index] == Well::InjectorCMode::GRUP);
|
||||
} else {
|
||||
globalIsProductionGrup_[global_well_index] = (currentProductionControls()[well_index] == Well::ProducerCMode::GRUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
++global_well_index;
|
||||
}
|
||||
comm.sum(globalIsInjectionGrup_.data(), globalIsInjectionGrup_.size());
|
||||
comm.sum(globalIsProductionGrup_.data(), globalIsProductionGrup_.size());
|
||||
|
Loading…
Reference in New Issue
Block a user