Merge pull request #3458 from joakim-hove/single-well-state

Add SingleWellState
This commit is contained in:
Joakim Hove 2021-08-16 17:04:35 +02:00 committed by GitHub
commit b8567b708e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 330 additions and 215 deletions

View File

@ -70,6 +70,7 @@ list (APPEND MAIN_SOURCE_FILES
opm/simulators/wells/ParallelWellInfo.cpp
opm/simulators/wells/PerfData.cpp
opm/simulators/wells/SegmentState.cpp
opm/simulators/wells/SingleWellState.cpp
opm/simulators/wells/StandardWellEval.cpp
opm/simulators/wells/StandardWellGeneric.cpp
opm/simulators/wells/TargetCalculator.cpp
@ -307,6 +308,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/simulators/wells/PerforationData.hpp
opm/simulators/wells/RateConverter.hpp
opm/simulators/utils/readDeck.hpp
opm/simulators/wells/SingleWellState.hpp
opm/simulators/wells/TargetCalculator.hpp
opm/simulators/wells/WellConnectionAuxiliaryModule.hpp
opm/simulators/wells/WellState.hpp

View File

@ -172,15 +172,16 @@ loadRestartData(const data::Wells& rst_wells,
for( const auto& wm : well_state.wellMap() ) {
const auto well_index = wm.second[ 0 ];
const auto& rst_well = rst_wells.at( wm.first );
well_state.update_thp(well_index, rst_well.thp);
well_state.update_bhp(well_index, rst_well.bhp);
well_state.update_temperature(well_index, rst_well.temperature);
auto& ws = well_state.well(well_index);
ws.bhp = rst_well.bhp;
ws.thp = rst_well.thp;
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

@ -612,7 +612,7 @@ namespace Opm {
if (this->wellTestState_.hasWellClosed(well_name)) {
// TODO: more checking here, to make sure this standard more specific and complete
// maybe there is some WCON keywords will not open the well
auto& events = this->wellState().events(w);
auto& events = this->wellState().well(w).events;
if (events.hasEvent(WellState::event_mask)) {
if (wellTestState_.lastTestTime(well_name) == ebosSimulator_.time()) {
// The well was shut this timestep, we are most likely retrying
@ -1424,7 +1424,7 @@ namespace Opm {
if (!well->isOperable() ) continue;
auto& events = this->wellState().events(well->indexOfWell());
auto& events = this->wellState().well(well->indexOfWell()).events;
if (events.hasEvent(WellState::event_mask)) {
well->updateWellStateWithTarget(ebosSimulator_, this->groupState(), this->wellState(), deferred_logger);
// There is no new well control change input within a report step,
@ -1732,7 +1732,7 @@ namespace Opm {
}
weighted_temperature = well_info.communication().sum(weighted_temperature);
total_weight = well_info.communication().sum(total_weight);
this->wellState().update_temperature(wellID, weighted_temperature/total_weight);
this->wellState().well(wellID).temperature = weighted_temperature/total_weight;
}
}

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

@ -37,10 +37,8 @@ GlobalWellInfo::GlobalWellInfo(const Schedule& sched, std::size_t report_step, c
this->name_map.emplace( well.name(), global_well_index );
}
for (const auto& well : local_wells) {
for (const auto& well : local_wells)
this->local_map.push_back( well.seqIndex() );
this->is_injector.push_back( well.isInjector() );
}
}
@ -56,23 +54,19 @@ bool GlobalWellInfo::in_producing_group(const std::string& wname) const {
}
void GlobalWellInfo::update_group(const std::vector<Well::Status>& well_status, const std::vector<Well::InjectorCMode>& injection_cmode, const std::vector<Well::ProducerCMode>& production_cmode) {
if (well_status.size() != this->local_map.size())
throw std::logic_error("Size mismatch");
void GlobalWellInfo::update_injector(std::size_t well_index, Well::Status well_status, Well::InjectorCMode injection_cmode) {
if (well_status == Well::Status::OPEN && injection_cmode == Well::InjectorCMode::GRUP)
this->m_in_injecting_group[this->local_map[well_index]] = 1;
}
void GlobalWellInfo::update_producer(std::size_t well_index, Well::Status well_status, Well::ProducerCMode production_cmode) {
if (well_status == Well::Status::OPEN && production_cmode == Well::ProducerCMode::GRUP)
this->m_in_producing_group[this->local_map[well_index]] = 1;
}
void GlobalWellInfo::clear() {
this->m_in_injecting_group.assign(this->name_map.size(), 0);
this->m_in_producing_group.assign(this->name_map.size(), 0);
for (std::size_t well_index = 0; well_index < well_status.size(); well_index++) {
if (well_status[well_index] == Well::Status::OPEN) {
if (this->is_injector[well_index]) {
if (injection_cmode[well_index] == Well::InjectorCMode::GRUP)
this->m_in_injecting_group[this->local_map[well_index]] = 1;
} else {
if (production_cmode[well_index] == Well::ProducerCMode::GRUP)
this->m_in_producing_group[this->local_map[well_index]] = 1;
}
}
}
}

View File

@ -69,13 +69,14 @@ public:
GlobalWellInfo(const Schedule& sched, std::size_t report_step, const std::vector<Well>& local_wells);
bool in_producing_group(const std::string& wname) const;
bool in_injecting_group(const std::string& wname) const;
void update_group(const std::vector<Well::Status>& well_status, const std::vector<Well::InjectorCMode>& injection_cmode, const std::vector<Well::ProducerCMode>& production_cmode);
std::size_t well_index(const std::string& wname) const;
const std::string& well_name(std::size_t well_index) const;
void update_injector(std::size_t well_index, Well::Status well_status, Well::InjectorCMode injection_cmode);
void update_producer(std::size_t well_index, Well::Status well_status, Well::ProducerCMode production_cmode);
void clear();
private:
std::vector<std::size_t> local_map; // local_index -> global_index
std::vector<bool> is_injector; // local_index -> bool
std::map<std::string, std::size_t> name_map; // string -> global_index
std::vector<int> m_in_injecting_group; // global_index -> int/bool

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;
@ -1474,7 +1475,8 @@ updateThp(WellState& well_state,
// When there is no vaild VFP table provided, we set the thp to be zero.
if (!baseif_.isVFPActive(deferred_logger) || baseif_.wellIsStopped()) {
well_state.update_thp(baseif_.indexOfWell(), 0.);
auto& well = well_state.well(baseif_.indexOfWell());
well.thp = 0;
return;
}
@ -1492,9 +1494,9 @@ updateThp(WellState& well_state,
rates[ Gas ] = well_state.wellRates(baseif_.indexOfWell())[pu.phase_pos[ Gas ] ];
}
const double bhp = well_state.bhp(baseif_.indexOfWell());
well_state.update_thp(baseif_.indexOfWell(), this->calculateThpFromBhp(rates, bhp, rho, deferred_logger));
auto& well = well_state.well(baseif_.indexOfWell());
const double bhp = well.bhp;
well.thp = this->calculateThpFromBhp(rates, bhp, rho, deferred_logger);
}
template<typename FluidSystem, typename Indices, typename Scalar>
@ -1614,6 +1616,7 @@ updateWellStateFromPrimaryVariables(WellState& well_state,
assert( FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) );
const int oil_pos = pu.phase_pos[Oil];
auto& well = well_state.well(baseif_.indexOfWell());
auto& segments = well_state.segments(baseif_.indexOfWell());
auto& segment_rates = segments.rates;
auto& segment_pressure = segments.pressure;
@ -1658,7 +1661,7 @@ updateWellStateFromPrimaryVariables(WellState& well_state,
// update the segment pressure
segment_pressure[seg] = primary_variables_[seg][SPres];
if (seg == 0) { // top segment
well_state.update_bhp(baseif_.indexOfWell(), segment_pressure[seg]);
well.bhp = segment_pressure[seg];
}
}
updateThp(well_state, rho, deferred_logger);
@ -1795,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;
@ -1819,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

@ -136,8 +136,9 @@ void
MultisegmentWellGeneric<Scalar>::
scaleSegmentPressuresWithBhp(WellState& well_state) const
{
auto& well = well_state.well(baseif_.indexOfWell());
auto& segments = well_state.segments(baseif_.indexOfWell());
auto bhp = well_state.bhp(baseif_.indexOfWell());
const auto bhp = well.bhp;
segments.scale_pressure(bhp);
}

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;
}
@ -340,6 +341,7 @@ namespace Opm
// store a copy of the well state, we don't want to update the real well state
WellState well_state_copy = ebosSimulator.problem().wellModel().wellState();
const auto& group_state = ebosSimulator.problem().wellModel().groupState();
auto& ws = well_state_copy.well(this->index_of_well_);
// Get the current controls.
const auto& summary_state = ebosSimulator.vanguard().summaryState();
@ -353,12 +355,12 @@ 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;
}
well_state_copy.update_bhp(well_copy.index_of_well_, bhp);
ws.bhp = bhp;
well_copy.scaleSegmentPressuresWithBhp(well_state_copy);
// initialized the well rates with the potentials i.e. the well rates based on bhp

View File

@ -0,0 +1,60 @@
/*
Copyright 2021 Equinor ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/simulators/wells/SingleWellState.hpp>
namespace Opm {
SingleWellState::SingleWellState(bool is_producer, double temp)
: producer(is_producer)
, temperature(temp)
{}
void SingleWellState::init_timestep(const SingleWellState& other) {
if (this->producer != other.producer)
return;
if (this->status == Well::Status::SHUT)
return;
if (other.status == Well::Status::SHUT)
return;
this->bhp = other.bhp;
this->thp = other.thp;
this->temperature = other.temperature;
}
void SingleWellState::shut() {
this->bhp = 0;
this->thp = 0;
this->status = Well::Status::SHUT;
}
void SingleWellState::stop() {
this->thp = 0;
this->status = Well::Status::STOP;
}
}

View File

@ -0,0 +1,52 @@
/*
Copyright 2021 Equinor ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_SINGLE_WELL_STATE_HEADER_INCLUDED
#define OPM_SINGLE_WELL_STATE_HEADER_INCLUDED
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
namespace Opm {
class SingleWellState {
public:
SingleWellState(bool is_producer, double temp);
Well::Status status{Well::Status::OPEN};
bool producer;
double bhp{0};
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();
void stop();
};
}
#endif

View File

@ -255,7 +255,7 @@ updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_log
const int well_index = baseif_.indexOfWell();
const int np = baseif_.numPhases();
const auto& pu = baseif_.phaseUsage();
const auto& well = well_state.well(well_index);
// the weighted total well rate
double total_well_rate = 0.0;
for (int p = 0; p < np; ++p) {
@ -339,7 +339,7 @@ updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_log
// BHP
primary_variables_[Bhp] = well_state.bhp(baseif_.indexOfWell());
primary_variables_[Bhp] = well.bhp;
}
template<class FluidSystem, class Indices, class Scalar>
@ -553,10 +553,11 @@ updateThp(WellState& well_state,
static constexpr int Gas = WellInterfaceIndices<FluidSystem,Indices,Scalar>::Gas;
static constexpr int Oil = WellInterfaceIndices<FluidSystem,Indices,Scalar>::Oil;
static constexpr int Water = WellInterfaceIndices<FluidSystem,Indices,Scalar>::Water;
auto& well = well_state.well(baseif_.indexOfWell());
// When there is no vaild VFP table provided, we set the thp to be zero.
if (!baseif_.isVFPActive(deferred_logger) || baseif_.wellIsStopped()) {
well_state.update_thp(baseif_.indexOfWell(), 0);
well.thp = 0;
return;
}
@ -574,13 +575,12 @@ updateThp(WellState& well_state,
rates[ Gas ] = well_state.wellRates(baseif_.indexOfWell())[pu.phase_pos[ Gas ] ];
}
const double bhp = well_state.bhp(baseif_.indexOfWell());
const double bhp = well.bhp;
well_state.update_thp(baseif_.indexOfWell(),
this->calculateThpFromBhp(well_state,
rates,
bhp,
deferred_logger));
well.thp = this->calculateThpFromBhp(well_state,
rates,
bhp,
deferred_logger);
}
template<class FluidSystem, class Indices, class Scalar>
@ -652,7 +652,8 @@ updateWellStateFromPrimaryVariables(WellState& well_state,
F[pu.phase_pos[Gas]] += F_solvent;
}
well_state.update_bhp(baseif_.indexOfWell(), primary_variables_[Bhp]);
auto& well = well_state.well(baseif_.indexOfWell());
well.bhp = primary_variables_[Bhp];
// calculate the phase rates based on the primary variables
// for producers, this is not a problem, while not sure for injectors here

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

@ -547,6 +547,7 @@ namespace Opm
cq_s, perf_dis_gas_rate, perf_vap_oil_rate, deferred_logger);
auto& perf_data = well_state.perfData(this->index_of_well_);
auto& ws = well_state.well(this->index_of_well_);
if constexpr (has_polymer && Base::has_polymermw) {
if (this->isInjector()) {
// Store the original water flux computed from the reservoir quantities.
@ -694,7 +695,7 @@ namespace Opm
}
// Store the perforation pressure for later usage.
perf_data.pressure[perf] = well_state.bhp(this->index_of_well_) + this->perf_pressure_diffs_[perf];
perf_data.pressure[perf] = ws.bhp + this->perf_pressure_diffs_[perf];
}
@ -1156,7 +1157,7 @@ namespace Opm
const WellState& well_state,
DeferredLogger& deferred_logger)
{
const double bhp = well_state.bhp(index_of_well_);
const double bhp = well_state.well(index_of_well_).bhp;
std::vector<double> well_rates;
computeWellRatesWithBhp(ebos_simulator, bhp, well_rates, deferred_logger);
@ -1211,6 +1212,7 @@ namespace Opm
b_perf.resize(nperf * num_components_);
surf_dens_perf.resize(nperf * num_components_);
const int w = index_of_well_;
const auto& ws = well_state.well(this->index_of_well_);
const bool waterPresent = FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx);
const bool oilPresent = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx);
@ -1224,7 +1226,7 @@ namespace Opm
// Compute the average pressure in each well block
const auto& perf_press = well_state.perfData(w).pressure;
auto p_above = this->parallel_well_info_.communicateAboveValues(well_state.bhp(w),
auto p_above = this->parallel_well_info_.communicateAboveValues(ws.bhp,
perf_press.data(),
nperf);
@ -1681,14 +1683,15 @@ namespace Opm
// to replace the original one
WellState well_state_copy = ebosSimulator.problem().wellModel().wellState();
const auto& group_state = ebosSimulator.problem().wellModel().groupState();
auto& ws = well_state_copy.well(this->index_of_well_);
// 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;
}
well_state_copy.update_bhp(index_of_well_, bhp);
ws.bhp = bhp;
const double dt = ebosSimulator.timeStepSize();
bool converged = this->iterateWellEquations(ebosSimulator, dt, well_state_copy, group_state, deferred_logger);
@ -1836,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;
}
@ -1845,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

@ -61,20 +61,22 @@ public:
return this->m_data.size();
}
void add(const std::string& name, T&& value) {
T& add(const std::string& name, T&& value) {
if (index_map.count(name) != 0)
throw std::logic_error("An object with name: " + name + " already exists in container");
this->index_map.emplace(name, this->m_data.size());
this->m_data.push_back(std::forward<T>(value));
return this->m_data.back();
}
void add(const std::string& name, const T& value) {
T& add(const std::string& name, const T& value) {
if (index_map.count(name) != 0)
throw std::logic_error("An object with name: " + name + " already exists in container");
this->index_map.emplace(name, this->m_data.size());
this->m_data.push_back(value);
return this->m_data.back();
}
bool has(const std::string& name) const {

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,11 +90,12 @@ 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;
double current_bhp = well_state.bhp(well_index);
double current_bhp = ws.bhp;
if (bhp_limit > current_bhp)
return Well::ProducerCMode::BHP;
}
@ -164,12 +165,12 @@ activeProductionConstraint(const WellState& well_state,
if (controls.hasControl(Well::ProducerCMode::THP) && currentControl != Well::ProducerCMode::THP) {
const auto& thp = getTHPConstraint(summaryState);
double current_thp = well_state.thp(well_index);
double current_thp = ws.thp;
if (thp > current_thp)
return Well::ProducerCMode::THP;
}
return well_state.currentProductionControl(well_index);
return currentControl;
}
@ -181,14 +182,15 @@ activeInjectionConstraint(const WellState& well_state,
{
const PhaseUsage& pu = this->phaseUsage();
const int well_index = this->index_of_well_;
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)
{
const auto& bhp = controls.bhp_limit;
double current_bhp = well_state.bhp(well_index);
double current_bhp = ws.bhp;
if (bhp < current_bhp)
return Well::InjectorCMode::BHP;
}
@ -241,12 +243,12 @@ activeInjectionConstraint(const WellState& well_state,
if (controls.hasControl(Well::InjectorCMode::THP) && currentControl != Well::InjectorCMode::THP)
{
const auto& thp = getTHPConstraint(summaryState);
double current_thp = well_state.thp(well_index);
double current_thp = ws.thp;
if (thp < current_thp)
return Well::InjectorCMode::THP;
}
return well_state.currentInjectionControl(well_index);
return currentControl;
}
template <typename FluidSystem>
@ -256,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;
}
}
@ -374,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,
@ -393,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;
@ -404,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,
@ -421,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) {
@ -599,6 +600,7 @@ namespace Opm
// only bhp and wellRates are used to initilize the primaryvariables for standard wells
const auto& well = this->well_ecl_;
const int well_index = this->index_of_well_;
auto& ws = well_state.well(well_index);
const auto& pu = this->phaseUsage();
const int np = well_state.numPhases();
const auto& summaryState = ebos_simulator.vanguard().summaryState();
@ -608,7 +610,7 @@ namespace Opm
for (int p = 0; p<np; ++p) {
well_state.wellRates(well_index)[p] = 0.0;
}
well_state.update_thp(well_index, 0.0);
ws.thp = 0;
return;
}
@ -638,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:
@ -663,7 +665,7 @@ namespace Opm
rates[p] = well_state.wellRates(well_index)[p];
}
double bhp = this->calculateBhpFromThp(well_state, rates, well, summaryState, this->getRefDensity(), deferred_logger);
well_state.update_bhp(well_index, bhp);
ws.bhp = bhp;
// if the total rates are negative or zero
// we try to provide a better intial well rate
@ -678,7 +680,7 @@ namespace Opm
}
case Well::InjectorCMode::BHP:
{
well_state.update_bhp(well_index, controls.bhp_limit);
ws.bhp = controls.bhp_limit;
double total_rate = 0.0;
for (int p = 0; p<np; ++p) {
total_rate += well_state.wellRates(well_index)[p];
@ -721,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:
@ -864,7 +866,7 @@ namespace Opm
}
case Well::ProducerCMode::BHP:
{
well_state.update_bhp(well_index, controls.bhp_limit);
ws.bhp = controls.bhp_limit;
double total_rate = 0.0;
for (int p = 0; p<np; ++p) {
total_rate -= well_state.wellRates(well_index)[p];
@ -886,7 +888,7 @@ namespace Opm
rates[p] = well_state.wellRates(well_index)[p];
}
double bhp = this->calculateBhpFromThp(well_state, rates, well, summaryState, this->getRefDensity(), deferred_logger);
well_state.update_bhp(well_index, bhp);
ws.bhp = bhp;
// if the total rates are negative or zero
// we try to provide a better intial well rate

View File

@ -41,15 +41,12 @@ void WellState::base_init(const std::vector<double>& cellPressures,
// clear old name mapping
this->wellMap_.clear();
this->perfdata.clear();
this->status_.clear();
this->parallel_well_info_.clear();
this->wellrates_.clear();
this->bhp_.clear();
this->thp_.clear();
this->temperature_.clear();
this->segment_state.clear();
this->well_potentials_.clear();
this->productivity_index_.clear();
this->wells_.clear();
{
// const int nw = wells->number_of_wells;
const int nw = wells_ecl.size();
@ -91,21 +88,16 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
// May be overwritten below.
const auto& pu = this->phase_usage_;
const int np = pu.num_phases;
double temp = well.isInjector() ? well.injectionControls(summary_state).temperature : 273.15 + 15.56;
this->status_.add(well.name(), Well::Status::OPEN);
auto& ws = this->wells_.add(well.name(), SingleWellState{well.isProducer(), temp});
this->parallel_well_info_.add(well.name(), well_info);
this->wellrates_.add(well.name(), std::vector<double>(np, 0));
this->well_potentials_.add(well.name(), std::vector<double>(np, 0));
const int num_perf_this_well = well_info->communication().sum(well_perf_data.size());
this->segment_state.add(well.name(), SegmentState{});
this->perfdata.add(well.name(), PerfData{static_cast<std::size_t>(num_perf_this_well), well.isInjector(), this->phase_usage_});
this->bhp_.add(well.name(), 0.0);
this->thp_.add(well.name(), 0.0);
this->productivity_index_.add(well.name(), std::vector<double>(np, 0));
if ( well.isInjector() )
this->temperature_.add(well.name(), well.injectionControls(summary_state).temperature);
else
this->temperature_.add(well.name(), 273.15 + 15.56); // standard condition temperature
if ( num_perf_this_well == 0 )
return;
@ -126,7 +118,7 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
const double global_pressure = well_info->broadcastFirstPerforationValue(local_pressure);
if (well.getStatus() == Well::Status::OPEN) {
this->status_[w] = Well::Status::OPEN;
ws.status = Well::Status::OPEN;
}
if (well.getStatus() == Well::Status::STOP) {
@ -136,9 +128,9 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
// applicable, otherwise assign equal to
// first perforation cell pressure.
if (is_bhp) {
bhp_[w] = bhp_limit;
ws.bhp = bhp_limit;
} else {
bhp_[w] = global_pressure;
ws.bhp = global_pressure;
}
} else if (is_grup) {
// Well under group control.
@ -148,7 +140,7 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
// the well is an injector or producer)
// pressure in first perforation cell.
const double safety_factor = well.isInjector() ? 1.01 : 0.99;
bhp_[w] = safety_factor * global_pressure;
ws.bhp = safety_factor * global_pressure;
} else {
// Open well, under own control:
// 1. Rates: initialize well rates to match
@ -206,10 +198,10 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
// the well is an injector or producer)
// pressure in first perforation cell.
if (is_bhp) {
bhp_[w] = bhp_limit;
ws.bhp = bhp_limit;
} else {
const double safety_factor = well.isInjector() ? 1.01 : 0.99;
bhp_[w] = safety_factor * global_pressure;
ws.bhp = safety_factor * global_pressure;
}
}
@ -219,7 +211,7 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
: prod_controls.hasControl(Well::ProducerCMode::THP);
const double thp_limit = well.isInjector() ? inj_controls.thp_limit : prod_controls.thp_limit;
if (has_thp) {
thp_[w] = thp_limit;
ws.thp = thp_limit;
}
}
@ -265,15 +257,12 @@ void WellState::init(const std::vector<double>& cellPressures,
well_dissolved_gas_rates_.clear();
well_vaporized_oil_rates_.clear();
this->events_.clear();
{
const auto& wg_events = schedule[report_step].wellgroup_events();
for (const auto& ecl_well : wells_ecl) {
const auto& wname = ecl_well.name();
if (wg_events.has(wname))
this->events_.add( wname, wg_events.at(wname) );
else
this->events_.add( wname, Events() );
this->well(wname).events = wg_events.at(wname);
}
}
@ -307,25 +296,15 @@ void WellState::init(const std::vector<double>& cellPressures,
this->well_vaporized_oil_rates_.add(wname, 0);
}
is_producer_.clear();
for (int w = 0; w < nw; ++w) {
const auto& ecl_well = wells_ecl[w];
this->is_producer_.add( ecl_well.name(), ecl_well.isProducer());
}
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;
}
}
@ -356,31 +335,30 @@ void WellState::init(const std::vector<double>& cellPressures,
continue;
}
const auto& wname = well.name();
auto& new_well = this->well(w);
auto it = prevState->wellMap().find(well.name());
if (it != end)
{
const int newIndex = w;
const int oldIndex = it->second[ 0 ];
if (prevState->status_[oldIndex] == Well::Status::SHUT) {
const auto& prev_well = prevState->well(oldIndex);
new_well.init_timestep(prev_well);
if (prev_well.status == Well::Status::SHUT) {
// Well was shut in previous state, do not use its values.
continue;
}
if (is_producer_[newIndex] != prevState->is_producer_[oldIndex]) {
if (new_well.producer != prev_well.producer)
// Well changed to/from injector from/to producer, do not use its privious values.
continue;
}
// bhp
this->update_bhp( newIndex, prevState->bhp( oldIndex ));
// thp
this->update_thp( newIndex, prevState->thp( oldIndex ));
// If new target is set using WCONPROD, WCONINJE etc. we use the new control
if (!this->events_[w].hasEvent(WellState::event_mask)) {
current_injection_controls_[ newIndex ] = prevState->currentInjectionControl(oldIndex);
current_production_controls_[ newIndex ] = prevState->currentProductionControl(oldIndex);
if (!new_well.events.hasEvent(WellState::event_mask)) {
new_well.injection_cmode = prev_well.injection_cmode;
new_well.production_cmode = prev_well.production_cmode;
}
wellRates(w) = prevState->wellRates(oldIndex);
@ -436,7 +414,7 @@ void WellState::init(const std::vector<double>& cellPressures,
: well.productionControls(summary_state).hasControl(Well::ProducerCMode::THP);
if (!has_thp) {
this->update_thp(w, 0.0);
new_well.thp = 0;
}
}
}
@ -507,8 +485,8 @@ WellState::report(const int* globalCellIdxMap,
data::Wells res;
for( const auto& [wname, winfo]: this->wellMap() ) {
const auto well_index = winfo[ 0 ];
if ((this->status_[well_index] == Well::Status::SHUT) &&
! wasDynamicallyClosed(well_index))
const auto& ws = this->well(well_index);
if ((ws.status == Well::Status::SHUT) && !wasDynamicallyClosed(well_index))
{
continue;
}
@ -519,9 +497,9 @@ WellState::report(const int* globalCellIdxMap,
const auto& wv = this->wellRates(well_index);
data::Well well;
well.bhp = this->bhp(well_index);
well.thp = this->thp( well_index );
well.temperature = this->temperature( well_index );
well.bhp = ws.bhp;
well.thp = ws.thp;
well.temperature = ws.temperature;
if( pu.phase_used[BlackoilPhases::Aqua] ) {
well.rates.set(rt::wat, wv[ pu.phase_pos[BlackoilPhases::Aqua] ] );
@ -556,7 +534,7 @@ WellState::report(const int* globalCellIdxMap,
well.rates.set(rt::brine, brineWellRate(well_index));
}
if (is_producer_[well_index]) {
if (ws.producer) {
well.rates.set(rt::alq, getALQ(wname));
}
else {
@ -569,9 +547,9 @@ WellState::report(const int* globalCellIdxMap,
{
auto& curr = well.current_control;
curr.isProducer = this->is_producer_[well_index];
curr.prod = this->currentProductionControl(well_index);
curr.inj = this->currentInjectionControl(well_index);
curr.isProducer = ws.producer;
curr.prod = ws.production_cmode;
curr.inj = ws.injection_cmode;
}
const auto& pwinfo = *this->parallel_well_info_[well_index];
@ -680,6 +658,7 @@ void WellState::initWellStateMSWell(const std::vector<Well>& wells_ecl,
// what we do here, is to set the segment rates and perforation rates
for (int w = 0; w < nw; ++w) {
const auto& well_ecl = wells_ecl[w];
auto& ws = this->well(w);
if ( well_ecl.isMultiSegment() ) {
const WellSegments& segment_set = well_ecl.getSegments();
@ -748,7 +727,7 @@ void WellState::initWellStateMSWell(const std::vector<Well>& wells_ecl,
{
// top segment is always the first one, and its pressure is the well bhp
auto& segment_pressure = this->segments(w).pressure;
segment_pressure[0] = bhp(w);
segment_pressure[0] = ws.bhp;
const auto& perf_press = perf_data.pressure;
for (int seg = 1; seg < well_nseg; ++seg) {
if ( !segment_perforations[seg].empty() ) {
@ -777,7 +756,8 @@ void WellState::initWellStateMSWell(const std::vector<Well>& wells_ecl,
const auto& wname = well.name();
if (prev_well_state->segment_state.has(wname)) {
if (prev_well_state->status_[wname] == Well::Status::SHUT) {
const auto& prev_ws = prev_well_state->well(wname);
if (prev_ws.status == Well::Status::SHUT) {
continue;
}
@ -842,15 +822,14 @@ double WellState::brineWellRate(const int w) const
void WellState::stopWell(int well_index)
{
this->status_[well_index] = Well::Status::STOP;
this->thp_[well_index] = 0;
auto& ws = this->well(well_index);
ws.stop();
}
void WellState::shutWell(int well_index)
{
this->status_[well_index] = Well::Status::SHUT;
this->thp_[well_index] = 0;
this->bhp_[well_index] = 0;
auto& ws = this->well(well_index);
ws.shut();
const int np = numPhases();
this->wellrates_[well_index].assign(np, 0);
@ -935,7 +914,14 @@ void WellState::communicateGroupRates(const Comm& comm)
template<class Comm>
void WellState::updateGlobalIsGrup(const Comm& comm)
{
this->global_well_info.value().update_group(this->status_.data(), this->current_injection_controls_.data(), this->current_production_controls_.data());
this->global_well_info.value().clear();
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, ws.production_cmode);
else
this->global_well_info.value().update_injector(well_index, ws.status, ws.injection_cmode);
}
this->global_well_info.value().communicate(comm);
}

View File

@ -22,6 +22,7 @@
#define OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
#include <opm/simulators/wells/ALQState.hpp>
#include <opm/simulators/wells/SingleWellState.hpp>
#include <opm/simulators/wells/GlobalWellInfo.hpp>
#include <opm/simulators/wells/SegmentState.hpp>
#include <opm/simulators/wells/WellContainer.hpp>
@ -107,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)
@ -147,10 +140,6 @@ public:
static void calculateSegmentRates(const std::vector<std::vector<int>>& segment_inlets, const std::vector<std::vector<int>>&segment_perforations,
const std::vector<double>& perforation_rates, const int np, const int segment, std::vector<double>& segment_rates);
Events& events(std::size_t well_index) {
return this->events_[well_index];
}
/// One rate pr well
double solventWellRate(const int w) const;
@ -293,7 +282,7 @@ public:
void updateStatus(int well_index, Well::Status status);
void openWell(int well_index) {
this->status_[well_index] = Well::Status::OPEN;
this->wells_[well_index].status = Well::Status::OPEN;
}
void shutWell(int well_index);
@ -309,18 +298,6 @@ public:
return this->phase_usage_;
}
/// One bhp pressure per well.
void update_bhp(std::size_t well_index, double value) { bhp_[well_index] = value; }
double bhp(std::size_t well_index) const { return bhp_[well_index]; }
/// One thp pressure per well.
void update_thp(std::size_t well_index, double value) { thp_[well_index] = value; }
double thp(std::size_t well_index) const { return thp_[well_index]; }
/// One temperature per well.
void update_temperature(std::size_t well_index, double value) { temperature_[well_index] = value; }
double temperature(std::size_t well_index) const { return temperature_[well_index]; }
/// One rate per well and phase.
const WellContainer<std::vector<double>>& wellRates() const { return wellrates_; }
std::vector<double>& wellRates(std::size_t well_index) { return wellrates_[well_index]; }
@ -345,13 +322,26 @@ public:
}
const std::string& name(std::size_t well_index) const {
return this->status_.well_name(well_index);
return this->wells_.well_name(well_index);
}
bool producer(std::size_t well_index) const {
return this->is_producer_[well_index];
const SingleWellState& well(std::size_t well_index) const {
return this->wells_[well_index];
}
const SingleWellState& well(const std::string& well_name) const {
return this->wells_[well_name];
}
SingleWellState& well(std::size_t well_index) {
return this->wells_[well_index];
}
SingleWellState& well(const std::string& well_name) {
return this->wells_[well_name];
}
private:
WellMapType wellMap_;
@ -362,23 +352,12 @@ private:
ALQState alq_state;
bool do_glift_optimization_;
WellContainer<Well::Status> status_;
WellContainer<SingleWellState> wells_;
WellContainer<const ParallelWellInfo*> parallel_well_info_;
WellContainer<double> bhp_;
WellContainer<double> thp_;
WellContainer<double> temperature_;
WellContainer<std::vector<double>> wellrates_;
PhaseUsage phase_usage_;
WellContainer<PerfData> perfdata;
WellContainer<int> is_producer_; // Size equal to number of local wells.
// 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.
@ -396,11 +375,6 @@ private:
// should be zero for injection wells
WellContainer<double> well_vaporized_oil_rates_;
// some events happens to the well, like this well is a new well
// or new well control keywords happens
// \Note: for now, only WCON* keywords, and well status change is considered
WellContainer<Events> events_;
WellContainer<SegmentState> segment_state;
// Productivity Index

View File

@ -26,6 +26,7 @@
#include <opm/simulators/wells/GlobalWellInfo.hpp>
#include <opm/simulators/wells/ParallelWellInfo.hpp>
#include <opm/simulators/wells/WellState.hpp>
#include <opm/simulators/wells/SingleWellState.hpp>
#include <opm/simulators/wells/SegmentState.hpp>
#include <opm/simulators/wells/WellContainer.hpp>
#include <opm/simulators/wells/PerfData.hpp>
@ -575,5 +576,27 @@ GAS
}
BOOST_AUTO_TEST_CASE(TestSingleWellState) {
Opm::SingleWellState ws1(true, 1);
Opm::SingleWellState ws2(true, 2);
Opm::SingleWellState ws3(false, 3);
ws1.bhp = 100;
ws1.thp = 200;
ws2.init_timestep(ws1);
BOOST_CHECK_EQUAL(ws2.bhp, ws1.bhp);
BOOST_CHECK_EQUAL(ws2.thp, ws1.thp);
ws3.bhp = ws1.bhp * 2;
ws3.thp = ws1.thp * 2;
ws3.init_timestep(ws1);
BOOST_CHECK(ws3.bhp != ws1.bhp);
BOOST_CHECK(ws3.thp != ws1.thp);
}
BOOST_AUTO_TEST_SUITE_END()