Various fixes and refactoring.

- Communicate all well rates.
 - When changing controls, modify rates to satisfy failed constraint.
 - Ensure targets are positive.
 - Always solve for potentials for MSW (temporary fix).
This commit is contained in:
Tor Harald Sandve 2020-03-24 09:24:45 +01:00 committed by Atgeirr Flø Rasmussen
parent 3a5a8c23df
commit 66931b9cb7
8 changed files with 458 additions and 311 deletions

View File

@ -86,6 +86,7 @@ namespace Opm
: status_{AllGood} : status_{AllGood}
, res_failures_{} , res_failures_{}
, well_failures_{} , well_failures_{}
, groupConverged_(true)
{ {
} }
@ -94,6 +95,7 @@ namespace Opm
status_ = AllGood; status_ = AllGood;
res_failures_.clear(); res_failures_.clear();
well_failures_.clear(); well_failures_.clear();
groupConverged_ = true;
} }
void setReservoirFailed(const ReservoirFailure& rf) void setReservoirFailed(const ReservoirFailure& rf)
@ -107,7 +109,12 @@ namespace Opm
status_ = static_cast<Status>(status_ | WellFailed); status_ = static_cast<Status>(status_ | WellFailed);
well_failures_.push_back(wf); well_failures_.push_back(wf);
} }
void setGroupConverged(const bool groupConverged)
{
groupConverged_ = groupConverged;
}
ConvergenceReport& operator+=(const ConvergenceReport& other) ConvergenceReport& operator+=(const ConvergenceReport& other)
{ {
status_ = static_cast<Status>(status_ | other.status_); status_ = static_cast<Status>(status_ | other.status_);
@ -122,7 +129,7 @@ namespace Opm
bool converged() const bool converged() const
{ {
return status_ == AllGood; return status_ == AllGood && groupConverged_;
} }
bool reservoirFailed() const bool reservoirFailed() const
@ -167,6 +174,7 @@ namespace Opm
Status status_; Status status_;
std::vector<ReservoirFailure> res_failures_; std::vector<ReservoirFailure> res_failures_;
std::vector<WellFailure> well_failures_; std::vector<WellFailure> well_failures_;
bool groupConverged_;
}; };
} // namespace Opm } // namespace Opm

View File

@ -424,7 +424,11 @@ namespace Opm {
const Well& getWellEcl(const std::string& well_name) const; const Well& getWellEcl(const std::string& well_name) const;
void updateGroupIndividualControls(Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups); 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 updateGroupIndividualControl(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups);
bool checkGroupConstraints(const Group& group, Opm::DeferredLogger& deferred_logger) const;
Group::ProductionCMode checkGroupProductionConstraints(const Group& group, Opm::DeferredLogger& deferred_logger) const;
Group::InjectionCMode checkGroupInjectionConstraints(const Group& group, const Phase& phase, Opm::DeferredLogger& deferred_logger) const;
void updateGroupHigherControls(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 checkGroupHigherConstraints(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups);

View File

@ -1114,7 +1114,6 @@ namespace Opm {
local_report += well->getWellConvergence(well_state_, B_avg, local_deferredLogger); local_report += well->getWellConvergence(well_state_, B_avg, local_deferredLogger);
} }
} }
Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(local_deferredLogger); Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(local_deferredLogger);
if (terminal_output_) { if (terminal_output_) {
global_deferredLogger.logMessages(); global_deferredLogger.logMessages();
@ -1132,7 +1131,11 @@ namespace Opm {
} }
} }
} }
const int reportStepIdx = ebosSimulator_.episodeIndex();
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
bool violated = checkGroupConstraints(fieldGroup, global_deferredLogger);
report.setGroupConverged(!violated);
return report; return report;
} }
@ -1243,7 +1246,8 @@ namespace Opm {
wellGroupHelpers::updateVREPForGroups(fieldGroup, schedule(), reportStepIdx, well_state_nupcol_, well_state_); wellGroupHelpers::updateVREPForGroups(fieldGroup, schedule(), reportStepIdx, well_state_nupcol_, well_state_);
wellGroupHelpers::updateReservoirRatesInjectionGroups(fieldGroup, schedule(), reportStepIdx, well_state_nupcol_, well_state_); wellGroupHelpers::updateReservoirRatesInjectionGroups(fieldGroup, schedule(), reportStepIdx, well_state_nupcol_, well_state_);
wellGroupHelpers::updateGroupProductionRates(fieldGroup, schedule(), reportStepIdx, well_state_nupcol_, well_state_);
wellGroupHelpers::updateWellRates(fieldGroup, schedule(), reportStepIdx, well_state_nupcol_, well_state_);
well_state_.communicateGroupRates(comm); well_state_.communicateGroupRates(comm);
// compute wsolvent fraction for REIN wells // compute wsolvent fraction for REIN wells
@ -1736,276 +1740,336 @@ namespace Opm {
{ {
const int reportStepIdx = ebosSimulator_.episodeIndex(); const int reportStepIdx = ebosSimulator_.episodeIndex();
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx); const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
checkGroupConstraints(fieldGroup, deferred_logger, switched_groups); updateGroupIndividualControl(fieldGroup, deferred_logger, switched_groups);
} }
template<typename TypeTag> template<typename TypeTag>
void void
BlackoilWellModel<TypeTag>:: BlackoilWellModel<TypeTag>::
checkGroupConstraints(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups) { updateGroupIndividualControl(const Group& group, Opm::DeferredLogger& deferred_logger, std::set<std::string>& switched_groups) {
const int reportStepIdx = ebosSimulator_.episodeIndex(); const int reportStepIdx = ebosSimulator_.episodeIndex();
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
const auto& comm = ebosSimulator_.vanguard().grid().comm();
auto& well_state = well_state_;
const bool skip = switched_groups.count(group.name()); const bool skip = switched_groups.count(group.name());
if (!skip && group.isInjectionGroup()) if (!skip && group.isInjectionGroup())
{ {
const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS}; const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS};
for (Phase phase : all) { for (Phase phase : all) {
if (!group.hasInjectionControl(phase)) { if (!group.hasInjectionControl(phase)) {
continue; continue;
} }
int phasePos; Group::InjectionCMode newControl = checkGroupInjectionConstraints(group, phase, deferred_logger);
if (phase == Phase::GAS && phase_usage_.phase_used[BlackoilPhases::Vapour] ) if (newControl != Group::InjectionCMode::NONE)
phasePos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
else if (phase == Phase::OIL && phase_usage_.phase_used[BlackoilPhases::Liquid])
phasePos = phase_usage_.phase_pos[BlackoilPhases::Liquid];
else if (phase == Phase::WATER && phase_usage_.phase_used[BlackoilPhases::Aqua] )
phasePos = phase_usage_.phase_pos[BlackoilPhases::Aqua];
else
continue;
const auto& controls = group.injectionControls(phase, summaryState);
const Group::InjectionCMode& currentControl = well_state.currentInjectionGroupControl(phase, group.name());
if (controls.has_control(Group::InjectionCMode::RATE))
{ {
if (currentControl != Group::InjectionCMode::RATE) switched_groups.insert(group.name());
{ actionOnBrokenConstraints(group, newControl, phase, reportStepIdx, deferred_logger);
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);
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 (currentControl != Group::InjectionCMode::RESV)
{
double current_rate = 0.0;
current_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phasePos, /*isInjector*/true);
// sum over all nodes
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 (currentControl != Group::InjectionCMode::REIN)
{
double production_Rate = 0.0;
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);
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);
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 (currentControl != Group::InjectionCMode::VREP)
{
double voidage_rate = 0.0;
const Group& groupVoidage = schedule().getGroup(controls.voidage_group, reportStepIdx);
voidage_rate += wellGroupHelpers::sumWellResRates(groupVoidage, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Aqua], false);
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);
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);
if (controls.target_void_fraction*voidage_rate < total_rate) {
switched_groups.insert(group.name());
actionOnBrokenConstraints(group, Group::InjectionCMode::VREP, phase, reportStepIdx, deferred_logger);
}
}
}
// 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);
// sum over all nodes
sales_rate = comm.sum(sales_rate);
// 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" );
}
}
} }
} } else if (!skip && group.isProductionGroup())
{
if (!skip && group.isProductionGroup()) { Group::ProductionCMode newControl = checkGroupProductionConstraints(group, deferred_logger);
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
const auto controls = group.productionControls(summaryState); const auto controls = group.productionControls(summaryState);
const Group::ProductionCMode& currentControl = well_state.currentProductionGroupControl(group.name()); if (newControl != Group::ProductionCMode::NONE)
if (group.has_control(Group::ProductionCMode::ORAT))
{ {
if (currentControl != Group::ProductionCMode::ORAT) switched_groups.insert(group.name());
{ actionOnBrokenConstraints(group, controls.exceed_action, newControl, reportStepIdx, deferred_logger);
double current_rate = 0.0;
current_rate += wellGroupHelpers::sumWellRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], false);
// sum over all nodes
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);
}
}
} }
if (group.has_control(Group::ProductionCMode::WRAT))
{
if (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);
// sum over all nodes
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 (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);
// 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 (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);
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);
if (controls.liquid_target < current_rate ) {
switched_groups.insert(group.name());
actionOnBrokenConstraints(group, controls.exceed_action, Group::ProductionCMode::LRAT, reportStepIdx, deferred_logger);
}
}
}
if (group.has_control(Group::ProductionCMode::CRAT))
{
OPM_DEFLOG_THROW(std::runtime_error, "Group " + group.name() + "CRAT control for production groups not implemented" , deferred_logger);
}
if (group.has_control(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);
current_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], true);
current_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Vapour], true);
// sum over all nodes
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);
}
}
}
if (group.has_control(Group::ProductionCMode::PRBL))
{
OPM_DEFLOG_THROW(std::runtime_error, "Group " + group.name() + "PRBL control for production groups not implemented", deferred_logger);
}
} else { } else {
//neither production or injecting group FIELD? //neither production or injecting group FIELD?
} }
// call recursively down the group hiearchy // call recursively down the group hiearchy
for (const std::string& groupName : group.groups()) { for (const std::string& groupName : group.groups()) {
checkGroupConstraints( schedule().getGroup(groupName, reportStepIdx), deferred_logger, switched_groups); updateGroupIndividualControl( schedule().getGroup(groupName, reportStepIdx), deferred_logger, switched_groups);
}
}
template<typename TypeTag>
bool
BlackoilWellModel<TypeTag>::
checkGroupConstraints(const Group& group, Opm::DeferredLogger& deferred_logger) const {
const int reportStepIdx = ebosSimulator_.episodeIndex();
if (group.isInjectionGroup())
{
const Phase all[] = {Phase::WATER, Phase::OIL, Phase::GAS};
for (Phase phase : all) {
if (!group.hasInjectionControl(phase)) {
continue;
}
Group::InjectionCMode newControl = checkGroupInjectionConstraints(group, phase, deferred_logger);
if (newControl != Group::InjectionCMode::NONE)
{
return true;
}
}
} else if (group.isProductionGroup())
{
Group::ProductionCMode newControl = checkGroupProductionConstraints(group, deferred_logger);
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
const auto controls = group.productionControls(summaryState);
if (newControl != Group::ProductionCMode::NONE)
{
return true;
}
} else {
//neither production or injecting group FIELD?
} }
// call recursively down the group hiearchy
bool violated = false;
for (const std::string& groupName : group.groups()) {
violated = violated || checkGroupConstraints( schedule().getGroup(groupName, reportStepIdx), deferred_logger);
}
return violated;
}
template<typename TypeTag>
Group::ProductionCMode
BlackoilWellModel<TypeTag>::
checkGroupProductionConstraints(const Group& group, Opm::DeferredLogger& deferred_logger) const {
const int reportStepIdx = ebosSimulator_.episodeIndex();
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
const auto& comm = ebosSimulator_.vanguard().grid().comm();
const auto& well_state = well_state_;
const auto controls = group.productionControls(summaryState);
const Group::ProductionCMode& currentControl = well_state.currentProductionGroupControl(group.name());
if (group.has_control(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);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.oil_target < current_rate ) {
return Group::ProductionCMode::ORAT;
}
}
}
if (group.has_control(Group::ProductionCMode::WRAT))
{
if (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);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.water_target < current_rate ) {
return Group::ProductionCMode::WRAT;
}
}
}
if (group.has_control(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);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.gas_target < current_rate ) {
return Group::ProductionCMode::GRAT;
}
}
}
if (group.has_control(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);
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);
if (controls.liquid_target < current_rate ) {
return Group::ProductionCMode::LRAT;
}
}
}
if (group.has_control(Group::ProductionCMode::CRAT))
{
OPM_DEFLOG_THROW(std::runtime_error, "Group " + group.name() + "CRAT control for production groups not implemented" , deferred_logger);
}
if (group.has_control(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);
current_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Liquid], true);
current_rate += wellGroupHelpers::sumWellResRates(group, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Vapour], true);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.resv_target < current_rate ) {
return Group::ProductionCMode::RESV;
}
}
}
if (group.has_control(Group::ProductionCMode::PRBL))
{
OPM_DEFLOG_THROW(std::runtime_error, "Group " + group.name() + "PRBL control for production groups not implemented", deferred_logger);
}
return Group::ProductionCMode::NONE;
}
template<typename TypeTag>
Group::InjectionCMode
BlackoilWellModel<TypeTag>::
checkGroupInjectionConstraints(const Group& group, const Phase& phase, Opm::DeferredLogger& deferred_logger) const {
const int reportStepIdx = ebosSimulator_.episodeIndex();
const auto& summaryState = ebosSimulator_.vanguard().summaryState();
const auto& comm = ebosSimulator_.vanguard().grid().comm();
const auto& well_state = well_state_;
int phasePos;
if (phase == Phase::GAS && phase_usage_.phase_used[BlackoilPhases::Vapour] )
phasePos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
else if (phase == Phase::OIL && phase_usage_.phase_used[BlackoilPhases::Liquid])
phasePos = phase_usage_.phase_pos[BlackoilPhases::Liquid];
else if (phase == Phase::WATER && phase_usage_.phase_used[BlackoilPhases::Aqua] )
phasePos = phase_usage_.phase_pos[BlackoilPhases::Aqua];
else
OPM_THROW(std::runtime_error, "Unknown phase" );
const auto& controls = group.injectionControls(phase, summaryState);
const Group::InjectionCMode& currentControl = well_state.currentInjectionGroupControl(phase, group.name());
if (controls.has_control(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);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.surface_max_rate < current_rate) {
return Group::InjectionCMode::RATE;
}
}
}
if (controls.has_control(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);
// sum over all nodes
current_rate = comm.sum(current_rate);
if (controls.resv_max_rate < current_rate) {
return Group::InjectionCMode::RESV;
}
}
}
if (controls.has_control(Group::InjectionCMode::REIN))
{
if (currentControl != Group::InjectionCMode::REIN)
{
double production_Rate = 0.0;
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);
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);
if (controls.target_reinj_fraction*production_Rate < current_rate) {
return Group::InjectionCMode::REIN;
}
}
}
if (controls.has_control(Group::InjectionCMode::VREP))
{
if (currentControl != Group::InjectionCMode::VREP)
{
double voidage_rate = 0.0;
const Group& groupVoidage = schedule().getGroup(controls.voidage_group, reportStepIdx);
voidage_rate += wellGroupHelpers::sumWellResRates(groupVoidage, schedule(), well_state, reportStepIdx, phase_usage_.phase_pos[BlackoilPhases::Aqua], false);
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);
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);
if (controls.target_void_fraction*voidage_rate < total_rate) {
return Group::InjectionCMode::VREP;
}
}
}
// 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);
// sum over all nodes
sales_rate = comm.sum(sales_rate);
// 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" );
}
}
return Group::InjectionCMode::NONE;
} }
template<typename TypeTag> template<typename TypeTag>
@ -2137,7 +2201,7 @@ namespace Opm {
const Group::InjectionCMode& currentControl = well_state_.currentInjectionGroupControl(phase, group.name()); const Group::InjectionCMode& currentControl = well_state_.currentInjectionGroupControl(phase, group.name());
if (currentControl != Group::InjectionCMode::FLD) { if (currentControl != Group::InjectionCMode::FLD) {
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx); const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
const bool changed = wellGroupHelpers::checkGroupConstraintsInj( const std::pair<bool, double> changed = wellGroupHelpers::checkGroupConstraintsInj(
group.name(), group.name(),
group.parent(), group.parent(),
parentGroup, parentGroup,
@ -2153,7 +2217,7 @@ namespace Opm {
*rateConverter_, *rateConverter_,
pvtreg, pvtreg,
deferred_logger); deferred_logger);
if (changed) { if (changed.first) {
switched_groups.insert(group.name()); switched_groups.insert(group.name());
actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, reportStepIdx, deferred_logger); actionOnBrokenConstraints(group, Group::InjectionCMode::FLD, phase, reportStepIdx, deferred_logger);
} }
@ -2173,7 +2237,7 @@ namespace Opm {
const Group::ProductionCMode& currentControl = well_state_.currentProductionGroupControl(group.name()); const Group::ProductionCMode& currentControl = well_state_.currentProductionGroupControl(group.name());
if (currentControl != Group::ProductionCMode::FLD) { if (currentControl != Group::ProductionCMode::FLD) {
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx); const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
const bool changed = wellGroupHelpers::checkGroupConstraintsProd( const std::pair<bool, double> changed = wellGroupHelpers::checkGroupConstraintsProd(
group.name(), group.name(),
group.parent(), group.parent(),
parentGroup, parentGroup,
@ -2188,7 +2252,7 @@ namespace Opm {
*rateConverter_, *rateConverter_,
pvtreg, pvtreg,
deferred_logger); deferred_logger);
if (changed) { if (changed.first) {
switched_groups.insert(group.name()); switched_groups.insert(group.name());
const auto exceed_action = group.productionControls(summaryState).exceed_action; const auto exceed_action = group.productionControls(summaryState).exceed_action;
actionOnBrokenConstraints(group, exceed_action, Group::ProductionCMode::FLD, reportStepIdx, deferred_logger); actionOnBrokenConstraints(group, exceed_action, Group::ProductionCMode::FLD, reportStepIdx, deferred_logger);

View File

@ -675,7 +675,7 @@ namespace Opm
} }
// If the well is pressure controlled the potential equals the rate. // If the well is pressure controlled the potential equals the rate.
{ /* {
bool pressure_controlled_well = false; bool pressure_controlled_well = false;
if (this->isInjector()) { if (this->isInjector()) {
const Opm::Well::InjectorCMode& current = well_state.currentInjectionControls()[index_of_well_]; const Opm::Well::InjectorCMode& current = well_state.currentInjectionControls()[index_of_well_];
@ -695,7 +695,7 @@ namespace Opm
} }
return; return;
} }
} } */
// creating a copy of the well itself, to avoid messing up the explicit informations // creating a copy of the well itself, to avoid messing up the explicit informations
// during this copy, the only information not copied properly is the well controls // during this copy, the only information not copied properly is the well controls

View File

@ -395,6 +395,39 @@ namespace Opm {
} }
wellState.setCurrentInjectionGroupReservoirRates(group.name(), resv); wellState.setCurrentInjectionGroupReservoirRates(group.name(), resv);
} }
inline void updateWellRates(const Group& group, const Schedule& schedule, const int reportStepIdx, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState) {
for (const std::string& groupName : group.groups()) {
const Group& groupTmp = schedule.getGroup(groupName, reportStepIdx);
updateWellRates(groupTmp, schedule, reportStepIdx, wellStateNupcol, wellState);
}
const int np = wellState.numPhases();
const auto& end = wellState.wellMap().end();
for (const std::string& wellName : group.wells()) {
std::vector<double> rates(np, 0.0);
const auto& it = wellState.wellMap().find(wellName);
if (it != end) { // the well is found on this node
int well_index = it->second[0];
for (int phase = 0; phase < np; ++phase) {
rates[phase] = wellStateNupcol.wellRates()[well_index*np + phase];
}
}
wellState.setCurrentWellRates(wellName, rates);
}
}
inline void updateGroupProductionRates(const Group& group, const Schedule& schedule, const int reportStepIdx, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState) {
for (const std::string& groupName : group.groups()) {
const Group& groupTmp = schedule.getGroup(groupName, reportStepIdx);
updateGroupProductionRates(groupTmp, schedule, reportStepIdx, wellStateNupcol, wellState);
}
const int np = wellState.numPhases();
std::vector<double> rates(np, 0.0);
for (int phase = 0; phase < np; ++phase) {
rates[phase] = sumWellPhaseRates(wellStateNupcol.wellRates(), group, schedule, wellState, reportStepIdx, phase, /*isInjector*/ false);
}
wellState.setCurrentProductionGroupRates(group.name(), rates);
}
inline void updateREINForGroups(const Group& group, const Schedule& schedule, const int reportStepIdx, const PhaseUsage& pu, const SummaryState& st, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState) { inline void updateREINForGroups(const Group& group, const Schedule& schedule, const int reportStepIdx, const PhaseUsage& pu, const SummaryState& st, const WellStateFullyImplicitBlackoil& wellStateNupcol, WellStateFullyImplicitBlackoil& wellState) {
const int np = wellState.numPhases(); const int np = wellState.numPhases();
@ -420,29 +453,22 @@ namespace Opm {
wellState.setCurrentInjectionREINRates(group.name(), rein); wellState.setCurrentInjectionREINRates(group.name(), rein);
} }
inline GuideRate::RateVector getRateVector(const WellState& well_state, const PhaseUsage& pu, const std::string& name) { inline GuideRate::RateVector getRateVector(const WellStateFullyImplicitBlackoil& well_state, const PhaseUsage& pu, const std::string& name) {
const std::vector<double>& rates = well_state.currentWellRates(name);
const auto& end = well_state.wellMap().end(); double oilRate = 0.0;
const auto& it = well_state.wellMap().find( name); if (pu.phase_used[BlackoilPhases::Liquid])
if (it == end) // the well is not found oilRate = rates[pu.phase_pos[BlackoilPhases::Liquid]];
assert(false);
int well_index = it->second[0];
int np = well_state.numPhases();
double oilRate = 0.0;
if (pu.phase_used[BlackoilPhases::Liquid])
oilRate = well_state.wellRates()[ well_index*np + pu.phase_pos[BlackoilPhases::Liquid]];
double gasRate = 0.0; double gasRate = 0.0;
if (pu.phase_used[BlackoilPhases::Vapour]) if (pu.phase_used[BlackoilPhases::Vapour])
gasRate = well_state.wellRates()[ well_index*np + pu.phase_pos[BlackoilPhases::Vapour]]; gasRate = rates[pu.phase_pos[BlackoilPhases::Vapour]];
double waterRate = 0.0; double waterRate = 0.0;
if (pu.phase_used[BlackoilPhases::Aqua]) if (pu.phase_used[BlackoilPhases::Aqua])
waterRate = well_state.wellRates()[well_index*np + pu.phase_pos[BlackoilPhases::Aqua]]; waterRate = rates[pu.phase_pos[BlackoilPhases::Aqua]];
return GuideRate::RateVector{oilRate, gasRate, waterRate}; return GuideRate::RateVector{oilRate, gasRate, waterRate};
} }
inline double getGuideRate(const std::string& name, inline double getGuideRate(const std::string& name,
@ -451,7 +477,7 @@ namespace Opm {
const int reportStepIdx, const int reportStepIdx,
const GuideRate* guideRate, const GuideRate* guideRate,
const GuideRateModel::Target target, const GuideRateModel::Target target,
const PhaseUsage& pu) const PhaseUsage& pu)
{ {
if (schedule.hasWell(name, reportStepIdx) || guideRate->has(name)) { if (schedule.hasWell(name, reportStepIdx) || guideRate->has(name)) {
return guideRate->get(name, target, getRateVector(wellState, pu, name)); return guideRate->get(name, target, getRateVector(wellState, pu, name));
@ -675,24 +701,23 @@ namespace Opm {
return ::Opm::wellGroupHelpers::groupControlledWells(schedule_, well_state_, report_step_, group_name, always_included_child); return ::Opm::wellGroupHelpers::groupControlledWells(schedule_, well_state_, report_step_, group_name, always_included_child);
} }
inline GuideRate::RateVector getGroupRateVector(const std::string& group_name) { inline GuideRate::RateVector getGroupRateVector(const std::string& group_name) {
#warning Does not work in parallell std::vector<double> groupRates = well_state_.currentProductionGroupRates(group_name);
const Group& group = schedule_.getGroup(group_name, report_step_); double oilRate = 0.0;
double oilRate = 0.0; if (pu_.phase_used[BlackoilPhases::Liquid])
if (pu_.phase_used[BlackoilPhases::Liquid]) oilRate = groupRates[pu_.phase_pos[BlackoilPhases::Liquid]];
oilRate = sumWellPhaseRates(well_state_.wellRates(), group, schedule_, well_state_, report_step_, pu_.phase_pos[BlackoilPhases::Liquid], /*isInjector*/ false);
double gasRate = 0.0; double gasRate = 0.0;
if (pu_.phase_used[BlackoilPhases::Vapour]) if (pu_.phase_used[BlackoilPhases::Vapour])
gasRate = sumWellPhaseRates(well_state_.wellRates(), group, schedule_, well_state_, report_step_, pu_.phase_pos[BlackoilPhases::Vapour], /*isInjector*/ false); gasRate = groupRates[pu_.phase_pos[BlackoilPhases::Vapour]];
double waterRate = 0.0; double waterRate = 0.0;
if (pu_.phase_used[BlackoilPhases::Aqua]) if (pu_.phase_used[BlackoilPhases::Aqua])
waterRate = sumWellPhaseRates(well_state_.wellRates(), group, schedule_, well_state_, report_step_, pu_.phase_pos[BlackoilPhases::Aqua], /*isInjector*/ false); waterRate = groupRates[pu_.phase_pos[BlackoilPhases::Aqua]];
return GuideRate::RateVector{oilRate, gasRate, waterRate}; return GuideRate::RateVector{oilRate, gasRate, waterRate};
} }
const Schedule& schedule_; const Schedule& schedule_;
@ -711,7 +736,7 @@ namespace Opm {
const int reportStepIdx, const int reportStepIdx,
const GuideRate* guideRate, const GuideRate* guideRate,
const GuideRateModel::Target target, const GuideRateModel::Target target,
const PhaseUsage& pu, const PhaseUsage& pu,
const bool alwaysIncludeThis = false) const bool alwaysIncludeThis = false)
{ {
FractionCalculator calc(schedule, wellState, reportStepIdx, guideRate, target, pu); FractionCalculator calc(schedule, wellState, reportStepIdx, guideRate, target, pu);
@ -743,7 +768,7 @@ namespace Opm {
template <class RateConverterType> template <class RateConverterType>
inline bool checkGroupConstraintsInj(const std::string& name, inline std::pair<bool, double> checkGroupConstraintsInj(const std::string& name,
const std::string& parent, const std::string& parent,
const Group& group, const Group& group,
const WellStateFullyImplicitBlackoil& wellState, const WellStateFullyImplicitBlackoil& wellState,
@ -769,7 +794,7 @@ namespace Opm {
currentGroupControl == Group::InjectionCMode::NONE) { currentGroupControl == Group::InjectionCMode::NONE) {
// Return if we are not available for parent group. // Return if we are not available for parent group.
if (!group.isAvailableForGroupControl()) { if (!group.isAvailableForGroupControl()) {
return false; return std::make_pair(false, 1.0);
} }
// Otherwise: check injection share of parent's control. // Otherwise: check injection share of parent's control.
const auto& parentGroup = schedule.getGroup(group.parent(), reportStepIdx); const auto& parentGroup = schedule.getGroup(group.parent(), reportStepIdx);
@ -796,7 +821,7 @@ namespace Opm {
// This can be false for FLD-controlled groups, we must therefore // This can be false for FLD-controlled groups, we must therefore
// check for FLD first (done above). // check for FLD first (done above).
if (!group.isInjectionGroup()) { if (!group.isInjectionGroup()) {
return false; return std::make_pair(false, 1.0);
} }
int phasePos; int phasePos;
@ -831,7 +856,7 @@ namespace Opm {
const std::vector<double>& groupInjectionReductions = wellState.currentInjectionGroupReductionRates(group.name()); const std::vector<double>& groupInjectionReductions = wellState.currentInjectionGroupReductionRates(group.name());
const double groupTargetReduction = groupInjectionReductions[phasePos]; const double groupTargetReduction = groupInjectionReductions[phasePos];
double fraction = wellGroupHelpers::fractionFromInjectionPotentials(name, group.name(), schedule, wellState, reportStepIdx, guideRate, target, pu, injectionPhase, true); double fraction = wellGroupHelpers::fractionFromInjectionPotentials(name, group.name(), schedule, wellState, reportStepIdx, guideRate, target, pu, injectionPhase, true);
double target_fraction = 1.0;
bool constraint_broken = false; bool constraint_broken = false;
switch(currentGroupControl) { switch(currentGroupControl) {
case Group::InjectionCMode::RATE: case Group::InjectionCMode::RATE:
@ -840,6 +865,7 @@ namespace Opm {
const double target_rate = fraction * std::max(0.0, (groupcontrols.surface_max_rate - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor; const double target_rate = fraction * std::max(0.0, (groupcontrols.surface_max_rate - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor;
if (current_rate > target_rate) { if (current_rate > target_rate) {
constraint_broken = true; constraint_broken = true;
target_fraction = target_rate / current_rate;
} }
break; break;
} }
@ -852,6 +878,7 @@ namespace Opm {
const double target_rate = fraction * std::max(0.0, (groupcontrols.resv_max_rate/coeff - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor; const double target_rate = fraction * std::max(0.0, (groupcontrols.resv_max_rate/coeff - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor;
if (current_rate > target_rate) { if (current_rate > target_rate) {
constraint_broken = true; constraint_broken = true;
target_fraction = target_rate / current_rate;
} }
break; break;
} }
@ -862,6 +889,7 @@ namespace Opm {
const double target_rate = fraction * std::max(0.0, (groupcontrols.target_reinj_fraction*productionRate - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor; const double target_rate = fraction * std::max(0.0, (groupcontrols.target_reinj_fraction*productionRate - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor;
if (current_rate > target_rate) { if (current_rate > target_rate) {
constraint_broken = true; constraint_broken = true;
target_fraction = target_rate / current_rate;
} }
break; break;
} }
@ -885,6 +913,7 @@ namespace Opm {
const double target_rate = fraction * std::max(0.0, ( voidageRate/coeff - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor; const double target_rate = fraction * std::max(0.0, ( voidageRate/coeff - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor;
if (current_rate > target_rate) { if (current_rate > target_rate) {
constraint_broken = true; constraint_broken = true;
target_fraction = target_rate / current_rate;
} }
break; break;
} }
@ -909,6 +938,7 @@ namespace Opm {
const double target_rate = fraction * std::max(0.0, (inj_rate - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor; const double target_rate = fraction * std::max(0.0, (inj_rate - groupTargetReduction + current_rate*efficiencyFactor)) / efficiencyFactor;
if (current_rate > target_rate) { if (current_rate > target_rate) {
constraint_broken = true; constraint_broken = true;
target_fraction = target_rate / current_rate;
} }
break; break;
} }
@ -925,7 +955,7 @@ namespace Opm {
} }
return constraint_broken; return std::make_pair(constraint_broken, target_fraction);
} }
template <class RateConverterType> template <class RateConverterType>
@ -1080,7 +1110,7 @@ namespace Opm {
template <class RateConverterType> template <class RateConverterType>
inline bool checkGroupConstraintsProd(const std::string& name, inline std::pair<bool, double> checkGroupConstraintsProd(const std::string& name,
const std::string& parent, const std::string& parent,
const Group& group, const Group& group,
const WellStateFullyImplicitBlackoil& wellState, const WellStateFullyImplicitBlackoil& wellState,
@ -1106,7 +1136,7 @@ namespace Opm {
currentGroupControl == Group::ProductionCMode::NONE) { currentGroupControl == Group::ProductionCMode::NONE) {
// Return if we are not available for parent group. // Return if we are not available for parent group.
if (!group.isAvailableForGroupControl()) { if (!group.isAvailableForGroupControl()) {
return false; return std::make_pair(false,1);
} }
// Otherwise: check production share of parent's control. // Otherwise: check production share of parent's control.
const auto& parentGroup = schedule.getGroup(group.parent(), reportStepIdx); const auto& parentGroup = schedule.getGroup(group.parent(), reportStepIdx);
@ -1129,7 +1159,7 @@ namespace Opm {
// This can be false for FLD-controlled groups, we must therefore // This can be false for FLD-controlled groups, we must therefore
// check for FLD first (done above). // check for FLD first (done above).
if (!group.isProductionGroup()) { if (!group.isProductionGroup()) {
return false; return std::make_pair(false,1.0);
} }
// If we are here, we are at the topmost group to be visited in the recursion. // If we are here, we are at the topmost group to be visited in the recursion.
@ -1174,8 +1204,8 @@ namespace Opm {
} }
target *= localFraction(chain[ii+1]); target *= localFraction(chain[ii+1]);
} }
const double target_rate = target / efficiencyFactor; const double target_rate = std::max(0.0, target / efficiencyFactor);
return current_rate > target_rate; return std::make_pair(current_rate > target_rate, target_rate / current_rate);
} }

View File

@ -495,14 +495,14 @@ namespace Opm
const SummaryState& summaryState, const SummaryState& summaryState,
DeferredLogger& deferred_logger) const; DeferredLogger& deferred_logger) const;
bool checkGroupConstraintsProd(const Group& group, std::pair<bool, double> checkGroupConstraintsProd(const Group& group,
const WellState& well_state, const WellState& well_state,
const double efficiencyFactor, const double efficiencyFactor,
const Schedule& schedule, const Schedule& schedule,
const SummaryState& summaryState, const SummaryState& summaryState,
DeferredLogger& deferred_logger) const; DeferredLogger& deferred_logger) const;
bool checkGroupConstraintsInj(const Group& group, std::pair<bool, double> checkGroupConstraintsInj(const Group& group,
const WellState& well_state, const WellState& well_state,
const double efficiencyFactor, const double efficiencyFactor,
const Schedule& schedule, const Schedule& schedule,

View File

@ -1682,7 +1682,7 @@ namespace Opm
const auto controls = well.injectionControls(summaryState); const auto controls = well.injectionControls(summaryState);
Opm::Well::InjectorCMode& currentControl = well_state.currentInjectionControls()[well_index]; Opm::Well::InjectorCMode& currentControl = well_state.currentInjectionControls()[well_index];
if (currentControl != Well::InjectorCMode::GRUP) { if (currentControl != Well::InjectorCMode::GRUP) {
// This checks only the first encountered group limit, // This checks only the first encountered group limit,
// in theory there could be several, and then we should // in theory there could be several, and then we should
// test all but the one currently applied. At that point, // test all but the one currently applied. At that point,
@ -1691,22 +1691,26 @@ namespace Opm
// control is the active one for the well (if any). // control is the active one for the well (if any).
const auto& group = schedule.getGroup( well.groupName(), current_step_ ); const auto& group = schedule.getGroup( well.groupName(), current_step_ );
const double efficiencyFactor = well.getEfficiencyFactor(); const double efficiencyFactor = well.getEfficiencyFactor();
const bool group_constraint_broken = checkGroupConstraintsInj( const std::pair<bool, double> group_constraint = checkGroupConstraintsInj(
group, well_state, efficiencyFactor, schedule, summaryState, deferred_logger); group, well_state, efficiencyFactor, schedule, summaryState, deferred_logger);
// If a group constraint was broken, we set the current well control to // If a group constraint was broken, we set the current well control to
// be GRUP. // be GRUP.
if (group_constraint_broken) { if (group_constraint.first) {
well_state.currentInjectionControls()[index_of_well_] = Well::InjectorCMode::GRUP; well_state.currentInjectionControls()[index_of_well_] = Well::InjectorCMode::GRUP;
const int np = well_state.numPhases();
for (int p = 0; p<np; ++p) {
well_state.wellRates()[index_of_well_*np + p] *= group_constraint.second;
}
} }
return group_constraint_broken; return group_constraint.first;
} }
} }
if (well.isProducer( )) { if (well.isProducer( )) {
const auto controls = well.productionControls(summaryState); const auto controls = well.productionControls(summaryState);
Well::ProducerCMode& currentControl = well_state.currentProductionControls()[well_index]; Well::ProducerCMode& currentControl = well_state.currentProductionControls()[well_index];
if (currentControl != Well::ProducerCMode::GRUP) { if (currentControl != Well::ProducerCMode::GRUP) {
// This checks only the first encountered group limit, // This checks only the first encountered group limit,
// in theory there could be several, and then we should // in theory there could be several, and then we should
// test all but the one currently applied. At that point, // test all but the one currently applied. At that point,
@ -1715,15 +1719,19 @@ namespace Opm
// control is the active one for the well (if any). // control is the active one for the well (if any).
const auto& group = schedule.getGroup( well.groupName(), current_step_ ); const auto& group = schedule.getGroup( well.groupName(), current_step_ );
const double efficiencyFactor = well.getEfficiencyFactor(); const double efficiencyFactor = well.getEfficiencyFactor();
const bool group_constraint_broken = checkGroupConstraintsProd( const std::pair<bool, double> group_constraint = checkGroupConstraintsProd(
group, well_state, efficiencyFactor, schedule, summaryState, deferred_logger); group, well_state, efficiencyFactor, schedule, summaryState, deferred_logger);
// If a group constraint was broken, we set the current well control to // If a group constraint was broken, we set the current well control to
// be GRUP. // be GRUP.
if (group_constraint_broken) { if (group_constraint.first) {
well_state.currentProductionControls()[index_of_well_] = Well::ProducerCMode::GRUP; well_state.currentProductionControls()[index_of_well_] = Well::ProducerCMode::GRUP;
const int np = well_state.numPhases();
for (int p = 0; p<np; ++p) {
well_state.wellRates()[index_of_well_*np + p] *= group_constraint.second;
}
} }
return group_constraint_broken; return group_constraint.first;
} }
} }
return false; return false;
@ -1734,7 +1742,7 @@ namespace Opm
template <typename TypeTag> template <typename TypeTag>
bool std::pair<bool, double>
WellInterface<TypeTag>::checkGroupConstraintsInj(const Group& group, WellInterface<TypeTag>::checkGroupConstraintsInj(const Group& group,
const WellState& well_state, const WellState& well_state,
const double efficiencyFactor, const double efficiencyFactor,
@ -1788,7 +1796,7 @@ namespace Opm
template <typename TypeTag> template <typename TypeTag>
bool std::pair<bool, double>
WellInterface<TypeTag>::checkGroupConstraintsProd(const Group& group, WellInterface<TypeTag>::checkGroupConstraintsProd(const Group& group,
const WellState& well_state, const WellState& well_state,
const double efficiencyFactor, const double efficiencyFactor,

View File

@ -350,8 +350,33 @@ namespace Opm
return it->second; return it->second;
} }
void setCurrentWellRates(const std::string& wellName, const std::vector<double>& rates ) {
well_rates[wellName] = rates;
}
const std::vector<double>& currentWellRates(const std::string& wellName) const {
auto it = well_rates.find(wellName);
if (it == well_rates.end())
OPM_THROW(std::logic_error, "Could not find any rates for well " << wellName);
return it->second;
}
void setCurrentProductionGroupRates(const std::string& groupName, const std::vector<double>& rates ) {
production_group_rates[groupName] = rates;
}
const std::vector<double>& currentProductionGroupRates(const std::string& groupName) const {
auto it = production_group_rates.find(groupName);
if (it == production_group_rates.end())
OPM_THROW(std::logic_error, "Could not find any rates for productino group " << groupName);
return it->second;
}
void setCurrentProductionGroupReductionRates(const std::string& groupName, const std::vector<double>& target ) { void setCurrentProductionGroupReductionRates(const std::string& groupName, const std::vector<double>& target ) {
production_group_reduction_rates[groupName] = target; production_group_reduction_rates[groupName] = target;
} }
@ -880,6 +905,12 @@ namespace Opm
for (auto& x : injection_group_reservoir_rates) { for (auto& x : injection_group_reservoir_rates) {
comm.sum(x.second.data(), x.second.size()); comm.sum(x.second.data(), x.second.size());
} }
for (auto& x : production_group_rates) {
comm.sum(x.second.data(), x.second.size());
}
for (auto& x : well_rates) {
comm.sum(x.second.data(), x.second.size());
}
} }
template<class Comm> template<class Comm>
@ -952,6 +983,8 @@ namespace Opm
std::map<std::string, Group::ProductionCMode> current_production_group_controls_; std::map<std::string, Group::ProductionCMode> current_production_group_controls_;
std::map<std::pair<Opm::Phase, 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>> well_rates;
std::map<std::string, std::vector<double>> production_group_rates;
std::map<std::string, std::vector<double>> production_group_reduction_rates; std::map<std::string, std::vector<double>> production_group_reduction_rates;
std::map<std::string, std::vector<double>> injection_group_reduction_rates; std::map<std::string, std::vector<double>> injection_group_reduction_rates;
std::map<std::string, std::vector<double>> injection_group_reservoir_rates; std::map<std::string, std::vector<double>> injection_group_reservoir_rates;