Merge pull request #2210 from totto82/gconsalesump

Support for Gconsale and Gconsump
This commit is contained in:
Atgeirr Flø Rasmussen 2019-12-06 15:01:49 +01:00 committed by GitHub
commit 52b9ecbfd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 169 additions and 54 deletions

View File

@ -806,20 +806,17 @@ namespace Opm {
calculateExplicitQuantities(local_deferredLogger);
prepareTimeStep(local_deferredLogger);
}
updateWellControls(local_deferredLogger, true);
updateWellControls(local_deferredLogger, /*allow for switching to group controls*/true);
// only check group controls for iterationIdx smaller then nupcol
// only update REIN and VREP rates if iterationIdx is smaller than nupcol
const int reportStepIdx = ebosSimulator_.episodeIndex();
const int nupcol = schedule().getNupcol(reportStepIdx);
if (iterationIdx < nupcol) {
if( localWellsActive() ) {
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
std::vector<double> groupTargetReduction(numPhases(), 0.0);
wellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ false, well_state_, groupTargetReduction);
std::vector<double> groupTargetReductionInj(numPhases(), 0.0);
wellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ true, well_state_, groupTargetReductionInj);
std::vector<double> rein(numPhases(), 0.0);
wellGroupHelpers::updateREINForGroups(fieldGroup, schedule(), reportStepIdx, well_state_, rein);
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
wellGroupHelpers::updateREINForGroups(fieldGroup, schedule(), reportStepIdx, phase_usage_, summaryState, well_state_, rein);
double resv = 0.0;
wellGroupHelpers::updateVREPForGroups(fieldGroup, schedule(), reportStepIdx, well_state_, resv);
}
@ -1145,16 +1142,26 @@ namespace Opm {
// For no well active globally we simply return.
if( !wellsActive() ) return ;
const int reportStepIdx = ebosSimulator_.episodeIndex();
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
// update group controls
if (checkGroupControl) {
const int reportStepIdx = ebosSimulator_.episodeIndex();
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
checkGroupConstraints(fieldGroup, deferred_logger);
}
for (const auto& well : well_container_) {
well->updateWellControl(ebosSimulator_, well_state_, deferred_logger);
}
// 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
if( localWellsActive() ) {
std::vector<double> groupTargetReduction(numPhases(), 0.0);
wellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ false, well_state_, groupTargetReduction);
std::vector<double> groupTargetReductionInj(numPhases(), 0.0);
wellGroupHelpers::updateGroupTargetReduction(fieldGroup, schedule(), reportStepIdx, /*isInjector*/ true, well_state_, groupTargetReductionInj);
}
}
@ -1723,8 +1730,41 @@ namespace Opm {
//OPM_THROW(std::runtime_error, "Group " + group.name() + "FLD control for injecting groups not implemented" );
}
} else if (group.isProductionGroup())
{
// Handle GCONSALE
if (schedule().gConSale(reportStepIdx).has(group.name())) {
if (controls.phase != Phase::GAS)
OPM_THROW(std::runtime_error, "Group " + group.name() + " has GCONSALE control but is not a GAS group" );
const auto& gconsale = schedule().gConSale(reportStepIdx).get(group.name(), summaryState);
double sales_rate = 0.0;
int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
sales_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, gasPos, /*isInjector*/false);
sales_rate -= wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, gasPos, /*isInjector*/true);
// add import rate and substract consumption rate for group for gas
if (schedule().gConSump(reportStepIdx).has(group.name())) {
const auto& gconsump = schedule().gConSump(reportStepIdx).get(group.name(), summaryState);
if (phase_usage_.phase_used[BlackoilPhases::Vapour]) {
sales_rate += gconsump.import_rate;
sales_rate -= gconsump.consumption_rate;
}
}
if (sales_rate > gconsale.max_sales_rate) {
OPM_THROW(std::runtime_error, "Group " + group.name() + " has sale rate more then the maximum permitted value. Not implemented in Flow" );
}
if (sales_rate < gconsale.min_sales_rate) {
OPM_THROW(std::runtime_error, "Group " + group.name() + " has sale rate less then minimum permitted value. Not implemented in Flow" );
}
if (gconsale.sales_target < 0.0) {
OPM_THROW(std::runtime_error, "Group " + group.name() + " has sale rate target less then zero. Not implemented in Flow" );
}
}
}
if (group.isProductionGroup()) {
const auto controls = group.productionControls(summaryState);
if (group.has_control(Group::ProductionCMode::NONE))

View File

@ -2180,8 +2180,8 @@ namespace Opm
throw("Expected WATER, OIL or GAS as type for injectors " + well.name());
}
const std::vector<double>& groupTargetReductions = well_state.currentProductionGroupReductionRates(group.name());
double groupTargetReduction = groupTargetReductions[phasePos];
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::accumulateGroupFractions(well.groupName(), group.name(), schedule, well_state, current_step_, Base::guide_rate_, groupTarget, /*isInjector*/true, fraction);
@ -2209,7 +2209,7 @@ namespace Opm
}
case Group::InjectionCMode::REIN:
{
double productionRate = well_state.currentInjectionVREPRates(groupcontrols.reinj_group);
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 = getSegmentGTotal(0) / scaling - fraction * target;
@ -2220,10 +2220,25 @@ 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 voidageRate = well_state.currentInjectionVREPRates(groupcontrols.voidage_group);
double voidageRate = well_state.currentInjectionVREPRates(groupcontrols.voidage_group)*groupcontrols.target_void_fraction;
double injReduction = 0.0;
if (groupcontrols.phase != Phase::WATER)
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]];
if (groupcontrols.phase != Phase::GAS)
injReduction += groupInjectionReductions[pu.phase_pos[BlackoilPhases::Vapour]]*convert_coeff[pu.phase_pos[BlackoilPhases::Vapour]];
voidageRate -= injReduction;
voidageRate /= efficiencyFactor;
double target = std::max(0.0, ( groupcontrols.target_void_fraction*voidageRate/coeff - groupTargetReduction));
control_eq = getSegmentGTotal(0) / scaling - fraction * target ;
double target = std::max(0.0, ( voidageRate/coeff - groupTargetReduction));
control_eq = getSegmentGTotal(0) / scaling - fraction * target;
break;
}
case Group::InjectionCMode::FLD:
@ -2232,6 +2247,28 @@ namespace Opm
assert(false);
break;
}
case Group::InjectionCMode::SALE:
{
// only for gas injectors
assert (phasePos == pu.phase_pos[BlackoilPhases::Vapour]);
// Gas injection rate = Total gas production rate + gas import rate - gas consumption rate - sales rate;
double inj_rate = well_state.currentInjectionREINRates(group.name())[phasePos];
if (schedule.gConSump(current_step_).has(group.name())) {
const auto& gconsump = schedule.gConSump(current_step_).get(group.name(), summaryState);
if (pu.phase_used[BlackoilPhases::Vapour]) {
inj_rate += gconsump.import_rate;
inj_rate -= gconsump.consumption_rate;
}
}
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));
control_eq = getSegmentGTotal(0) /scaling - fraction * target;
break;
}
default:
OPM_DEFLOG_THROW(std::runtime_error, "Unvalid group control specified for group " + well.groupName(), deferred_logger );

View File

@ -1051,7 +1051,7 @@ namespace Opm
}
case Group::InjectionCMode::REIN:
{
double productionRate = well_state.currentInjectionVREPRates(groupcontrols.reinj_group);
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;
@ -1062,7 +1062,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 voidageRate = well_state.currentInjectionVREPRates(groupcontrols.voidage_group);
double voidageRate = well_state.currentInjectionVREPRates(groupcontrols.voidage_group)*groupcontrols.target_void_fraction;
double injReduction = 0.0;
@ -1079,7 +1079,7 @@ namespace Opm
voidageRate /= efficiencyFactor;
double target = std::max(0.0, ( groupcontrols.target_void_fraction*voidageRate/coeff - groupTargetReduction));
double target = std::max(0.0, ( voidageRate/coeff - groupTargetReduction));
control_eq = getWQTotal() - fraction * target;
break;
}
@ -1089,6 +1089,28 @@ namespace Opm
assert(false);
break;
}
case Group::InjectionCMode::SALE:
{
// only for gas injectors
assert (phasePos == pu.phase_pos[BlackoilPhases::Vapour]);
// Gas injection rate = Total gas production rate + gas import rate - gas consumption rate - sales rate;
double inj_rate = well_state.currentInjectionREINRates(group.name())[phasePos];
if (schedule.gConSump(current_step_).has(group.name())) {
const auto& gconsump = schedule.gConSump(current_step_).get(group.name(), summaryState);
if (pu.phase_used[BlackoilPhases::Vapour]) {
inj_rate += gconsump.import_rate;
inj_rate -= gconsump.consumption_rate;
}
}
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));
control_eq = getWQTotal() - fraction * target;
break;
}
default:
OPM_DEFLOG_THROW(std::runtime_error, "Unvalid group control specified for group " + well.groupName(), deferred_logger );
}

View File

@ -29,38 +29,6 @@ namespace Opm {
namespace wellGroupHelpers
{
inline void setCmodeGroup(const Group& group, const Schedule& schedule, const SummaryState& summaryState, const int reportStepIdx, WellStateFullyImplicitBlackoil& wellState) {
for (const std::string& groupName : group.groups()) {
setCmodeGroup( schedule.getGroup(groupName, reportStepIdx), schedule, summaryState, reportStepIdx, wellState);
}
// use NONE as default control
if (!wellState.hasInjectionGroupControl(group.name())) {
wellState.setCurrentInjectionGroupControl(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.isProductionGroup() && schedule.hasWellGroupEvent(group.name(), ScheduleEvents::GROUP_PRODUCTION_UPDATE, reportStepIdx)) {
const auto controls = group.productionControls(summaryState);
wellState.setCurrentProductionGroupControl(group.name(), controls.cmode);
}
}
inline void accumulateGroupEfficiencyFactor(const Group& group, const Schedule& schedule, const int reportStepIdx, double& factor) {
factor *= group.getGroupEfficiencyFactor();
if (group.parent() != "FIELD")
accumulateGroupEfficiencyFactor(schedule.getGroup(group.parent(), reportStepIdx), schedule, reportStepIdx, factor);
}
inline void setGroupControl(const Group& group, const Schedule& schedule, const int reportStepIdx, const bool injector, WellStateFullyImplicitBlackoil& wellState, std::ostringstream& ss) {
for (const std::string& groupName : group.groups()) {
@ -107,6 +75,44 @@ namespace Opm {
}
}
inline void setCmodeGroup(const Group& group, const Schedule& schedule, const SummaryState& summaryState, const int reportStepIdx, WellStateFullyImplicitBlackoil& wellState) {
for (const std::string& groupName : group.groups()) {
setCmodeGroup( schedule.getGroup(groupName, reportStepIdx), schedule, summaryState, reportStepIdx, wellState);
}
// use NONE as default control
if (!wellState.hasInjectionGroupControl(group.name())) {
wellState.setCurrentInjectionGroupControl(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.isProductionGroup() && schedule.hasWellGroupEvent(group.name(), ScheduleEvents::GROUP_PRODUCTION_UPDATE, reportStepIdx)) {
const auto controls = group.productionControls(summaryState);
wellState.setCurrentProductionGroupControl(group.name(), controls.cmode);
}
if (schedule.gConSale(reportStepIdx).has(group.name())) {
wellState.setCurrentInjectionGroupControl(group.name(), Group::InjectionCMode::SALE);
std::ostringstream ss;
setGroupControl(group, schedule, reportStepIdx, /*injector*/true, wellState, ss);
}
}
inline void accumulateGroupEfficiencyFactor(const Group& group, const Schedule& schedule, const int reportStepIdx, double& factor) {
factor *= group.getGroupEfficiencyFactor();
if (group.parent() != "FIELD")
accumulateGroupEfficiencyFactor(schedule.getGroup(group.parent(), reportStepIdx), schedule, reportStepIdx, factor);
}
inline void computeGroupTargetReduction(const Group& group, const WellStateFullyImplicitBlackoil& wellState, const Schedule& schedule, const int reportStepIdx, const int phasePos, const bool isInjector, double& groupTargetReduction )
{
@ -332,12 +338,12 @@ namespace Opm {
wellState.setCurrentInjectionVREPRates(group.name(), resv);
}
inline void updateREINForGroups(const Group& group, const Schedule& schedule, const int reportStepIdx, WellStateFullyImplicitBlackoil& wellState, std::vector<double>& rein) {
inline void updateREINForGroups(const Group& group, const Schedule& schedule, const int reportStepIdx, const PhaseUsage& pu, const SummaryState& st, WellStateFullyImplicitBlackoil& wellState, std::vector<double>& rein) {
const int np = wellState.numPhases();
for (const std::string& groupName : group.groups()) {
const Group& groupTmp = schedule.getGroup(groupName, reportStepIdx);
std::vector<double> thisRein(np, 0.0);
updateREINForGroups(groupTmp, schedule, reportStepIdx, wellState, thisRein);
updateREINForGroups(groupTmp, schedule, reportStepIdx, pu, st, wellState, thisRein);
for (int phase = 0; phase < np; ++phase) {
rein[phase] = thisRein[phase];
}
@ -345,6 +351,16 @@ namespace Opm {
for (int phase = 0; phase < np; ++phase) {
rein[phase] = sumWellPhaseRates(wellState.wellRates(), group, schedule, wellState, reportStepIdx, phase, /*isInjector*/ false);
}
// add import rate and substract consumption rate for group for gas
if (schedule.gConSump(reportStepIdx).has(group.name())) {
const auto& gconsump = schedule.gConSump(reportStepIdx).get(group.name(), st);
if (pu.phase_used[BlackoilPhases::Vapour]) {
rein[pu.phase_pos[BlackoilPhases::Vapour]] += gconsump.import_rate;
rein[pu.phase_pos[BlackoilPhases::Vapour]] -= gconsump.consumption_rate;
}
}
wellState.setCurrentInjectionREINRates(group.name(), rein);
}