allow for multiple group injection phases

This commit is contained in:
Tor Harald Sandve 2020-01-23 09:05:37 +01:00
parent a840c4f418
commit 469ffa2cbe
8 changed files with 251 additions and 154 deletions

View File

@ -831,6 +831,16 @@ std::size_t packSize(const IntervalTabulated2DFunction<Scalar>& data,
packSize(data.yExtrapolate(), comm);
}
template std::size_t packSize(const IntervalTabulated2DFunction<double>& data,
Dune::MPIHelper::MPICommunicator comm);
template
std::size_t packSize(const std::vector<IntervalTabulated2DFunction<double>>& data,
Dune::MPIHelper::MPICommunicator comm);
template
std::size_t packSize(const std::map<int,IntervalTabulated2DFunction<double>>& data,
Dune::MPIHelper::MPICommunicator comm);
template<class Scalar>
std::size_t packSize(const UniformXTabulated2DFunction<Scalar>& data,
Dune::MPIHelper::MPICommunicator comm)

View File

@ -384,7 +384,7 @@ namespace Opm {
void actionOnBrokenConstraints(const Group& group, const Group::ExceedAction& exceed_action, const Group::ProductionCMode& newControl, const int reportStepIdx, Opm::DeferredLogger& deferred_logger);
void actionOnBrokenConstraints(const Group& group, const Group::InjectionCMode& newControl, const int reportStepIdx, Opm::DeferredLogger& deferred_logger);
void actionOnBrokenConstraints(const Group& group, const Group::InjectionCMode& newControl, const Phase& topUpPhase, const int reportStepIdx, Opm::DeferredLogger& deferred_logger);
WellInterfacePtr getWell(const std::string& well_name) const;

View File

@ -1689,7 +1689,7 @@ namespace Opm {
const int reportStepIdx = ebosSimulator_.episodeIndex();
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
const auto& comm = ebosSimulator_.vanguard().grid().comm();
auto& well_state = well_state_;
auto& well_state = well_state_;
if (group.isInjectionGroup())
{
@ -1716,6 +1716,33 @@ namespace Opm {
throw("Expected WATER, OIL or GAS as type for group injector: " + group.name());
}
for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) {
Phase currentPhase;
if (phasePos == phase_usage_.phase_pos[BlackoilPhases::Aqua]) {
if (!group.hasInjectionControl(Phase::WATER)) {
continue;
}
currentPhase = Phase::WATER;
}
else if (phasePos == phase_usage_.phase_pos[BlackoilPhases::Liquid]) {
if (!group.hasInjectionControl(Phase::OIL)) {
continue;
}
currentPhase = Phase::OIL;
}
else if (phasePos == phase_usage_.phase_pos[BlackoilPhases::Vapour]) {
if (!group.hasInjectionControl(Phase::GAS)) {
continue;
}
currentPhase = Phase::GAS;
} else {
throw("Expected oil, gas or water phase for injector " + group.name());
}
const auto& controls = group.injectionControls(currentPhase, summaryState);
if (group.has_control(Group::InjectionCMode::RATE))
{
if (checkCurrentControl || currentControl != Group::InjectionCMode::RATE)
@ -1723,12 +1750,11 @@ namespace Opm {
double current_rate = 0.0;
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true);
// sum over all nodes
current_rate = comm.sum(current_rate);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.surface_max_rate < current_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::RATE, reportStepIdx, deferred_logger);
}
if (controls.surface_max_rate < current_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::RATE, currentPhase, reportStepIdx, deferred_logger);
}
}
if (group.has_control(Group::InjectionCMode::RESV))
@ -1740,10 +1766,9 @@ namespace Opm {
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.resv_max_rate < current_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::RESV, reportStepIdx, deferred_logger);
}
}}
if (controls.resv_max_rate < current_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::RESV, currentPhase, reportStepIdx, deferred_logger);
} }
if (group.has_control(Group::InjectionCMode::REIN))
{
if (checkCurrentControl || currentControl != Group::InjectionCMode::REIN)
@ -1752,19 +1777,18 @@ namespace Opm {
const Group& groupRein = schedule().getGroup(controls.reinj_group, reportStepIdx);
production_Rate += wellGroupHelpers::sumWellRates(groupRein, schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/false);
// sum over all nodes
production_Rate = comm.sum(production_Rate);
// sum over all nodes
production_Rate = comm.sum(production_Rate);
double current_rate = 0.0;
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true);
double current_rate = 0.0;
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true);
// sum over all nodes
current_rate = comm.sum(current_rate);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.target_reinj_fraction*production_Rate < current_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::REIN, reportStepIdx, deferred_logger);
}
}}
if (controls.target_reinj_fraction*production_Rate < current_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::REIN, currentPhase,reportStepIdx, deferred_logger);
} }
if (group.has_control(Group::InjectionCMode::VREP))
{
if (checkCurrentControl || currentControl != Group::InjectionCMode::VREP)
@ -1775,20 +1799,19 @@ namespace Opm {
voidage_rate += wellGroupHelpers::sumWellResRates(groupVoidage, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], false);
voidage_rate += wellGroupHelpers::sumWellResRates(groupVoidage, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Vapour], false);
// sum over all nodes
voidage_rate = comm.sum(voidage_rate);
// sum over all nodes
voidage_rate = comm.sum(voidage_rate);
double total_rate = 0.0;
total_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Aqua], true);
total_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], true);
total_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Vapour], true);
double total_rate = 0.0;
total_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Aqua], true);
total_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], true);
total_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Vapour], true);
// sum over all nodes
total_rate = comm.sum(total_rate);
// sum over all nodes
total_rate = comm.sum(total_rate);
if (controls.target_void_fraction*voidage_rate < total_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::VREP, reportStepIdx, deferred_logger);
}
if (controls.target_void_fraction*voidage_rate < total_rate) {
actionOnBrokenConstraints(group, Group::InjectionCMode::VREP, currentPhase, reportStepIdx, deferred_logger);
}
}
// Handle GCONSALE
@ -1825,6 +1848,7 @@ namespace Opm {
OPM_THROW(std::runtime_error, "Group " + group.name() + " has sale rate target less then zero. Not implemented in Flow" );
}
}
}
}
@ -1832,6 +1856,10 @@ namespace Opm {
const auto controls = group.productionControls(summaryState);
const Group::ProductionCMode& currentControl = well_state.currentProductionGroupControl(group.name());
if (group.has_control(Group::ProductionCMode::NONE))
{
}
if (group.has_control(Group::ProductionCMode::ORAT))
{
if (checkCurrentControl || currentControl != Group::ProductionCMode::ORAT)
@ -1850,10 +1878,8 @@ namespace Opm {
if (group.has_control(Group::ProductionCMode::WRAT))
{
if (checkCurrentControl || currentControl != Group::ProductionCMode::WRAT)
{
double current_rate = 0.0;
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Aqua], false);
double current_rate = 0.0;
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Aqua], false);
// sum over all nodes
current_rate = comm.sum(current_rate);
@ -1996,9 +2022,9 @@ namespace Opm {
template<typename TypeTag>
void
BlackoilWellModel<TypeTag>::
actionOnBrokenConstraints(const Group& group, const Group::InjectionCMode& newControl, const int reportStepIdx, Opm::DeferredLogger& deferred_logger) {
actionOnBrokenConstraints(const Group& group, const Group::InjectionCMode& newControl, const Phase& controlPhase, const int reportStepIdx, Opm::DeferredLogger& deferred_logger) {
auto& well_state = well_state_;
const Group::InjectionCMode& oldControl = well_state.currentInjectionGroupControl(group.name());
const Group::InjectionCMode& oldControl = well_state.currentInjectionGroupControl(controlPhase, group.name());
std::ostringstream ss;
if (oldControl != newControl) {
@ -2010,11 +2036,9 @@ namespace Opm {
if (cc.size() > 1) {
ss << " on rank " << cc.rank();
}
well_state.setCurrentInjectionGroupControl(group.name(), newControl);
well_state.setCurrentInjectionGroupControl(controlPhase, group.name(), newControl);
}
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
const Phase& topUpPhase = group.injectionControls(summaryState).phase;
wellGroupHelpers::setGroupControl(group, schedule(), topUpPhase, reportStepIdx, /*isInjector*/true, well_state, ss);
wellGroupHelpers::setGroupControl(group, schedule(), controlPhase, reportStepIdx, /*isInjector*/true, well_state, ss);
if (!ss.str().empty())
deferred_logger.info(ss.str());
@ -2033,7 +2057,7 @@ namespace Opm {
if (group.isProductionGroup())
return;
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(group.name());
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(Phase::GAS, group.name());
if( currentGroupControl == Group::InjectionCMode::REIN ) {
int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
double gasProductionRate = wellGroupHelpers::sumWellRates(group, schedule, wellState, reportStepIdx, gasPos, /*isInjector*/false);

View File

@ -2126,8 +2126,43 @@ namespace Opm
assembleGroupInjectionControl(const Group& group, const WellState& well_state, const Opm::Schedule& schedule, const SummaryState& summaryState, const Well::InjectorType& injectorType, EvalWell& control_eq, double efficiencyFactor, Opm::DeferredLogger& deferred_logger)
{
const auto& well = well_ecl_;
const auto pu = phaseUsage();
const Group::InjectionCMode& currentGroupControl = well_state.currentInjectionGroupControl(group.name());
const auto& pu = phaseUsage();
int phasePos;
Well::GuideRateTarget wellTarget;
Phase injectionPhase;
double scaling = 1.0;
switch (injectorType) {
case Well::InjectorType::WATER:
{
phasePos = pu.phase_pos[BlackoilPhases::Aqua];
wellTarget = Well::GuideRateTarget::WAT;
injectionPhase = Phase::WATER;
scaling = scalingFactor(pu.phase_pos[BlackoilPhases::Aqua]);
break;
}
case Well::InjectorType::OIL:
{
phasePos = pu.phase_pos[BlackoilPhases::Liquid];
wellTarget = Well::GuideRateTarget::OIL;
injectionPhase = Phase::OIL;
scaling = scalingFactor(pu.phase_pos[BlackoilPhases::Liquid]);
break;
}
case Well::InjectorType::GAS:
{
phasePos = pu.phase_pos[BlackoilPhases::Vapour];
wellTarget = Well::GuideRateTarget::GAS;
injectionPhase = Phase::GAS;
scaling = scalingFactor(pu.phase_pos[BlackoilPhases::Vapour]);
break;
}
default:
throw("Expected WATER, OIL or GAS as type for injectors " + well.name());
}
const Group::InjectionCMode& currentGroupControl = well_state.currentInjectionGroupControl(injectionPhase, group.name());
if (currentGroupControl == Group::InjectionCMode::FLD) {
// Inject share of parents control
const auto& parent = schedule.getGroup( group.parent(), current_step_ );
@ -2145,42 +2180,12 @@ namespace Opm
return;
}
const auto& groupcontrols = group.injectionControls(summaryState);
int phasePos;
Well::GuideRateTarget wellTarget;
double scaling = 1.0;
switch (injectorType) {
case Well::InjectorType::WATER:
{
phasePos = pu.phase_pos[BlackoilPhases::Aqua];
wellTarget = Well::GuideRateTarget::WAT;
scaling = scalingFactor(pu.phase_pos[BlackoilPhases::Aqua]);
break;
}
case Well::InjectorType::OIL:
{
phasePos = pu.phase_pos[BlackoilPhases::Liquid];
wellTarget = Well::GuideRateTarget::OIL;
scaling = scalingFactor(pu.phase_pos[BlackoilPhases::Liquid]);
break;
}
case Well::InjectorType::GAS:
{
phasePos = pu.phase_pos[BlackoilPhases::Vapour];
wellTarget = Well::GuideRateTarget::GAS;
scaling = scalingFactor(pu.phase_pos[BlackoilPhases::Vapour]);
break;
}
default:
throw("Expected WATER, OIL or GAS as type for injectors " + well.name());
}
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, current_step_, phasePos, fraction);
wellGroupHelpers::accumulateGroupInjectionPotentialFractions(well.groupName(), group.name(), schedule, well_state, pu, current_step_, injectionPhase, fraction);
switch(currentGroupControl) {
case Group::InjectionCMode::NONE:

View File

@ -983,8 +983,38 @@ namespace Opm
{
const auto& well = well_ecl_;
const auto pu = phaseUsage();
const auto& groupcontrols = group.injectionControls(summaryState);
const Group::InjectionCMode& currentGroupControl = well_state.currentInjectionGroupControl(group.name());
int phasePos;
Well::GuideRateTarget wellTarget;
Phase injectionPhase;
switch (injectorType) {
case Well::InjectorType::WATER:
{
phasePos = pu.phase_pos[BlackoilPhases::Aqua];
wellTarget = Well::GuideRateTarget::WAT;
injectionPhase = Phase::WATER;
break;
}
case Well::InjectorType::OIL:
{
phasePos = pu.phase_pos[BlackoilPhases::Liquid];
wellTarget = Well::GuideRateTarget::OIL;
injectionPhase = Phase::OIL;
break;
}
case Well::InjectorType::GAS:
{
phasePos = pu.phase_pos[BlackoilPhases::Vapour];
wellTarget = Well::GuideRateTarget::GAS;
injectionPhase = Phase::GAS;
break;
}
default:
throw("Expected WATER, OIL or GAS as type for injectors " + well.name());
}
const auto& groupcontrols = group.injectionControls(injectionPhase, summaryState);
const Group::InjectionCMode& currentGroupControl = well_state.currentInjectionGroupControl(injectionPhase, group.name());
if (currentGroupControl == Group::InjectionCMode::FLD) {
// Inject share of parents control
@ -1004,36 +1034,12 @@ namespace Opm
}
int phasePos;
Well::GuideRateTarget wellTarget;
switch (injectorType) {
case Well::InjectorType::WATER:
{
phasePos = pu.phase_pos[BlackoilPhases::Aqua];
wellTarget = Well::GuideRateTarget::WAT;
break;
}
case Well::InjectorType::OIL:
{
phasePos = pu.phase_pos[BlackoilPhases::Liquid];
wellTarget = Well::GuideRateTarget::OIL;
break;
}
case Well::InjectorType::GAS:
{
phasePos = pu.phase_pos[BlackoilPhases::Vapour];
wellTarget = Well::GuideRateTarget::GAS;
break;
}
default:
throw("Expected WATER, OIL or GAS as type for injectors " + well.name());
}
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, current_step_, phasePos, fraction);
wellGroupHelpers::accumulateGroupInjectionPotentialFractions(well.groupName(), group.name(), schedule, well_state, pu, current_step_, injectionPhase, fraction);
switch(currentGroupControl) {
case Group::InjectionCMode::NONE:
{
@ -1061,7 +1067,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));
control_eq = getWQTotal() - fraction * target;
control_eq = getWQTotal() - fraction * target;
break;
}
case Group::InjectionCMode::VREP:
@ -1074,13 +1080,17 @@ namespace Opm
double injReduction = 0.0;
if (groupcontrols.phase != Phase::WATER)
injReduction += groupInjectionReductions[pu.phase_pos[BlackoilPhases::Aqua]]*convert_coeff[pu.phase_pos[BlackoilPhases::Aqua]];
injReduction += wellGroupHelpers::sumWellPhaseRates(well_state.wellReservoirRates(), group, schedule, well_state, current_step_, pu.phase_pos[BlackoilPhases::Aqua], true);
// injReduction += groupInjectionReductions[pu.phase_pos[BlackoilPhases::Aqua]]*convert_coeff[pu.phase_pos[BlackoilPhases::Aqua]];
if (groupcontrols.phase != Phase::OIL)
injReduction += groupInjectionReductions[pu.phase_pos[BlackoilPhases::Liquid]]*convert_coeff[pu.phase_pos[BlackoilPhases::Liquid]];
injReduction += wellGroupHelpers::sumWellPhaseRates(well_state.wellReservoirRates(), group, schedule, well_state, current_step_, pu.phase_pos[BlackoilPhases::Liquid], true);
//injReduction += groupInjectionReductions[pu.phase_pos[BlackoilPhases::Liquid]]*convert_coeff[pu.phase_pos[BlackoilPhases::Liquid]];
if (groupcontrols.phase != Phase::GAS)
injReduction += groupInjectionReductions[pu.phase_pos[BlackoilPhases::Vapour]]*convert_coeff[pu.phase_pos[BlackoilPhases::Vapour]];
injReduction += wellGroupHelpers::sumWellPhaseRates(well_state.wellReservoirRates(), group, schedule, well_state, current_step_, pu.phase_pos[BlackoilPhases::Vapour], true);
//injReduction += groupInjectionReductions[pu.phase_pos[BlackoilPhases::Vapour]]*convert_coeff[pu.phase_pos[BlackoilPhases::Vapour]];
voidageRate -= injReduction;

View File

@ -29,14 +29,13 @@ namespace Opm {
namespace wellGroupHelpers
{
inline void setGroupControl(const Group& group, const Schedule& schedule, const Phase& topUpPhase, const int reportStepIdx, const bool injector, WellStateFullyImplicitBlackoil& wellState, std::ostringstream& ss) {
inline void setGroupControl(const Group& group, const Schedule& schedule, const Phase& groupInjectionPhase, const int reportStepIdx, const bool injector, WellStateFullyImplicitBlackoil& wellState, std::ostringstream& ss) {
for (const std::string& groupName : group.groups()) {
const Group& groupTmp = schedule.getGroup(groupName, reportStepIdx);
setGroupControl(groupTmp, schedule, topUpPhase, reportStepIdx, injector, wellState, ss);
setGroupControl(groupTmp, schedule, groupInjectionPhase, reportStepIdx, injector, wellState, ss);
if (injector) {
if (groupTmp.injection_phase() == topUpPhase || wellState.currentInjectionGroupControl(groupName) == Group::InjectionCMode::NONE) // only switch sub groups with same phase or NONE
wellState.setCurrentInjectionGroupControl(groupName, Group::InjectionCMode::FLD);
wellState.setCurrentInjectionGroupControl(groupInjectionPhase, groupName, Group::InjectionCMode::FLD);
} else {
wellState.setCurrentProductionGroupControl(groupName, Group::ProductionCMode::FLD);
}
@ -69,13 +68,13 @@ namespace Opm {
// Get the current controls.
const Well::InjectorType& injectorType = wellEcl.getInjectionProperties().injectorType;
if (injectorType == Well::InjectorType::WATER && topUpPhase != Phase::WATER)
if (injectorType == Well::InjectorType::WATER && groupInjectionPhase != Phase::WATER)
continue;
if (injectorType == Well::InjectorType::OIL && topUpPhase != Phase::OIL)
if (injectorType == Well::InjectorType::OIL && groupInjectionPhase != Phase::OIL)
continue;
if (injectorType == Well::InjectorType::GAS && topUpPhase != Phase::GAS)
if (injectorType == Well::InjectorType::GAS && groupInjectionPhase != Phase::GAS)
continue;
if (injectorType == Well::InjectorType::MULTI)
@ -96,16 +95,25 @@ namespace Opm {
}
// use NONE as default control
if (!wellState.hasInjectionGroupControl(group.name())) {
wellState.setCurrentInjectionGroupControl(group.name(), Group::InjectionCMode::NONE);
const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS};
for (Phase phase : all) {
if (!wellState.hasInjectionGroupControl(phase, group.name())) {
wellState.setCurrentInjectionGroupControl(phase, group.name(), Group::InjectionCMode::NONE);
}
}
if (!wellState.hasProductionGroupControl(group.name())) {
wellState.setCurrentProductionGroupControl(group.name(), Group::ProductionCMode::NONE);
}
if (group.isInjectionGroup() && schedule.hasWellGroupEvent(group.name(), ScheduleEvents::GROUP_INJECTION_UPDATE, reportStepIdx)) {
const auto controls = group.injectionControls(summaryState);
wellState.setCurrentInjectionGroupControl(group.name(), controls.cmode);
if (group.isInjectionGroup() && schedule.hasWellGroupEvent(group.name(), ScheduleEvents::GROUP_INJECTION_UPDATE, reportStepIdx)) {
for (Phase phase : all) {
if (!group.hasInjectionControl(phase))
continue;
const auto& controls = group.injectionControls(phase, summaryState);
wellState.setCurrentInjectionGroupControl(phase, group.name(), controls.cmode);
}
}
if (group.isProductionGroup() && schedule.hasWellGroupEvent(group.name(), ScheduleEvents::GROUP_PRODUCTION_UPDATE, reportStepIdx)) {
@ -114,7 +122,7 @@ namespace Opm {
}
if (schedule.gConSale(reportStepIdx).has(group.name())) {
wellState.setCurrentInjectionGroupControl(group.name(), Group::InjectionCMode::SALE);
wellState.setCurrentInjectionGroupControl(Phase::GAS, group.name(), Group::InjectionCMode::SALE);
std::ostringstream ss;
setGroupControl(group, schedule, Phase::GAS, reportStepIdx, /*injector*/true, wellState, ss);
}
@ -240,22 +248,34 @@ namespace Opm {
return rate;
}
inline void updateGroupTargetReduction(const Group& group, const Schedule& schedule, const int reportStepIdx, const bool isInjector, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState, std::vector<double>& groupTargetReduction)
inline void updateGroupTargetReduction(const Group& group, const Schedule& schedule, const int reportStepIdx, const bool isInjector, const PhaseUsage& pu, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState, std::vector<double>& groupTargetReduction)
{
const int np = wellState.numPhases();
for (const std::string& groupName : group.groups()) {
std::vector<double> thisGroupTargetReduction(np, 0.0);
const Group& groupTmp = schedule.getGroup(groupName, reportStepIdx);
updateGroupTargetReduction(groupTmp, schedule, reportStepIdx, isInjector, wellStateNupcol, wellState, thisGroupTargetReduction);
updateGroupTargetReduction(groupTmp, schedule, reportStepIdx, isInjector, pu, wellStateNupcol, wellState, thisGroupTargetReduction);
// accumulate group contribution from sub group
if (isInjector) {
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(groupName);
if (currentGroupControl != Group::InjectionCMode::FLD) {
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] += sumWellRates(groupTmp, schedule, wellStateNupcol, reportStepIdx, phase, isInjector);
const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS};
for (Phase phase : all) {
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(phase, groupName);
int phasePos;
if (phase == Phase::GAS)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Vapour] ];
else if (phase == Phase::OIL)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Liquid] ];
else if (phase == Phase::WATER)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Aqua] ];
else
throw("invalid phase");
if (currentGroupControl != Group::InjectionCMode::FLD) {
groupTargetReduction[phasePos] += sumWellRates(groupTmp, schedule, wellStateNupcol, reportStepIdx, phasePos, isInjector);
} else {
groupTargetReduction[phasePos] += thisGroupTargetReduction[phasePos];
}
continue;
}
} else {
const Group::ProductionCMode& currentGroupControl = wellState.currentProductionGroupControl(groupName);
@ -263,13 +283,13 @@ namespace Opm {
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] += sumWellRates(groupTmp, schedule, wellStateNupcol, reportStepIdx, phase, isInjector);
}
continue;
} else {
// or accumulate directly from the wells if controled from its parents
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] += thisGroupTargetReduction[phase];
}
}
}
// or accumulate directly from the wells if controled from its parents
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] += thisGroupTargetReduction[phase];
}
}
for (const std::string& wellName : group.wells()) {
const auto& wellTmp = schedule.getWell(wellName, reportStepIdx);
@ -320,19 +340,34 @@ namespace Opm {
// accumulate group contribution from sub group if FLD
if (isInjector) {
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(groupName);
if (currentGroupControl != Group::InjectionCMode::FLD) {
continue;
const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS};
for (Phase phase : all) {
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(phase, groupName);
if (currentGroupControl != Group::InjectionCMode::FLD) {
continue;
}
int phasePos;
if (phase == Phase::GAS)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Vapour] ];
else if (phase == Phase::OIL)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Liquid] ];
else if (phase == Phase::WATER)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Aqua] ];
else
throw("invalid phase");
pot[phasePos] += thisPot[phasePos];
}
} else {
const Group::ProductionCMode& currentGroupControl = wellState.currentProductionGroupControl(groupName);
if (currentGroupControl != Group::ProductionCMode::FLD) {
continue;
}
for (int phase = 0; phase < np; phase++) {
pot[phase] += thisPot[phase];
}
}
for (int phase = 0; phase < np; phase++) {
pot[phase] += thisPot[phase];
}
}
for (const std::string& wellName : group.wells()) {
const auto& wellTmp = schedule.getWell(wellName, reportStepIdx);
@ -523,12 +558,22 @@ namespace Opm {
return;
}
inline double groupFractionFromInjectionPotentials(const Group& group, const Schedule& schedule, const WellStateFullyImplicitBlackoil& wellState, const int reportStepIdx, const int phasePos) {
inline double groupFractionFromInjectionPotentials(const Group& group, const Schedule& schedule, const WellStateFullyImplicitBlackoil& wellState, const PhaseUsage& pu, const int reportStepIdx, const Phase& injectionPhase) {
double groupTotalGuideRate = 0.0;
const Group& groupParent = schedule.getGroup(group.parent(), reportStepIdx);
int phasePos;
if (injectionPhase == Phase::GAS)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Vapour] ];
else if (injectionPhase == Phase::OIL)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Liquid] ];
else if (injectionPhase == Phase::WATER)
phasePos = pu.phase_pos[ pu.phase_pos[BlackoilPhases::Aqua] ];
else
throw("invalid phase");
for (const std::string& groupName : groupParent.groups()) {
// only count group under group control from its parent
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(groupName);
const Group::InjectionCMode& currentGroupControl = wellState.currentInjectionGroupControl(injectionPhase, groupName);
if (currentGroupControl != Group::InjectionCMode::FLD)
continue;
@ -541,11 +586,11 @@ namespace Opm {
return groupGuideRate / groupTotalGuideRate;
}
inline void accumulateGroupInjectionPotentialFractions(const std::string& groupName, const std::string& controlGroupName, const Schedule& schedule, const WellStateFullyImplicitBlackoil& wellState,const int reportStepIdx, const int phasePos, double& fraction) {
inline void accumulateGroupInjectionPotentialFractions(const std::string& groupName, const std::string& controlGroupName, const Schedule& schedule, const WellStateFullyImplicitBlackoil& wellState, const PhaseUsage& pu, const int reportStepIdx, const Phase& injectionPhase, double& fraction) {
const Group& group = schedule.getGroup(groupName, reportStepIdx);
if (groupName != controlGroupName) {
fraction *= groupFractionFromInjectionPotentials(group, schedule, wellState, reportStepIdx, phasePos);
accumulateGroupInjectionPotentialFractions(group.parent(), controlGroupName, schedule, wellState, reportStepIdx, phasePos, fraction);
fraction *= groupFractionFromInjectionPotentials(group, schedule, wellState, pu, reportStepIdx, injectionPhase);
accumulateGroupInjectionPotentialFractions(group.parent(), controlGroupName, schedule, wellState, pu, reportStepIdx, injectionPhase, fraction);
}
return;
}

View File

@ -319,8 +319,8 @@ namespace Opm
return current_production_group_controls_.count(groupName) > 0;
}
bool hasInjectionGroupControl(const std::string& groupName) {
return current_injection_group_controls_.count(groupName) > 0;
bool hasInjectionGroupControl(const Opm::Phase& phase, const std::string& groupName) {
return current_injection_group_controls_.count(std::make_pair(phase, groupName)) > 0;
}
/// One current control per group.
@ -337,14 +337,14 @@ namespace Opm
}
/// One current control per group.
void setCurrentInjectionGroupControl(const std::string& groupName, const Group::InjectionCMode& groupControl ) {
current_injection_group_controls_[groupName] = groupControl;
void setCurrentInjectionGroupControl(const Opm::Phase& phase, const std::string& groupName, const Group::InjectionCMode& groupControl ) {
current_injection_group_controls_[std::make_pair(phase, groupName)] = groupControl;
}
const Group::InjectionCMode& currentInjectionGroupControl(const std::string& groupName) const {
auto it = current_injection_group_controls_.find(groupName);
const Group::InjectionCMode& currentInjectionGroupControl(const Opm::Phase& phase, const std::string& groupName) const {
auto it = current_injection_group_controls_.find(std::make_pair(phase, groupName));
if (it == current_injection_group_controls_.end())
OPM_THROW(std::logic_error, "Could not find any control for injection group " << groupName);
OPM_THROW(std::logic_error, "Could not find any control for " << phase << " injection group " << groupName);
return it->second;
}
@ -912,7 +912,7 @@ namespace Opm
std::map<std::string, int> wellNameToGlobalIdx_;
std::map<std::string, Group::ProductionCMode> current_production_group_controls_;
std::map<std::string, Group::InjectionCMode> current_injection_group_controls_;
std::map<std::pair<Opm::Phase, std::string>, Group::InjectionCMode> current_injection_group_controls_;
std::map<std::string, std::vector<double>> production_group_reduction_rates;
std::map<std::string, std::vector<double>> injection_group_reduction_rates;

View File

@ -1710,12 +1710,14 @@ BOOST_AUTO_TEST_CASE(Group)
{
#ifdef HAVE_MPI
Opm::UnitSystem unitSystem;
std::map<Opm::Phase, Opm::Group::GroupInjectionProperties> injection;
Opm::Group val1("test1", 1, 2, 3.0, unitSystem,
Opm::Group::GroupType::PRODUCTION,
4.0, true, 5, "test2",
Opm::IOrderSet<std::string>({"test3", "test4"}, {"test3","test4"}),
Opm::IOrderSet<std::string>({"test5", "test6"}, {"test5","test6"}),
Opm::Group::GroupInjectionProperties(),
injection,
Opm::Group::GroupProductionProperties());
auto val2 = PackUnpack(val1);
@ -2126,12 +2128,13 @@ BOOST_AUTO_TEST_CASE(Schedule)
Opm::Schedule::WellMap wells;
wells.insert({"test", {{std::make_shared<Opm::Well>(getFullWell())},1}});
Opm::Schedule::GroupMap groups;
std::map<Opm::Phase, Opm::Group::GroupInjectionProperties> injection;
groups.insert({"test", {{std::make_shared<Opm::Group>("test1", 1, 2, 3.0, unitSystem,
Opm::Group::GroupType::PRODUCTION,
4.0, true, 5, "test2",
Opm::IOrderSet<std::string>({"test3", "test4"}, {"test3","test4"}),
Opm::IOrderSet<std::string>({"test5", "test6"}, {"test5","test6"}),
Opm::Group::GroupInjectionProperties(),
injection,
Opm::Group::GroupProductionProperties())},1}});
using VapType = Opm::OilVaporizationProperties::OilVaporization;
Opm::DynamicState<Opm::OilVaporizationProperties> oilvap{{Opm::OilVaporizationProperties(VapType::VAPPARS,