mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Add trivial class SingleWellState with bhp and thp
This commit is contained in:
parent
3d3e9cca1b
commit
a54daf75e8
@ -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
|
||||
|
@ -172,8 +172,9 @@ 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);
|
||||
auto& ws = well_state.well(well_index);
|
||||
ws.bhp = rst_well.bhp;
|
||||
ws.thp = rst_well.thp;
|
||||
well_state.update_temperature(well_index, rst_well.temperature);
|
||||
|
||||
if (rst_well.current_control.isProducer) {
|
||||
|
@ -1474,7 +1474,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 +1493,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 +1615,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 +1660,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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -340,6 +340,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();
|
||||
@ -358,7 +359,7 @@ namespace Opm
|
||||
prod_controls.bhp_limit = bhp;
|
||||
well_state_copy.currentProductionControl(index_of_well_, 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
|
||||
|
43
opm/simulators/wells/SingleWellState.cpp
Normal file
43
opm/simulators/wells/SingleWellState.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
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 {
|
||||
|
||||
|
||||
void SingleWellState::init_timestep(const SingleWellState& other) {
|
||||
this->bhp = other.bhp;
|
||||
this->thp = other.thp;
|
||||
}
|
||||
|
||||
|
||||
void SingleWellState::shut() {
|
||||
this->bhp = 0;
|
||||
this->thp = 0;
|
||||
}
|
||||
|
||||
void SingleWellState::stop() {
|
||||
this->thp = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
42
opm/simulators/wells/SingleWellState.hpp
Normal file
42
opm/simulators/wells/SingleWellState.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
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
|
||||
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class SingleWellState {
|
||||
public:
|
||||
double bhp{0};
|
||||
double thp{0};
|
||||
|
||||
|
||||
void init_timestep(const SingleWellState& other);
|
||||
void shut();
|
||||
void stop();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -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
|
||||
|
@ -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,6 +1683,7 @@ 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()) {
|
||||
@ -1688,7 +1691,7 @@ namespace Opm
|
||||
} else {
|
||||
well_state_copy.currentProductionControl(index_of_well_, 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);
|
||||
|
@ -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 {
|
||||
|
@ -91,10 +91,11 @@ activeProductionConstraint(const WellState& well_state,
|
||||
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);
|
||||
|
||||
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,7 +165,7 @@ 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;
|
||||
}
|
||||
@ -181,6 +182,7 @@ 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);
|
||||
@ -188,7 +190,7 @@ activeInjectionConstraint(const WellState& well_state,
|
||||
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,7 +243,7 @@ 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;
|
||||
}
|
||||
|
@ -599,6 +599,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 +609,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;
|
||||
}
|
||||
|
||||
@ -663,7 +664,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 +679,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];
|
||||
@ -864,7 +865,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 +887,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
|
||||
|
@ -44,12 +44,11 @@ void WellState::base_init(const std::vector<double>& cellPressures,
|
||||
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();
|
||||
@ -92,6 +91,7 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
|
||||
const auto& pu = this->phase_usage_;
|
||||
const int np = pu.num_phases;
|
||||
|
||||
auto& ws = this->wells_.add(well.name(), SingleWellState{});
|
||||
this->status_.add(well.name(), Well::Status::OPEN);
|
||||
this->parallel_well_info_.add(well.name(), well_info);
|
||||
this->wellrates_.add(well.name(), std::vector<double>(np, 0));
|
||||
@ -99,8 +99,6 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
|
||||
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);
|
||||
@ -136,9 +134,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 +146,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 +204,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 +217,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,11 +354,17 @@ 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 ];
|
||||
|
||||
const auto& prev_well = prevState->well(oldIndex);
|
||||
new_well.init_timestep(prev_well);
|
||||
|
||||
|
||||
if (prevState->status_[oldIndex] == Well::Status::SHUT) {
|
||||
// Well was shut in previous state, do not use its values.
|
||||
continue;
|
||||
@ -371,12 +375,6 @@ void WellState::init(const std::vector<double>& cellPressures,
|
||||
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);
|
||||
@ -436,7 +434,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -512,6 +510,7 @@ WellState::report(const int* globalCellIdxMap,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const auto& ws = this->well(well_index);
|
||||
|
||||
const auto& reservoir_rates = this->well_reservoir_rates_[well_index];
|
||||
const auto& well_potentials = this->well_potentials_[well_index];
|
||||
@ -519,8 +518,8 @@ 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.bhp = ws.bhp;
|
||||
well.thp = ws.thp;
|
||||
well.temperature = this->temperature( well_index );
|
||||
|
||||
if( pu.phase_used[BlackoilPhases::Aqua] ) {
|
||||
@ -680,6 +679,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 +748,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() ) {
|
||||
@ -842,15 +842,16 @@ double WellState::brineWellRate(const int w) const
|
||||
|
||||
void WellState::stopWell(int well_index)
|
||||
{
|
||||
auto& ws = this->well(well_index);
|
||||
ws.stop();
|
||||
this->status_[well_index] = Well::Status::STOP;
|
||||
this->thp_[well_index] = 0;
|
||||
}
|
||||
|
||||
void WellState::shutWell(int well_index)
|
||||
{
|
||||
auto& ws = this->well(well_index);
|
||||
ws.shut();
|
||||
this->status_[well_index] = Well::Status::SHUT;
|
||||
this->thp_[well_index] = 0;
|
||||
this->bhp_[well_index] = 0;
|
||||
const int np = numPhases();
|
||||
this->wellrates_[well_index].assign(np, 0);
|
||||
|
||||
|
@ -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>
|
||||
@ -309,14 +310,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]; }
|
||||
@ -352,6 +345,23 @@ public:
|
||||
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,10 +372,9 @@ private:
|
||||
ALQState alq_state;
|
||||
bool do_glift_optimization_;
|
||||
|
||||
WellContainer<SingleWellState> wells_;
|
||||
WellContainer<Well::Status> status_;
|
||||
WellContainer<const ParallelWellInfo*> parallel_well_info_;
|
||||
WellContainer<double> bhp_;
|
||||
WellContainer<double> thp_;
|
||||
WellContainer<double> temperature_;
|
||||
WellContainer<std::vector<double>> wellrates_;
|
||||
PhaseUsage phase_usage_;
|
||||
|
@ -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,20 @@ GAS
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestSingleWellState) {
|
||||
Opm::SingleWellState ws1;
|
||||
Opm::SingleWellState ws2;
|
||||
|
||||
ws1.bhp = 100;
|
||||
ws1.thp = 200;
|
||||
|
||||
ws2.init_timestep(ws1);
|
||||
BOOST_CHECK_EQUAL(ws2.bhp, ws1.bhp);
|
||||
BOOST_CHECK_EQUAL(ws2.thp, ws1.thp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user