Use SingleWellState for production and injection control

This commit is contained in:
Joakim Hove 2021-08-04 12:03:36 +02:00
parent c381459804
commit 581f571c9d
14 changed files with 69 additions and 75 deletions

View File

@ -178,10 +178,10 @@ loadRestartData(const data::Wells& rst_wells,
ws.temperature = rst_well.temperature;
if (rst_well.current_control.isProducer) {
well_state.currentProductionControl(well_index, rst_well.current_control.prod);
ws.production_cmode = rst_well.current_control.prod;
}
else {
well_state.currentInjectionControl(well_index, rst_well.current_control.inj);
ws.injection_cmode = rst_well.current_control.inj;
}
for( size_t i = 0; i < phs.size(); ++i ) {

View File

@ -202,9 +202,9 @@ checkDoGasLiftOptimization_(const std::string &well_name)
if (itr != this->ecl_wells_.end()) {
//const Well *well = (itr->second).first;
//assert(well); // Should never be nullptr
const int index = (itr->second).second;
const Well::ProducerCMode& control_mode
= this->well_state_.currentProductionControl(index);
const int well_index = (itr->second).second;
const auto& ws = this->well_state_.well(well_index);
const Well::ProducerCMode& control_mode = ws.production_cmode;
if (control_mode != Well::ProducerCMode::THP ) {
displayDebugMessage_("Not THP control. Skipping.", well_name);
return false;

View File

@ -1235,9 +1235,8 @@ bool
GasLiftSingleWellGeneric::OptimizeState::
checkThpControl()
{
const int index = this->parent.well_state_.wellIndex(this->parent.well_name_);
const Well::ProducerCMode& control_mode
= this->parent.well_state_.currentProductionControl(index);
const int well_index = this->parent.well_state_.wellIndex(this->parent.well_name_);
const Well::ProducerCMode& control_mode = this->parent.well_state_.well(well_index).production_cmode;
return control_mode == Well::ProducerCMode::THP;
}

View File

@ -155,9 +155,10 @@ checkConvergenceControlEq(const WellState& well_state,
CR::WellFailure::Type ctrltype = CR::WellFailure::Type::Invalid;
const int well_index = baseif_.indexOfWell();
const auto& ws = well_state.well(well_index);
if (baseif_.isInjector() )
{
auto current = well_state.currentInjectionControl(well_index);
auto current = ws.injection_cmode;
switch(current) {
case Well::InjectorCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;
@ -183,7 +184,7 @@ checkConvergenceControlEq(const WellState& well_state,
if (baseif_.isProducer() )
{
auto current = well_state.currentProductionControl(well_index);
auto current = ws.production_cmode;
switch(current) {
case Well::ProducerCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;
@ -1797,9 +1798,10 @@ getControlTolerance(const WellState& well_state,
double control_tolerance = 0.;
const int well_index = baseif_.indexOfWell();
const auto& ws = well_state.well(well_index);
if (baseif_.isInjector() )
{
auto current = well_state.currentInjectionControl(well_index);
auto current = ws.injection_cmode;
switch(current) {
case Well::InjectorCMode::THP:
control_tolerance = tolerance_pressure_ms_wells;
@ -1821,7 +1823,7 @@ getControlTolerance(const WellState& well_state,
if (baseif_.isProducer() )
{
auto current = well_state.currentProductionControl(well_index);
auto current = ws.production_cmode;
switch(current) {
case Well::ProducerCMode::THP:
control_tolerance = tolerance_pressure_ms_wells; // 0.1 bar

View File

@ -257,8 +257,9 @@ namespace Opm
// If the well is pressure controlled the potential equals the rate.
bool thp_controlled_well = false;
bool bhp_controlled_well = false;
const auto& ws = well_state.well(this->index_of_well_);
if (this->isInjector()) {
const Well::InjectorCMode& current = well_state.currentInjectionControl(index_of_well_);
const Well::InjectorCMode& current = ws.injection_cmode;
if (current == Well::InjectorCMode::THP) {
thp_controlled_well = true;
}
@ -266,7 +267,7 @@ namespace Opm
bhp_controlled_well = true;
}
} else {
const Well::ProducerCMode& current = well_state.currentProductionControl(index_of_well_);
const Well::ProducerCMode& current = ws.production_cmode;
if (current == Well::ProducerCMode::THP) {
thp_controlled_well = true;
}
@ -354,10 +355,10 @@ namespace Opm
// Set current control to bhp, and bhp value in state, modify bhp limit in control object.
if (well_copy.well_ecl_.isInjector()) {
inj_controls.bhp_limit = bhp;
well_state_copy.currentInjectionControl(index_of_well_, Well::InjectorCMode::BHP);
ws.injection_cmode = Well::InjectorCMode::BHP;
} else {
prod_controls.bhp_limit = bhp;
well_state_copy.currentProductionControl(index_of_well_, Well::ProducerCMode::BHP);
ws.production_cmode = Well::ProducerCMode::BHP;
}
ws.bhp = bhp;
well_copy.scaleSegmentPressuresWithBhp(well_state_copy);

View File

@ -35,6 +35,9 @@ public:
double thp{0};
double temperature{};
Events events;
Well::InjectorCMode injection_cmode{Well::InjectorCMode::CMODE_UNDEFINED};
Well::ProducerCMode production_cmode{Well::ProducerCMode::CMODE_UNDEFINED};
void init_timestep(const SingleWellState& other);
void shut();

View File

@ -265,7 +265,7 @@ doGasLiftOptimize(const WellState &well_state,
}
if (glift_optimize_only_thp_wells) {
const int well_index = baseif_.indexOfWell();
auto control_mode = well_state.currentProductionControl(well_index);
auto control_mode = well_state.well(well_index).production_cmode;
if (control_mode != Well::ProducerCMode::THP ) {
gliftDebug("Not THP control", deferred_logger);
return false;
@ -698,13 +698,14 @@ checkConvergenceControlEq(const WellState& well_state,
CR::WellFailure::Type ctrltype = CR::WellFailure::Type::Invalid;
const int well_index = baseif_.indexOfWell();
const auto& ws = well_state.well(well_index);
if (baseif_.wellIsStopped()) {
ctrltype = CR::WellFailure::Type::ControlRate;
control_tolerance = 1.e-6; // use smaller tolerance for zero control?
}
else if (baseif_.isInjector() )
{
auto current = well_state.currentInjectionControl(well_index);
auto current = ws.injection_cmode;
switch(current) {
case Well::InjectorCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;
@ -729,7 +730,7 @@ checkConvergenceControlEq(const WellState& well_state,
}
else if (baseif_.isProducer() )
{
auto current = well_state.currentProductionControl(well_index);
auto current = ws.production_cmode;
switch(current) {
case Well::ProducerCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;

View File

@ -1687,9 +1687,9 @@ namespace Opm
// Set current control to bhp, and bhp value in state, modify bhp limit in control object.
if (well_ecl_.isInjector()) {
well_state_copy.currentInjectionControl(index_of_well_, Well::InjectorCMode::BHP);
ws.injection_cmode = Well::InjectorCMode::BHP;
} else {
well_state_copy.currentProductionControl(index_of_well_, Well::ProducerCMode::BHP);
ws.production_cmode = Well::ProducerCMode::BHP;
}
ws.bhp = bhp;
@ -1839,8 +1839,9 @@ namespace Opm
// If the well is pressure controlled the potential equals the rate.
bool thp_controlled_well = false;
bool bhp_controlled_well = false;
const auto& ws = well_state.well(this->index_of_well_);
if (this->isInjector()) {
const Well::InjectorCMode& current = well_state.currentInjectionControl(index_of_well_);
const Well::InjectorCMode& current = ws.injection_cmode;
if (current == Well::InjectorCMode::THP) {
thp_controlled_well = true;
}
@ -1848,7 +1849,7 @@ namespace Opm
bhp_controlled_well = true;
}
} else {
const Well::ProducerCMode& current = well_state.currentProductionControl(index_of_well_);
const Well::ProducerCMode& current = ws.production_cmode;
if (current == Well::ProducerCMode::THP) {
thp_controlled_well = true;
}

View File

@ -404,13 +404,14 @@ namespace WellGroupHelpers
const double efficiency = wellTmp.getEfficiencyFactor();
// add contributino from wells not under group control
const auto& ws = wellState.well(well_index);
if (isInjector) {
if (wellState.currentInjectionControl(well_index) != Well::InjectorCMode::GRUP)
if (ws.injection_cmode != Well::InjectorCMode::GRUP)
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] += wellStateNupcol.wellRates(well_index)[phase] * efficiency;
}
} else {
if (wellState.currentProductionControl(well_index) != Well::ProducerCMode::GRUP)
if (ws.production_cmode != Well::ProducerCMode::GRUP)
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] -= wellStateNupcol.wellRates(well_index)[phase] * efficiency;
}
@ -480,13 +481,14 @@ namespace WellGroupHelpers
}
// scale rates
const auto& ws = wellState.well(well_index);
if (isInjector) {
if (wellState.currentInjectionControl(well_index) == Well::InjectorCMode::GRUP)
if (ws.injection_cmode == Well::InjectorCMode::GRUP)
for (int phase = 0; phase < np; phase++) {
wellState.wellRates(well_index)[phase] *= scale;
}
} else {
if (wellState.currentProductionControl(well_index) == Well::ProducerCMode::GRUP)
if (ws.production_cmode == Well::ProducerCMode::GRUP)
for (int phase = 0; phase < np; phase++) {
wellState.wellRates(well_index)[phase] *= scale;
}

View File

@ -278,7 +278,7 @@ assembleControlEqProd_(const WellState& well_state,
EvalWell& control_eq,
DeferredLogger& deferred_logger) const
{
auto current = well_state.currentProductionControl(baseif_.indexOfWell());
const auto current = well_state.well(baseif_.indexOfWell()).production_cmode;
const auto& pu = baseif_.phaseUsage();
const double efficiencyFactor = baseif_.wellEcl().getEfficiencyFactor();
@ -392,7 +392,7 @@ assembleControlEqInj_(const WellState& well_state,
EvalWell& control_eq,
DeferredLogger& deferred_logger) const
{
auto current = well_state.currentInjectionControl(baseif_.indexOfWell());
auto current = well_state.well(baseif_.indexOfWell()).injection_cmode;
const InjectorType injectorType = controls.injector_type;
const auto& pu = baseif_.phaseUsage();
const double efficiencyFactor = baseif_.wellEcl().getEfficiencyFactor();

View File

@ -90,8 +90,8 @@ activeProductionConstraint(const WellState& well_state,
const PhaseUsage& pu = this->phaseUsage();
const int well_index = this->index_of_well_;
const auto controls = this->well_ecl_.productionControls(summaryState);
auto currentControl = well_state.currentProductionControl(well_index);
auto& ws = well_state.well(well_index);
const auto currentControl = ws.production_cmode;
if (controls.hasControl(Well::ProducerCMode::BHP) && currentControl != Well::ProducerCMode::BHP) {
const double bhp_limit = controls.bhp_limit;
@ -170,7 +170,7 @@ activeProductionConstraint(const WellState& well_state,
return Well::ProducerCMode::THP;
}
return well_state.currentProductionControl(well_index);
return currentControl;
}
@ -185,7 +185,7 @@ activeInjectionConstraint(const WellState& well_state,
const auto& ws = well_state.well(well_index);
const auto controls = this->well_ecl_.injectionControls(summaryState);
auto currentControl = well_state.currentInjectionControl(well_index);
const auto currentControl = ws.injection_cmode;
if (controls.hasControl(Well::InjectorCMode::BHP) && currentControl != Well::InjectorCMode::BHP)
{
@ -248,7 +248,7 @@ activeInjectionConstraint(const WellState& well_state,
return Well::InjectorCMode::THP;
}
return well_state.currentInjectionControl(well_index);
return currentControl;
}
template <typename FluidSystem>
@ -258,18 +258,19 @@ checkIndividualConstraints(WellState& well_state,
const SummaryState& summaryState) const
{
const int well_index = this->index_of_well_;
auto& ws = well_state.well(well_index);
if (this->well_ecl_.isProducer()) {
auto new_cmode = this->activeProductionConstraint(well_state, summaryState);
if (new_cmode != well_state.currentProductionControl(well_index)) {
well_state.currentProductionControl(well_index, new_cmode);
if (new_cmode != ws.production_cmode) {
ws.production_cmode = new_cmode;
return true;
}
}
if (this->well_ecl_.isInjector()) {
auto new_cmode = this->activeInjectionConstraint(well_state, summaryState);
if (new_cmode != well_state.currentInjectionControl(well_index)) {
well_state.currentInjectionControl(well_index, new_cmode);
if (new_cmode != ws.injection_cmode) {
ws.injection_cmode = new_cmode;
return true;
}
}
@ -376,9 +377,10 @@ checkGroupConstraints(WellState& well_state,
{
const auto& well = well_ecl_;
const int well_index = index_of_well_;
auto& ws = well_state.well(well_index);
if (well.isInjector()) {
auto currentControl = well_state.currentInjectionControl(well_index);
const auto currentControl = ws.injection_cmode;
if (currentControl != Well::InjectorCMode::GRUP) {
// This checks only the first encountered group limit,
@ -395,7 +397,7 @@ checkGroupConstraints(WellState& well_state,
// If a group constraint was broken, we set the current well control to
// be GRUP.
if (group_constraint.first) {
well_state.currentInjectionControl(index_of_well_, Well::InjectorCMode::GRUP);
ws.injection_cmode = Well::InjectorCMode::GRUP;
const int np = well_state.numPhases();
for (int p = 0; p<np; ++p) {
well_state.wellRates(index_of_well_)[p] *= group_constraint.second;
@ -406,7 +408,7 @@ checkGroupConstraints(WellState& well_state,
}
if (well.isProducer( )) {
auto currentControl = well_state.currentProductionControl(well_index);
const auto currentControl = ws.production_cmode;
if (currentControl != Well::ProducerCMode::GRUP) {
// This checks only the first encountered group limit,
@ -423,7 +425,7 @@ checkGroupConstraints(WellState& well_state,
// If a group constraint was broken, we set the current well control to
// be GRUP.
if (group_constraint.first) {
well_state.currentProductionControl(index_of_well_, Well::ProducerCMode::GRUP);
ws.production_cmode = Well::ProducerCMode::GRUP;
const int np = well_state.numPhases();
for (int p = 0; p<np; ++p) {
well_state.wellRates(index_of_well_)[p] *= group_constraint.second;

View File

@ -165,11 +165,12 @@ namespace Opm
const auto& summaryState = ebos_simulator.vanguard().summaryState();
const auto& schedule = ebos_simulator.vanguard().schedule();
const auto& well = this->well_ecl_;
auto& ws = well_state.well(this->index_of_well_);
std::string from;
if (well.isInjector()) {
from = Well::InjectorCMode2String(well_state.currentInjectionControl(this->index_of_well_));
from = Well::InjectorCMode2String(ws.injection_cmode);
} else {
from = Well::ProducerCMode2String(well_state.currentProductionControl(this->index_of_well_));
from = Well::ProducerCMode2String(ws.production_cmode);
}
bool changed = false;
@ -188,9 +189,9 @@ namespace Opm
if (changed) {
std::string to;
if (well.isInjector()) {
to = Well::InjectorCMode2String(well_state.currentInjectionControl(this->index_of_well_));
to = Well::InjectorCMode2String(ws.injection_cmode);
} else {
to = Well::ProducerCMode2String(well_state.currentProductionControl(this->index_of_well_));
to = Well::ProducerCMode2String(ws.production_cmode);
}
std::ostringstream ss;
ss << " Switching control mode for well " << this->name()
@ -573,7 +574,7 @@ namespace Opm
{
this->operability_status_.reset();
auto current_control = well_state.currentProductionControl(this->index_of_well_);
auto current_control = well_state.well(this->index_of_well_).production_cmode;
// Operability checking is not free
// Only check wells under BHP and THP control
if(current_control == Well::ProducerCMode::BHP || current_control == Well::ProducerCMode::THP) {
@ -639,7 +640,7 @@ namespace Opm
OPM_DEFLOG_THROW(std::runtime_error, "Expected WATER, OIL or GAS as type for injectors " + this->name(), deferred_logger );
}
auto current = well_state.currentInjectionControl(well_index);
const auto current = ws.injection_cmode;
switch(current) {
case Well::InjectorCMode::RATE:
@ -722,7 +723,7 @@ namespace Opm
//Producer
else
{
auto current = well_state.currentProductionControl(well_index);
const auto current = ws.production_cmode;
const auto& controls = well.productionControls(summaryState);
switch (current) {
case Well::ProducerCMode::ORAT:

View File

@ -296,19 +296,15 @@ void WellState::init(const std::vector<double>& cellPressures,
this->well_vaporized_oil_rates_.add(wname, 0);
}
current_injection_controls_.clear();
current_production_controls_.clear();
for (int w = 0; w < nw; ++w) {
const auto& wname = wells_ecl[w].name();
current_production_controls_.add(wname, Well::ProducerCMode::CMODE_UNDEFINED);
current_injection_controls_.add(wname, Well::InjectorCMode::CMODE_UNDEFINED);
auto& ws = this->well(w);
if (wells_ecl[w].isProducer()) {
const auto controls = wells_ecl[w].productionControls(summary_state);
currentProductionControl(w, controls.cmode);
ws.production_cmode = controls.cmode;
}
else {
const auto controls = wells_ecl[w].injectionControls(summary_state);
currentInjectionControl(w, controls.cmode);
ws.injection_cmode = controls.cmode;
}
}
@ -361,8 +357,8 @@ void WellState::init(const std::vector<double>& cellPressures,
// If new target is set using WCONPROD, WCONINJE etc. we use the new control
if (!new_well.events.hasEvent(WellState::event_mask)) {
current_injection_controls_[ newIndex ] = prevState->currentInjectionControl(oldIndex);
current_production_controls_[ newIndex ] = prevState->currentProductionControl(oldIndex);
new_well.injection_cmode = prev_well.injection_cmode;
new_well.production_cmode = prev_well.production_cmode;
}
wellRates(w) = prevState->wellRates(oldIndex);
@ -552,8 +548,8 @@ WellState::report(const int* globalCellIdxMap,
auto& curr = well.current_control;
curr.isProducer = ws.producer;
curr.prod = this->currentProductionControl(well_index);
curr.inj = this->currentInjectionControl(well_index);
curr.prod = ws.production_cmode;
curr.inj = ws.injection_cmode;
}
const auto& pwinfo = *this->parallel_well_info_[well_index];
@ -922,9 +918,9 @@ void WellState::updateGlobalIsGrup(const Comm& comm)
for (std::size_t well_index = 0; well_index < this->size(); well_index++) {
const auto& ws = this->well(well_index);
if (ws.producer)
this->global_well_info.value().update_producer(well_index, ws.status, this->current_production_controls_[well_index]);
this->global_well_info.value().update_producer(well_index, ws.status, ws.production_cmode);
else
this->global_well_info.value().update_injector(well_index, ws.status, this->current_injection_controls_[well_index]);
this->global_well_info.value().update_injector(well_index, ws.status, ws.injection_cmode);
}
this->global_well_info.value().communicate(comm);
}

View File

@ -108,14 +108,6 @@ public:
const std::vector<std::vector<PerforationData>>& well_perf_data,
const SummaryState& summary_state);
/// One current control per injecting well.
Well::InjectorCMode currentInjectionControl(std::size_t well_index) const { return current_injection_controls_[well_index]; }
void currentInjectionControl(std::size_t well_index, Well::InjectorCMode cmode) { current_injection_controls_[well_index] = cmode; }
/// One current control per producing well.
Well::ProducerCMode currentProductionControl(std::size_t well_index) const { return current_production_controls_[well_index]; }
void currentProductionControl(std::size_t well_index, Well::ProducerCMode cmode) { current_production_controls_[well_index] = cmode; }
void setCurrentWellRates(const std::string& wellName, const std::vector<double>& new_rates ) {
auto& [owner, rates] = this->well_rates.at(wellName);
if (owner)
@ -366,12 +358,6 @@ private:
PhaseUsage phase_usage_;
WellContainer<PerfData> perfdata;
// vector with size number of wells +1.
// iterate over all perforations of a given well
// for (int perf = first_perf_index_[well_index]; perf < first_perf_index_[well_index] + num_perf_[well_index]; ++perf)
WellContainer<Opm::Well::InjectorCMode> current_injection_controls_;
WellContainer<Well::ProducerCMode> current_production_controls_;
// The well_rates variable is defined for all wells on all processors. The
// bool in the value pair is whether the current process owns the well or
// not.