mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
allow for multiple group injection phases
This commit is contained in:
parent
a840c4f418
commit
469ffa2cbe
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user