Use wellcontainer2 (#3255)

Use WellContainer<> to manage members in WellState
This commit is contained in:
Joakim Hove 2021-05-20 16:16:12 +02:00 committed by GitHub
parent b9f916080a
commit 506a349085
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 329 additions and 302 deletions

View File

@ -1979,20 +1979,19 @@ namespace Opm {
well_state.update_temperature( well_index, rst_well.temperature);
if (rst_well.current_control.isProducer) {
well_state.currentProductionControls()[ well_index ] = rst_well.current_control.prod;
well_state.currentProductionControl( well_index, rst_well.current_control.prod);
}
else {
well_state.currentInjectionControls()[ well_index ] = rst_well.current_control.inj;
well_state.currentInjectionControl( well_index, rst_well.current_control.inj);
}
const auto wellrate_index = well_index * np;
for( size_t i = 0; i < phs.size(); ++i ) {
assert( rst_well.rates.has( phs[ i ] ) );
well_state.wellRates()[ wellrate_index + i ] = rst_well.rates.get( phs[ i ] );
well_state.wellRates(well_index)[ i ] = rst_well.rates.get( phs[ i ] );
}
auto * perf_pressure = well_state.perfPress().data() + wm.second[1];
auto * perf_rates = well_state.perfRates().data() + wm.second[1];
auto& perf_pressure = well_state.perfPress(well_index);
auto& perf_rates = well_state.perfRates(well_index);
auto * perf_phase_rates = well_state.mutable_perfPhaseRates().data() + wm.second[1]*np;
const auto& perf_data = this->well_perf_data_[well_index];
@ -3370,6 +3369,7 @@ namespace Opm {
auto& well_info = *local_parallel_well_info_[wellID];
const int num_perf_this_well = well_info.communication().sum(well_perf_data_[wellID].size());
auto * perf_phase_rate = &this->wellState().perfPhaseRates()[connpos];
for (int perf = 0; perf < num_perf_this_well; ++perf) {
const int cell_idx = well_perf_data_[wellID][perf].cell_index;
@ -3382,7 +3382,7 @@ namespace Opm {
cellInternalEnergy = fs.enthalpy(phaseIdx).value() - fs.pressure(phaseIdx).value() / fs.density(phaseIdx).value();
cellBinv = fs.invB(phaseIdx).value();
cellDensity = fs.density(phaseIdx).value();
perfPhaseRate = this->wellState().perfPhaseRates()[connpos + perf*np + phaseIdx ];
perfPhaseRate = perf_phase_rate[ perf*np + phaseIdx ];
weight_factor += cellDensity * perfPhaseRate/cellBinv * cellInternalEnergy/cellTemperatures;
}
total_weight += weight_factor;

View File

@ -420,12 +420,11 @@ GasLiftStage2<TypeTag>::
getStdWellRates_(const WellInterface<TypeTag> &well)
{
const int well_index = well.indexOfWell();
const int np = this->well_state_.numPhases();
const auto& pu = well.phaseUsage();
auto oil_rate =
-this->well_state_.wellRates()[np * well_index + pu.phase_pos[Oil]];
-this->well_state_.wellRates(well_index)[pu.phase_pos[Oil]];
auto gas_rate =
-this->well_state_.wellRates()[np * well_index + pu.phase_pos[Gas]];
-this->well_state_.wellRates(well_index)[pu.phase_pos[Gas]];
return {oil_rate, gas_rate};
}

View File

@ -281,8 +281,8 @@ namespace Opm
const int top_segment_index = well_state.topSegmentIndex(index_of_well_);
auto * segment_rates = &well_state.segRates()[top_segment_index*this->number_of_phases_];
for (int phase = 0; phase < number_of_phases_; ++phase) {
const double well_phase_rate = well_state.wellRates()[number_of_phases_*index_of_well_ + phase];
const double unscaled_top_seg_rate = segment_rates[phase];
const double well_phase_rate = well_state.wellRates(index_of_well_)[phase];
if (std::abs(unscaled_top_seg_rate) > 1e-12)
{
for (int seg = 0; seg < numberOfSegments(); ++seg) {
@ -297,7 +297,7 @@ namespace Opm
}
std::vector<double> perforation_rates(number_of_phases_ * number_of_perforations_,0.0);
const double perf_phaserate_scaled = well_state.wellRates()[number_of_phases_ * index_of_well_ + phase] / sumTw;
const double perf_phaserate_scaled = well_state.wellRates(index_of_well_)[phase] / sumTw;
for (int perf = 0; perf < number_of_perforations_; ++perf) {
perforation_rates[number_of_phases_ * perf + phase] = well_index_[perf] * perf_phaserate_scaled;
}
@ -545,7 +545,7 @@ namespace Opm
/* {
bool pressure_controlled_well = false;
if (this->isInjector()) {
const Well::InjectorCMode& current = well_state.currentInjectionControls()[index_of_well_];
const Well::InjectorCMode& current = well_state.currentInjectionControl()[index_of_well_];
if (current == Well::InjectorCMode::BHP || current == Well::InjectorCMode::THP) {
pressure_controlled_well = true;
}
@ -566,7 +566,7 @@ namespace Opm
debug_cost_counter_ = 0;
// does the well have a THP related constraint?
const auto& summaryState = ebosSimulator.vanguard().summaryState();
const Well::ProducerCMode& current_control = well_state.currentProductionControls()[this->index_of_well_];
auto current_control = well_state.currentProductionControl(this->index_of_well_);
if ( !Base::wellHasTHPConstraints(summaryState) || current_control == Well::ProducerCMode::BHP) {
computeWellRatesAtBhpLimit(ebosSimulator, well_potentials, deferred_logger);
} else {
@ -626,10 +626,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.currentInjectionControls()[index_of_well_] = Well::InjectorCMode::BHP;
well_state_copy.currentInjectionControl(index_of_well_, Well::InjectorCMode::BHP);
} else {
prod_controls.bhp_limit = bhp;
well_state_copy.currentProductionControls()[index_of_well_] = Well::ProducerCMode::BHP;
well_state_copy.currentProductionControl(index_of_well_, Well::ProducerCMode::BHP);
}
well_state_copy.update_bhp(well_copy.index_of_well_, bhp);
well_copy.scaleSegmentPressuresWithBhp(well_state_copy);
@ -638,7 +638,7 @@ namespace Opm
const int np = number_of_phases_;
const double sign = well_copy.well_ecl_.isInjector() ? 1.0 : -1.0;
for (int phase = 0; phase < np; ++phase){
well_state_copy.wellRates()[well_copy.index_of_well_*np + phase]
well_state_copy.wellRates(well_copy.index_of_well_)[phase]
= sign * well_state_copy.wellPotentials()[well_copy.index_of_well_*np + phase];
}
well_copy.scaleSegmentRatesWithWellRates(well_state_copy);
@ -1847,13 +1847,13 @@ namespace Opm
const PhaseUsage& pu = phaseUsage();
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
rates[ Water ] = well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[ Water ] ];
rates[ Water ] = well_state.wellRates(index_of_well_)[pu.phase_pos[ Water ] ];
}
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
rates[ Oil ] = well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[ Oil ] ];
rates[ Oil ] = well_state.wellRates(index_of_well_)[pu.phase_pos[ Oil ] ];
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
rates[ Gas ] = well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[ Gas ] ];
rates[ Gas ] = well_state.wellRates(index_of_well_)[pu.phase_pos[ Gas ] ];
}
const double bhp = well_state.bhp(index_of_well_);
@ -2376,7 +2376,7 @@ namespace Opm
const double phase_rate = g_total * fractions[p];
segment_rates[seg*this->number_of_phases_ + p] = phase_rate;
if (seg == 0) { // top segment
well_state.wellRates()[index_of_well_ * number_of_phases_ + p] = phase_rate;
well_state.wellRates(index_of_well_)[p] = phase_rate;
}
}
@ -2644,7 +2644,7 @@ namespace Opm
const EvalWell seg_pressure = getSegmentPressure(seg);
const int rate_start_offset = first_perf_ * number_of_phases_;
auto * perf_rates = &well_state.mutable_perfPhaseRates()[rate_start_offset];
auto * perf_press_state = &well_state.perfPress()[first_perf_];
auto& perf_press_state = well_state.perfPress(this->index_of_well_);
for (const int perf : segment_perforations_[seg]) {
const int cell_idx = well_cells_[perf];
const auto& int_quants = *(ebosSimulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/ 0));
@ -3063,7 +3063,7 @@ namespace Opm
const int well_index = index_of_well_;
if (this->isInjector() )
{
const Well::InjectorCMode& current = well_state.currentInjectionControls()[well_index];
auto current = well_state.currentInjectionControl(well_index);
switch(current) {
case Well::InjectorCMode::THP:
control_tolerance = param_.tolerance_pressure_ms_wells_;
@ -3085,7 +3085,7 @@ namespace Opm
if (this->isProducer() )
{
const Well::ProducerCMode& current = well_state.currentProductionControls()[well_index];
auto current = well_state.currentProductionControl(well_index);
switch(current) {
case Well::ProducerCMode::THP:
control_tolerance = param_.tolerance_pressure_ms_wells_; // 0.1 bar
@ -3130,7 +3130,7 @@ namespace Opm
const int well_index = index_of_well_;
if (this->isInjector() )
{
const Well::InjectorCMode& current = well_state.currentInjectionControls()[well_index];
auto current = well_state.currentInjectionControl(well_index);
switch(current) {
case Well::InjectorCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;
@ -3156,7 +3156,7 @@ namespace Opm
if (this->isProducer() )
{
const Well::ProducerCMode& current = well_state.currentProductionControls()[well_index];
auto current = well_state.currentProductionControl(well_index);
switch(current) {
case Well::ProducerCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;

View File

@ -848,7 +848,7 @@ namespace Opm
}
// Store the perforation pressure for later usage.
auto * perf_press = &well_state.perfPress()[first_perf_];
auto& perf_press = well_state.perfPress(index_of_well_);
perf_press[perf] = well_state.bhp(index_of_well_) + perf_pressure_diffs_[perf];
}
@ -1271,21 +1271,21 @@ namespace Opm
if (this->isProducer()) {
const double g_total = primary_variables_[WQTotal];
for (int p = 0; p < number_of_phases_; ++p) {
well_state.wellRates()[index_of_well_ * number_of_phases_ + p] = g_total * F[p];
well_state.wellRates(index_of_well_)[p] = g_total * F[p];
}
} else { // injectors
for (int p = 0; p < number_of_phases_; ++p) {
well_state.wellRates()[index_of_well_ * number_of_phases_ + p] = 0.0;
well_state.wellRates(index_of_well_)[p] = 0.0;
}
switch (this->wellEcl().injectorType()) {
case InjectorType::WATER:
well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[Water]] = primary_variables_[WQTotal];
well_state.wellRates(index_of_well_)[pu.phase_pos[Water]] = primary_variables_[WQTotal];
break;
case InjectorType::GAS:
well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[Gas]] = primary_variables_[WQTotal];
well_state.wellRates(index_of_well_)[pu.phase_pos[Gas]] = primary_variables_[WQTotal];
break;
case InjectorType::OIL:
well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[Oil]] = primary_variables_[WQTotal];
well_state.wellRates(index_of_well_)[pu.phase_pos[Oil]] = primary_variables_[WQTotal];
break;
case InjectorType::MULTI:
// Not supported.
@ -1328,13 +1328,13 @@ namespace Opm
const Opm::PhaseUsage& pu = phaseUsage();
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
rates[ Water ] = well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[ Water ] ];
rates[ Water ] = well_state.wellRates(index_of_well_)[pu.phase_pos[ Water ] ];
}
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
rates[ Oil ] = well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[ Oil ] ];
rates[ Oil ] = well_state.wellRates(index_of_well_)[pu.phase_pos[ Oil ] ];
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
rates[ Gas ] = well_state.wellRates()[index_of_well_ * number_of_phases_ + pu.phase_pos[ Gas ] ];
rates[ Gas ] = well_state.wellRates(index_of_well_)[pu.phase_pos[ Gas ] ];
}
const double bhp = well_state.bhp(index_of_well_);
@ -1665,9 +1665,9 @@ namespace Opm
}
// Compute the average pressure in each well block
const auto * perf_press = &well_state.perfPress()[first_perf_];
const auto& perf_press = well_state.perfPress(w);
auto p_above = this->parallel_well_info_.communicateAboveValues(well_state.bhp(w),
perf_press,
perf_press.data(),
nperf);
for (int perf = 0; perf < nperf; ++perf) {
@ -1690,14 +1690,12 @@ namespace Opm
if (gasPresent) {
const unsigned gasCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::gasCompIdx);
const int gaspos = gasCompIdx + perf * num_components_;
const int gaspos_well = pu.phase_pos[Gas] + w * pu.num_phases;
if (oilPresent) {
const int oilpos_well = pu.phase_pos[Oil] + w * pu.num_phases;
const double oilrate = std::abs(well_state.wellRates()[oilpos_well]); //in order to handle negative rates in producers
const double oilrate = std::abs(well_state.wellRates(w)[pu.phase_pos[Oil]]); //in order to handle negative rates in producers
rvmax_perf[perf] = FluidSystem::gasPvt().saturatedOilVaporizationFactor(fs.pvtRegionIndex(), temperature, p_avg);
if (oilrate > 0) {
const double gasrate = std::abs(well_state.wellRates()[gaspos_well]) - (has_solvent ? well_state.solventWellRate(w) : 0.0);
const double gasrate = std::abs(well_state.wellRates(w)[pu.phase_pos[Gas]]) - (has_solvent ? well_state.solventWellRate(w) : 0.0);
double rv = 0.0;
if (gasrate > 0) {
rv = oilrate / gasrate;
@ -1718,13 +1716,11 @@ namespace Opm
if (oilPresent) {
const unsigned oilCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::oilCompIdx);
const int oilpos = oilCompIdx + perf * num_components_;
const int oilpos_well = pu.phase_pos[Oil] + w * pu.num_phases;
if (gasPresent) {
rsmax_perf[perf] = FluidSystem::oilPvt().saturatedGasDissolutionFactor(fs.pvtRegionIndex(), temperature, p_avg);
const int gaspos_well = pu.phase_pos[Gas] + w * pu.num_phases;
const double gasrate = std::abs(well_state.wellRates()[gaspos_well]) - (has_solvent ? well_state.solventWellRate(w) : 0.0);
const double gasrate = std::abs(well_state.wellRates(w)[pu.phase_pos[Gas]]) - (has_solvent ? well_state.solventWellRate(w) : 0.0);
if (gasrate > 0) {
const double oilrate = std::abs(well_state.wellRates()[oilpos_well]);
const double oilrate = std::abs(well_state.wellRates(w)[pu.phase_pos[Oil]]);
double rs = 0.0;
if (oilrate > 0) {
rs = gasrate / oilrate;
@ -2423,9 +2419,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.currentInjectionControls()[index_of_well_] = Well::InjectorCMode::BHP;
well_state_copy.currentInjectionControl(index_of_well_, Well::InjectorCMode::BHP);
} else {
well_state_copy.currentProductionControls()[index_of_well_] = Well::ProducerCMode::BHP;
well_state_copy.currentProductionControl(index_of_well_, Well::ProducerCMode::BHP);
}
well_state_copy.update_bhp(index_of_well_, bhp);
@ -2507,8 +2503,7 @@ namespace Opm
}
if (this->glift_optimize_only_thp_wells) {
const int well_index = index_of_well_;
const Well::ProducerCMode& control_mode
= well_state.currentProductionControls()[well_index];
auto control_mode = well_state.currentProductionControl(well_index);
if (control_mode != Well::ProducerCMode::THP ) {
gliftDebug("Not THP control", deferred_logger);
return false;
@ -2691,7 +2686,7 @@ namespace Opm
// does the well have a THP related constraint?
const auto& summaryState = ebosSimulator.vanguard().summaryState();
const Well::ProducerCMode& current_control = well_state.currentProductionControls()[this->index_of_well_];
auto current_control = well_state.currentProductionControl(this->index_of_well_);
if ( !well.Base::wellHasTHPConstraints(summaryState) || current_control == Well::ProducerCMode::BHP ) {
// get the bhp value based on the bhp constraints
const double bhp = well.mostStrictBhpFromBhpLimits(summaryState);
@ -2721,7 +2716,7 @@ namespace Opm
// the weighted total well rate
double total_well_rate = 0.0;
for (int p = 0; p < np; ++p) {
total_well_rate += scalingFactor(p) * well_state.wellRates()[np * well_index + p];
total_well_rate += scalingFactor(p) * well_state.wellRates(well_index)[p];
}
// Not: for the moment, the first primary variable for the injectors is not G_total. The injection rate
@ -2729,13 +2724,13 @@ namespace Opm
if (this->isInjector()) {
switch (this->wellEcl().injectorType()) {
case InjectorType::WATER:
primary_variables_[WQTotal] = well_state.wellRates()[np * well_index + pu.phase_pos[Water]];
primary_variables_[WQTotal] = well_state.wellRates(well_index)[pu.phase_pos[Water]];
break;
case InjectorType::GAS:
primary_variables_[WQTotal] = well_state.wellRates()[np * well_index + pu.phase_pos[Gas]];
primary_variables_[WQTotal] = well_state.wellRates(well_index)[pu.phase_pos[Gas]];
break;
case InjectorType::OIL:
primary_variables_[WQTotal] = well_state.wellRates()[np * well_index + pu.phase_pos[Oil]];
primary_variables_[WQTotal] = well_state.wellRates(well_index)[pu.phase_pos[Oil]];
break;
case InjectorType::MULTI:
// Not supported.
@ -2749,10 +2744,10 @@ namespace Opm
if (std::abs(total_well_rate) > 0.) {
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
primary_variables_[WFrac] = scalingFactor(pu.phase_pos[Water]) * well_state.wellRates()[np*well_index + pu.phase_pos[Water]] / total_well_rate;
primary_variables_[WFrac] = scalingFactor(pu.phase_pos[Water]) * well_state.wellRates(well_index)[pu.phase_pos[Water]] / total_well_rate;
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
primary_variables_[GFrac] = scalingFactor(pu.phase_pos[Gas]) * (well_state.wellRates()[np*well_index + pu.phase_pos[Gas]]
primary_variables_[GFrac] = scalingFactor(pu.phase_pos[Gas]) * (well_state.wellRates(well_index)[pu.phase_pos[Gas]]
- (has_solvent ? well_state.solventWellRate(well_index) : 0.0) ) / total_well_rate ;
}
if constexpr (has_solvent) {
@ -3276,7 +3271,7 @@ namespace Opm
}
else if (this->isInjector() )
{
const Opm::Well::InjectorCMode& current = well_state.currentInjectionControls()[well_index];
auto current = well_state.currentInjectionControl(well_index);
switch(current) {
case Well::InjectorCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;
@ -3301,7 +3296,7 @@ namespace Opm
}
else if (this->isProducer() )
{
const Well::ProducerCMode& current = well_state.currentProductionControls()[well_index];
auto current = well_state.currentProductionControl(well_index);
switch(current) {
case Well::ProducerCMode::THP:
ctrltype = CR::WellFailure::Type::ControlTHP;

View File

@ -55,23 +55,23 @@ public:
std::size_t size() const {
return this->data.size();
return this->m_data.size();
}
void 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->data.size());
this->data.push_back(std::forward<T>(value));
this->index_map.emplace(name, this->m_data.size());
this->m_data.push_back(std::forward<T>(value));
}
void 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->data.size());
this->data.push_back(value);
this->index_map.emplace(name, this->m_data.size());
this->m_data.push_back(value);
}
bool has(const std::string& name) const {
@ -81,20 +81,20 @@ public:
void update(const std::string& name, T&& value) {
auto index = this->index_map.at(name);
this->data[index] = std::forward<T>(value);
this->m_data[index] = std::forward<T>(value);
}
void update(const std::string& name, const T& value) {
auto index = this->index_map.at(name);
this->data[index] = value;
this->m_data[index] = value;
}
void update(std::size_t index, T&& value) {
this->data.at(index) = std::forward<T>(value);
this->m_data.at(index) = std::forward<T>(value);
}
void update(std::size_t index, const T& value) {
this->data.at(index) = value;
this->m_data.at(index) = value;
}
/*
@ -103,7 +103,7 @@ public:
*/
void copy_welldata(const WellContainer<T>& other) {
if (this->index_map == other.index_map)
this->data = other.data;
this->m_data = other.m_data;
else {
for (const auto& [name, index] : this->index_map)
this->update_if(index, name, other);
@ -117,40 +117,45 @@ public:
void copy_welldata(const WellContainer<T>& other, const std::string& name) {
auto this_index = this->index_map.at(name);
auto other_index = other.index_map.at(name);
this->data[this_index] = other.data[other_index];
this->m_data[this_index] = other.m_data[other_index];
}
T& operator[](std::size_t index) {
return this->data.at(index);
return this->m_data.at(index);
}
const T& operator[](std::size_t index) const {
return this->data.at(index);
return this->m_data.at(index);
}
T& operator[](const std::string& name) {
auto index = this->index_map.at(name);
return this->data[index];
return this->m_data[index];
}
const T& operator[](const std::string& name) const {
auto index = this->index_map.at(name);
return this->data[index];
return this->m_data[index];
}
void clear() {
this->data.clear();
this->m_data.clear();
this->index_map.clear();
}
typename std::vector<T>::const_iterator begin() const {
return this->data.begin();
return this->m_data.begin();
}
typename std::vector<T>::const_iterator end() const {
return this->data.end();
return this->m_data.end();
}
const std::vector<T>& data() const {
return this->m_data;
}
private:
void update_if(std::size_t index, const std::string& name, const WellContainer<T>& other) {
auto other_iter = other.index_map.find(name);
@ -158,11 +163,11 @@ private:
return;
auto other_index = other_iter->second;
this->data[index] = other.data[other_index];
this->m_data[index] = other.m_data[other_index];
}
std::vector<T> data;
std::vector<T> m_data;
std::unordered_map<std::string, std::size_t> index_map;
};

View File

@ -31,6 +31,7 @@
#include <opm/simulators/wells/TargetCalculator.hpp>
#include <opm/simulators/wells/VFPProdProperties.hpp>
#include <opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp>
#include <opm/simulators/wells/WellContainer.hpp>
#include <algorithm>
#include <cassert>
@ -125,7 +126,7 @@ namespace WellGroupHelpers
schedule.getGroup(group.parent(), reportStepIdx), schedule, reportStepIdx, factor);
}
double sumWellPhaseRates(const std::vector<double>& rates,
double sumWellPhaseRates(const WellContainer<std::vector<double>>& rates,
const Group& group,
const Schedule& schedule,
const WellStateFullyImplicitBlackoil& wellState,
@ -162,11 +163,11 @@ namespace WellGroupHelpers
continue;
double factor = wellEcl.getEfficiencyFactor();
const auto wellrate_index = well_index * wellState.numPhases();
const auto& well_rates = rates[well_index];
if (injector)
rate += factor * rates[wellrate_index + phasePos];
rate += factor * well_rates[phasePos];
else
rate -= factor * rates[wellrate_index + phasePos];
rate -= factor * well_rates[phasePos];
}
const auto& gefac = group.getGroupEfficiencyFactor();
return gefac * rate;
@ -391,18 +392,17 @@ namespace WellGroupHelpers
continue;
}
const auto wellrate_index = well_index * wellState.numPhases();
const double efficiency = wellTmp.getEfficiencyFactor();
// add contributino from wells not under group control
if (isInjector) {
if (wellState.currentInjectionControls()[well_index] != Well::InjectorCMode::GRUP)
if (wellState.currentInjectionControl(well_index) != Well::InjectorCMode::GRUP)
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] += wellStateNupcol.wellRates()[wellrate_index + phase] * efficiency;
groupTargetReduction[phase] += wellStateNupcol.wellRates(well_index)[phase] * efficiency;
}
} else {
if (wellState.currentProductionControls()[well_index] != Well::ProducerCMode::GRUP)
if (wellState.currentProductionControl(well_index) != Well::ProducerCMode::GRUP)
for (int phase = 0; phase < np; phase++) {
groupTargetReduction[phase] -= wellStateNupcol.wellRates()[wellrate_index + phase] * efficiency;
groupTargetReduction[phase] -= wellStateNupcol.wellRates(well_index)[phase] * efficiency;
}
}
}
@ -491,7 +491,7 @@ namespace WellGroupHelpers
if (!wellTmp.isInjector())
sign = -1;
for (int phase = 0; phase < np; ++phase) {
rates[phase] = sign * wellStateNupcol.wellRates()[well_index * np + phase];
rates[phase] = sign * wellStateNupcol.wellRates(well_index)[phase];
}
}
wellState.setCurrentWellRates(wellName, rates);

View File

@ -39,6 +39,9 @@ class Schedule;
class VFPProdProperties;
class WellStateFullyImplicitBlackoil;
template <typename>
class WellContainer;
namespace Network { class ExtNetwork; }
namespace WellGroupHelpers
@ -58,7 +61,7 @@ namespace WellGroupHelpers
const int reportStepIdx,
double& factor);
double sumWellPhaseRates(const std::vector<double>& rates,
double sumWellPhaseRates(const WellContainer<std::vector<double>>& rates,
const Group& group,
const Schedule& schedule,
const WellStateFullyImplicitBlackoil& wellState,

View File

@ -321,7 +321,7 @@ namespace Opm
double wsalt() const;
bool checkRateEconLimits(const WellEconProductionLimits& econ_production_limits,
const std::vector<double>& well_rates,
const double * rates_or_potentials,
DeferredLogger& deferred_logger) const;
template <class ValueType>

View File

@ -214,9 +214,9 @@ namespace Opm
const auto& well = well_ecl_;
std::string from;
if (well.isInjector()) {
from = Well::InjectorCMode2String(well_state.currentInjectionControls()[index_of_well_]);
from = Well::InjectorCMode2String(well_state.currentInjectionControl(index_of_well_));
} else {
from = Well::ProducerCMode2String(well_state.currentProductionControls()[index_of_well_]);
from = Well::ProducerCMode2String(well_state.currentProductionControl(index_of_well_));
}
bool changed = false;
@ -235,9 +235,9 @@ namespace Opm
if (changed) {
std::string to;
if (well.isInjector()) {
to = Well::InjectorCMode2String(well_state.currentInjectionControls()[index_of_well_]);
to = Well::InjectorCMode2String(well_state.currentInjectionControl(index_of_well_));
} else {
to = Well::ProducerCMode2String(well_state.currentProductionControls()[index_of_well_]);
to = Well::ProducerCMode2String(well_state.currentProductionControl(index_of_well_));
}
std::ostringstream ss;
ss << " Switching control mode for well " << name()
@ -262,15 +262,14 @@ namespace Opm
bool
WellInterface<TypeTag>::
checkRateEconLimits(const WellEconProductionLimits& econ_production_limits,
const std::vector<double>& well_rates,
const double * rates_or_potentials,
DeferredLogger& deferred_logger) const
{
const PhaseUsage& pu = phaseUsage();
const int np = number_of_phases_;
if (econ_production_limits.onMinOilRate()) {
assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
const double oil_rate = well_rates[index_of_well_ * np + pu.phase_pos[ Oil ] ];
const double oil_rate = rates_or_potentials[pu.phase_pos[ Oil ] ];
const double min_oil_rate = econ_production_limits.minOilRate();
if (std::abs(oil_rate) < min_oil_rate) {
return true;
@ -279,7 +278,7 @@ namespace Opm
if (econ_production_limits.onMinGasRate() ) {
assert(FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx));
const double gas_rate = well_rates[index_of_well_ * np + pu.phase_pos[ Gas ] ];
const double gas_rate = rates_or_potentials[pu.phase_pos[ Gas ] ];
const double min_gas_rate = econ_production_limits.minGasRate();
if (std::abs(gas_rate) < min_gas_rate) {
return true;
@ -289,8 +288,8 @@ namespace Opm
if (econ_production_limits.onMinLiquidRate() ) {
assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
assert(FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx));
const double oil_rate = well_rates[index_of_well_ * np + pu.phase_pos[ Oil ] ];
const double water_rate = well_rates[index_of_well_ * np + pu.phase_pos[ Water ] ];
const double oil_rate = rates_or_potentials[pu.phase_pos[ Oil ] ];
const double water_rate = rates_or_potentials[pu.phase_pos[ Water ] ];
const double liquid_rate = oil_rate + water_rate;
const double min_liquid_rate = econ_production_limits.minLiquidRate();
if (std::abs(liquid_rate) < min_liquid_rate) {
@ -558,7 +557,7 @@ namespace Opm
std::vector<double> well_rates(np, 0.0);
for (int p = 0; p < np; ++p) {
well_rates[p] = well_state.wellRates()[index_of_well_ * np + p];
well_rates[p] = well_state.wellRates(index_of_well_)[p];
}
const double well_ratio = ratioFunc(well_rates, phaseUsage());
@ -682,11 +681,12 @@ namespace Opm
bool rate_limit_violated = false;
const auto& quantity_limit = econ_production_limits.quantityLimit();
const int np = number_of_phases_;
if (econ_production_limits.onAnyRateLimit()) {
if (quantity_limit == WellEconProductionLimits::QuantityLimit::POTN)
rate_limit_violated = checkRateEconLimits(econ_production_limits, well_state.wellPotentials(), deferred_logger);
rate_limit_violated = checkRateEconLimits(econ_production_limits, &well_state.wellPotentials()[index_of_well_ * np], deferred_logger);
else {
rate_limit_violated = checkRateEconLimits(econ_production_limits, well_state.wellRates(), deferred_logger);
rate_limit_violated = checkRateEconLimits(econ_production_limits, well_state.wellRates(index_of_well_).data(), deferred_logger);
}
}
@ -932,16 +932,15 @@ namespace Opm
const int np = number_of_phases_;
std::vector<double> surface_rates(np, 0.0);
const int well_rate_index = np * index_of_well_;
for (int p = 0; p < np; ++p) {
surface_rates[p] = well_state.wellRates()[well_rate_index + p];
surface_rates[p] = well_state.wellRates(index_of_well_)[p];
}
std::vector<double> voidage_rates(np, 0.0);
rateConverter_.calcReservoirVoidageRates(fipreg, pvtRegionIdx_, surface_rates, voidage_rates);
for (int p = 0; p < np; ++p) {
well_state.wellReservoirRates()[well_rate_index + p] = voidage_rates[p];
well_state.wellReservoirRates(index_of_well_)[p] = voidage_rates[p];
}
}
@ -1170,7 +1169,7 @@ namespace Opm
{
this->operability_status_.reset();
const Well::ProducerCMode& current_control = well_state.currentProductionControls()[this->index_of_well_];
auto current_control = well_state.currentProductionControl(this->index_of_well_);
// Operability checking is not free
// Only check wells under BHP and THP control
if(current_control == Well::ProducerCMode::BHP || current_control == Well::ProducerCMode::THP) {
@ -1201,7 +1200,7 @@ namespace Opm
if (this->wellIsStopped()) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = 0.0;
well_state.wellRates(well_index)[p] = 0.0;
}
well_state.update_thp(well_index, 0.0);
return;
@ -1233,12 +1232,12 @@ namespace Opm
OPM_DEFLOG_THROW(std::runtime_error, "Expected WATER, OIL or GAS as type for injectors " + name(), deferred_logger );
}
const Well::InjectorCMode& current = well_state.currentInjectionControls()[well_index];
auto current = well_state.currentInjectionControl(well_index);
switch(current) {
case Well::InjectorCMode::RATE:
{
well_state.wellRates()[well_index*np + phasePos] = controls.surface_rate;
well_state.wellRates(well_index)[phasePos] = controls.surface_rate;
break;
}
@ -1247,7 +1246,7 @@ namespace Opm
std::vector<double> convert_coeff(number_of_phases_, 1.0);
rateConverter_.calcCoeff(/*fipreg*/ 0, pvtRegionIdx_, convert_coeff);
const double coeff = convert_coeff[phasePos];
well_state.wellRates()[well_index*np + phasePos] = controls.reservoir_rate/coeff;
well_state.wellRates(well_index)[phasePos] = controls.reservoir_rate/coeff;
break;
}
@ -1255,7 +1254,7 @@ namespace Opm
{
std::vector<double> rates(3, 0.0);
for (int p = 0; p<np; ++p) {
rates[p] = well_state.wellRates()[well_index*np + p];
rates[p] = well_state.wellRates(well_index)[p];
}
double bhp = calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
well_state.update_bhp(well_index, bhp);
@ -1266,7 +1265,7 @@ namespace Opm
double total_rate = std::accumulate(rates.begin(), rates.end(), 0.0);
if (total_rate <= 0.0){
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = well_state.wellPotentials()[well_index*np + p];
well_state.wellRates(well_index)[p] = well_state.wellPotentials()[well_index*np + p];
}
}
break;
@ -1276,14 +1275,14 @@ namespace Opm
well_state.update_bhp(well_index, controls.bhp_limit);
double total_rate = 0.0;
for (int p = 0; p<np; ++p) {
total_rate += well_state.wellRates()[well_index*np + p];
total_rate += well_state.wellRates(well_index)[p];
}
// if the total rates are negative or zero
// we try to provide a better intial well rate
// using the well potentials
if (total_rate <= 0.0){
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = well_state.wellPotentials()[well_index*np + p];
well_state.wellRates(well_index)[p] = well_state.wellPotentials()[well_index*np + p];
}
}
break;
@ -1303,24 +1302,24 @@ namespace Opm
//Producer
else
{
const Well::ProducerCMode& current = well_state.currentProductionControls()[well_index];
auto current = well_state.currentProductionControl(well_index);
const auto& controls = well.productionControls(summaryState);
switch (current) {
case Well::ProducerCMode::ORAT:
{
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
double current_rate = -well_state.wellRates(well_index)[ pu.phase_pos[Oil] ];
// for trivial rates or opposite direction we don't just scale the rates
// but use either the potentials or the mobility ratio to initial the well rates
if (current_rate > 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] *= controls.oil_rate/current_rate;
well_state.wellRates(well_index)[p] *= controls.oil_rate/current_rate;
}
} else {
const std::vector<double> fractions = initialWellRateFractions(ebos_simulator, well_state.wellPotentials());
double control_fraction = fractions[pu.phase_pos[Oil]];
if (control_fraction != 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = - fractions[p] * controls.oil_rate/control_fraction;
well_state.wellRates(well_index)[p] = - fractions[p] * controls.oil_rate/control_fraction;
}
}
}
@ -1328,19 +1327,19 @@ namespace Opm
}
case Well::ProducerCMode::WRAT:
{
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ];
double current_rate = -well_state.wellRates(well_index)[ pu.phase_pos[Water] ];
// for trivial rates or opposite direction we don't just scale the rates
// but use either the potentials or the mobility ratio to initial the well rates
if (current_rate > 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] *= controls.water_rate/current_rate;
well_state.wellRates(well_index)[p] *= controls.water_rate/current_rate;
}
} else {
const std::vector<double> fractions = initialWellRateFractions(ebos_simulator, well_state.wellPotentials());
double control_fraction = fractions[pu.phase_pos[Water]];
if (control_fraction != 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = - fractions[p] * controls.water_rate/control_fraction;
well_state.wellRates(well_index)[p] = - fractions[p] * controls.water_rate/control_fraction;
}
}
}
@ -1348,19 +1347,19 @@ namespace Opm
}
case Well::ProducerCMode::GRAT:
{
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Gas] ];
double current_rate = -well_state.wellRates(well_index)[pu.phase_pos[Gas] ];
// or trivial rates or opposite direction we don't just scale the rates
// but use either the potentials or the mobility ratio to initial the well rates
if (current_rate > 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] *= controls.gas_rate/current_rate;
well_state.wellRates(well_index)[p] *= controls.gas_rate/current_rate;
}
} else {
const std::vector<double> fractions = initialWellRateFractions(ebos_simulator, well_state.wellPotentials());
double control_fraction = fractions[pu.phase_pos[Gas]];
if (control_fraction != 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = - fractions[p] * controls.gas_rate/control_fraction;
well_state.wellRates(well_index)[p] = - fractions[p] * controls.gas_rate/control_fraction;
}
}
}
@ -1370,20 +1369,20 @@ namespace Opm
}
case Well::ProducerCMode::LRAT:
{
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ]
- well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
double current_rate = -well_state.wellRates(well_index)[ pu.phase_pos[Water] ]
- well_state.wellRates(well_index)[ pu.phase_pos[Oil] ];
// or trivial rates or opposite direction we don't just scale the rates
// but use either the potentials or the mobility ratio to initial the well rates
if (current_rate > 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] *= controls.liquid_rate/current_rate;
well_state.wellRates(well_index)[p] *= controls.liquid_rate/current_rate;
}
} else {
const std::vector<double> fractions = initialWellRateFractions(ebos_simulator, well_state.wellPotentials());
double control_fraction = fractions[pu.phase_pos[Water]] + fractions[pu.phase_pos[Oil]];
if (control_fraction != 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = - fractions[p] * controls.liquid_rate / control_fraction;
well_state.wellRates(well_index)[p] = - fractions[p] * controls.liquid_rate / control_fraction;
}
}
}
@ -1399,19 +1398,19 @@ namespace Opm
rateConverter_.calcCoeff(/*fipreg*/ 0, pvtRegionIdx_, convert_coeff);
double total_res_rate = 0.0;
for (int p = 0; p<np; ++p) {
total_res_rate -= well_state.wellRates()[well_index*np + p] * convert_coeff[p];
total_res_rate -= well_state.wellRates(well_index)[p] * convert_coeff[p];
}
if (controls.prediction_mode) {
// or trivial rates or opposite direction we don't just scale the rates
// but use either the potentials or the mobility ratio to initial the well rates
if (total_res_rate > 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] *= controls.resv_rate/total_res_rate;
well_state.wellRates(well_index)[p] *= controls.resv_rate/total_res_rate;
}
} else {
const std::vector<double> fractions = initialWellRateFractions(ebos_simulator, well_state.wellPotentials());
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = - fractions[p] * controls.resv_rate / convert_coeff[p];
well_state.wellRates(well_index)[p] = - fractions[p] * controls.resv_rate / convert_coeff[p];
}
}
} else {
@ -1432,12 +1431,12 @@ namespace Opm
// but use either the potentials or the mobility ratio to initial the well rates
if (total_res_rate > 0.0) {
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] *= target/total_res_rate;
well_state.wellRates(well_index)[p] *= target/total_res_rate;
}
} else {
const std::vector<double> fractions = initialWellRateFractions(ebos_simulator, well_state.wellPotentials());
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = - fractions[p] * target / convert_coeff[p];
well_state.wellRates(well_index)[p] = - fractions[p] * target / convert_coeff[p];
}
}
@ -1449,14 +1448,14 @@ namespace Opm
well_state.update_bhp(well_index, controls.bhp_limit);
double total_rate = 0.0;
for (int p = 0; p<np; ++p) {
total_rate -= well_state.wellRates()[well_index*np + p];
total_rate -= well_state.wellRates(well_index)[p];
}
// if the total rates are negative or zero
// we try to provide a better intial well rate
// using the well potentials
if (total_rate <= 0.0){
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = -well_state.wellPotentials()[well_index*np + p];
well_state.wellRates(well_index)[p] = -well_state.wellPotentials()[well_index*np + p];
}
}
break;
@ -1465,7 +1464,7 @@ namespace Opm
{
std::vector<double> rates(3, 0.0);
for (int p = 0; p<np; ++p) {
rates[p] = well_state.wellRates()[well_index*np + p];
rates[p] = well_state.wellRates(well_index)[p];
}
double bhp = calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
well_state.update_bhp(well_index, bhp);
@ -1476,7 +1475,7 @@ namespace Opm
double total_rate = -std::accumulate(rates.begin(), rates.end(), 0.0);
if (total_rate <= 0.0){
for (int p = 0; p<np; ++p) {
well_state.wellRates()[well_index*np + p] = -well_state.wellPotentials()[well_index*np + p];
well_state.wellRates(well_index)[p] = -well_state.wellPotentials()[well_index*np + p];
}
}
break;
@ -1570,18 +1569,17 @@ namespace Opm
const auto& well = well_ecl_;
const PhaseUsage& pu = phaseUsage();
const int well_index = index_of_well_;
const auto wellrate_index = well_index * pu.num_phases;
if (well.isInjector()) {
const auto controls = well.injectionControls(summaryState);
Well::InjectorCMode& currentControl = well_state.currentInjectionControls()[well_index];
auto currentControl = well_state.currentInjectionControl(well_index);
if (controls.hasControl(Well::InjectorCMode::BHP) && currentControl != Well::InjectorCMode::BHP)
{
const auto& bhp = controls.bhp_limit;
double current_bhp = well_state.bhp(well_index);
if (bhp < current_bhp) {
currentControl = Well::InjectorCMode::BHP;
well_state.currentInjectionControl(well_index, Well::InjectorCMode::BHP);
return true;
}
}
@ -1594,17 +1592,17 @@ namespace Opm
switch (injectorType) {
case InjectorType::WATER:
{
current_rate = well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Aqua] ];
current_rate = well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Aqua] ];
break;
}
case InjectorType::OIL:
{
current_rate = well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Liquid] ];
current_rate = well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Liquid] ];
break;
}
case InjectorType::GAS:
{
current_rate = well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Vapour] ];
current_rate = well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Vapour] ];
break;
}
default:
@ -1612,7 +1610,7 @@ namespace Opm
}
if (controls.surface_rate < current_rate) {
currentControl = Well::InjectorCMode::RATE;
well_state.currentInjectionControl(well_index, Well::InjectorCMode::RATE);
return true;
}
@ -1622,13 +1620,13 @@ namespace Opm
{
double current_rate = 0.0;
if( pu.phase_used[BlackoilPhases::Aqua] )
current_rate += well_state.wellReservoirRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Aqua] ];
current_rate += well_state.wellReservoirRates(well_index)[ pu.phase_pos[BlackoilPhases::Aqua] ];
if( pu.phase_used[BlackoilPhases::Liquid] )
current_rate += well_state.wellReservoirRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Liquid] ];
current_rate += well_state.wellReservoirRates(well_index)[ pu.phase_pos[BlackoilPhases::Liquid] ];
if( pu.phase_used[BlackoilPhases::Vapour] )
current_rate += well_state.wellReservoirRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Vapour] ];
current_rate += well_state.wellReservoirRates(well_index)[ pu.phase_pos[BlackoilPhases::Vapour] ];
if (controls.reservoir_rate < current_rate) {
currentControl = Well::InjectorCMode::RESV;
@ -1650,47 +1648,47 @@ namespace Opm
if (well.isProducer( )) {
const auto controls = well.productionControls(summaryState);
Well::ProducerCMode& currentControl = well_state.currentProductionControls()[well_index];
auto currentControl = well_state.currentProductionControl(well_index);
if (controls.hasControl(Well::ProducerCMode::BHP) && currentControl != Well::ProducerCMode::BHP )
{
const double bhp = controls.bhp_limit;
double current_bhp = well_state.bhp(well_index);
if (bhp > current_bhp) {
currentControl = Well::ProducerCMode::BHP;
well_state.currentProductionControl(well_index, Well::ProducerCMode::BHP);
return true;
}
}
if (controls.hasControl(Well::ProducerCMode::ORAT) && currentControl != Well::ProducerCMode::ORAT) {
double current_rate = -well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Liquid] ];
double current_rate = -well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Liquid] ];
if (controls.oil_rate < current_rate ) {
currentControl = Well::ProducerCMode::ORAT;
well_state.currentProductionControl(well_index, Well::ProducerCMode::ORAT);
return true;
}
}
if (controls.hasControl(Well::ProducerCMode::WRAT) && currentControl != Well::ProducerCMode::WRAT ) {
double current_rate = -well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Aqua] ];
double current_rate = -well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Aqua] ];
if (controls.water_rate < current_rate ) {
currentControl = Well::ProducerCMode::WRAT;
well_state.currentProductionControl(well_index, Well::ProducerCMode::WRAT);
return true;
}
}
if (controls.hasControl(Well::ProducerCMode::GRAT) && currentControl != Well::ProducerCMode::GRAT ) {
double current_rate = -well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Vapour] ];
double current_rate = -well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Vapour] ];
if (controls.gas_rate < current_rate ) {
currentControl = Well::ProducerCMode::GRAT;
well_state.currentProductionControl(well_index, Well::ProducerCMode::GRAT);
return true;
}
}
if (controls.hasControl(Well::ProducerCMode::LRAT) && currentControl != Well::ProducerCMode::LRAT) {
double current_rate = -well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Liquid] ];
current_rate -= well_state.wellRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Aqua] ];
double current_rate = -well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Liquid] ];
current_rate -= well_state.wellRates(well_index)[ pu.phase_pos[BlackoilPhases::Aqua] ];
if (controls.liquid_rate < current_rate ) {
currentControl = Well::ProducerCMode::LRAT;
well_state.currentProductionControl(well_index, Well::ProducerCMode::LRAT);
return true;
}
}
@ -1698,16 +1696,16 @@ namespace Opm
if (controls.hasControl(Well::ProducerCMode::RESV) && currentControl != Well::ProducerCMode::RESV ) {
double current_rate = 0.0;
if( pu.phase_used[BlackoilPhases::Aqua] )
current_rate -= well_state.wellReservoirRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Aqua] ];
current_rate -= well_state.wellReservoirRates(well_index)[ pu.phase_pos[BlackoilPhases::Aqua] ];
if( pu.phase_used[BlackoilPhases::Liquid] )
current_rate -= well_state.wellReservoirRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Liquid] ];
current_rate -= well_state.wellReservoirRates(well_index)[ pu.phase_pos[BlackoilPhases::Liquid] ];
if( pu.phase_used[BlackoilPhases::Vapour] )
current_rate -= well_state.wellReservoirRates()[ wellrate_index + pu.phase_pos[BlackoilPhases::Vapour] ];
current_rate -= well_state.wellReservoirRates(well_index)[ pu.phase_pos[BlackoilPhases::Vapour] ];
if (controls.prediction_mode && controls.resv_rate < current_rate) {
currentControl = Well::ProducerCMode::RESV;
well_state.currentProductionControl(well_index, Well::ProducerCMode::RESV);
return true;
}
@ -1732,7 +1730,7 @@ namespace Opm
}
if (resv_rate < current_rate) {
currentControl = Well::ProducerCMode::RESV;
well_state.currentProductionControl(well_index, Well::ProducerCMode::RESV);
return true;
}
}
@ -1743,7 +1741,7 @@ namespace Opm
const auto& thp = this->getTHPConstraint(summaryState);
double current_thp = well_state.thp(well_index);
if (thp > current_thp) {
currentControl = Well::ProducerCMode::THP;
well_state.currentProductionControl(well_index, Well::ProducerCMode::THP);
return true;
}
}
@ -1769,7 +1767,7 @@ namespace Opm
const int well_index = index_of_well_;
if (well.isInjector()) {
Well::InjectorCMode& currentControl = well_state.currentInjectionControls()[well_index];
auto currentControl = well_state.currentInjectionControl(well_index);
if (currentControl != Well::InjectorCMode::GRUP) {
// This checks only the first encountered group limit,
@ -1785,10 +1783,10 @@ namespace Opm
// If a group constraint was broken, we set the current well control to
// be GRUP.
if (group_constraint.first) {
well_state.currentInjectionControls()[index_of_well_] = Well::InjectorCMode::GRUP;
well_state.currentInjectionControl(index_of_well_, Well::InjectorCMode::GRUP);
const int np = well_state.numPhases();
for (int p = 0; p<np; ++p) {
well_state.wellRates()[index_of_well_*np + p] *= group_constraint.second;
well_state.wellRates(index_of_well_)[p] *= group_constraint.second;
}
}
return group_constraint.first;
@ -1796,7 +1794,7 @@ namespace Opm
}
if (well.isProducer( )) {
Well::ProducerCMode& currentControl = well_state.currentProductionControls()[well_index];
auto currentControl = well_state.currentProductionControl(well_index);
if (currentControl != Well::ProducerCMode::GRUP) {
// This checks only the first encountered group limit,
@ -1812,10 +1810,10 @@ namespace Opm
// If a group constraint was broken, we set the current well control to
// be GRUP.
if (group_constraint.first) {
well_state.currentProductionControls()[index_of_well_] = Well::ProducerCMode::GRUP;
well_state.currentProductionControl(index_of_well_, Well::ProducerCMode::GRUP);
const int np = well_state.numPhases();
for (int p = 0; p<np; ++p) {
well_state.wellRates()[index_of_well_*np + p] *= group_constraint.second;
well_state.wellRates(index_of_well_)[p] *= group_constraint.second;
}
}
return group_constraint.first;
@ -1875,7 +1873,7 @@ namespace Opm
group_state,
current_step_,
guide_rate_,
well_state.wellRates().data() + index_of_well_ * phaseUsage().num_phases,
well_state.wellRates(index_of_well_).data(),
injectionPhase,
phaseUsage(),
efficiencyFactor,
@ -1910,7 +1908,7 @@ namespace Opm
group_state,
current_step_,
guide_rate_,
well_state.wellRates().data() + index_of_well_ * phaseUsage().num_phases,
well_state.wellRates(index_of_well_).data(),
phaseUsage(),
efficiencyFactor,
schedule,
@ -1937,7 +1935,7 @@ namespace Opm
EvalWell& control_eq,
DeferredLogger& deferred_logger)
{
const Well::InjectorCMode& current = well_state.currentInjectionControls()[index_of_well_];
auto current = well_state.currentInjectionControl(index_of_well_);
const InjectorType injectorType = controls.injector_type;
const auto& pu = phaseUsage();
const double efficiencyFactor = well_ecl_.getEfficiencyFactor();
@ -2020,7 +2018,7 @@ namespace Opm
EvalWell& control_eq,
DeferredLogger& deferred_logger)
{
const Well::ProducerCMode& current = well_state.currentProductionControls()[index_of_well_];
auto current = well_state.currentProductionControl(index_of_well_);
const auto& pu = phaseUsage();
const double efficiencyFactor = well_ecl_.getEfficiencyFactor();
@ -2348,7 +2346,7 @@ namespace Opm
// if more than one nonzero rate.
int nonzero_rate_index = -1;
for (int p = 0; p < number_of_phases_; ++p) {
if (well_state.wellRates()[index_of_well_ * number_of_phases_ + p] != 0.0) {
if (well_state.wellRates(index_of_well_)[p] != 0.0) {
if (nonzero_rate_index == -1) {
nonzero_rate_index = p;
} else {
@ -2366,12 +2364,12 @@ namespace Opm
std::vector<double> well_q_s = computeCurrentWellRates(ebosSimulator, deferred_logger);
// Set the currently-zero phase flows to be nonzero in proportion to well_q_s.
const double initial_nonzero_rate = well_state.wellRates()[index_of_well_ * number_of_phases_ + nonzero_rate_index];
const double initial_nonzero_rate = well_state.wellRates(index_of_well_)[nonzero_rate_index];
const int comp_idx_nz = flowPhaseToEbosCompIdx(nonzero_rate_index);
for (int p = 0; p < number_of_phases_; ++p) {
if (p != nonzero_rate_index) {
const int comp_idx = flowPhaseToEbosCompIdx(p);
double& rate = well_state.wellRates()[index_of_well_ * number_of_phases_ + p];
double& rate = well_state.wellRates(index_of_well_)[p];
rate = (initial_nonzero_rate/well_q_s[comp_idx_nz]) * (well_q_s[comp_idx]);
}
}

View File

@ -35,27 +35,26 @@ void WellState::init(const std::vector<double>& cellPressures,
const SummaryState& summary_state)
{
// clear old name mapping
wellMap_.clear();
well_perf_data_ = well_perf_data;
parallel_well_info_ = parallel_well_info;
this->wellMap_.clear();
this->perfpress_.clear();
this->perfrates_.clear();
this->status_.clear();
this->well_perf_data_.clear();
this->parallel_well_info_.clear();
this->wellrates_.clear();
{
// const int nw = wells->number_of_wells;
const int nw = wells_ecl.size();
const int np = this->phase_usage_.num_phases;
// const int np = wells->number_of_phases;
status_.assign(nw, Well::Status::OPEN);
bhp_.resize(nw, 0.0);
thp_.resize(nw, 0.0);
temperature_.resize(nw, 273.15 + 15.56); // standard condition temperature
wellrates_.resize(nw * np, 0.0);
int connpos = 0;
for (int w = 0; w < nw; ++w) {
const Well& well = wells_ecl[w];
// Initialize bhp(), thp(), wellRates(), temperature().
initSingleWell(cellPressures, w, well, *parallel_well_info[w], summary_state);
initSingleWell(cellPressures, w, well, well_perf_data[w], parallel_well_info[w], summary_state);
// Setup wellname -> well index mapping.
const int num_perf_this_well = well_perf_data[w].size();
@ -67,12 +66,6 @@ void WellState::init(const std::vector<double>& cellPressures,
wellMapEntry[ 2 ] = num_perf_this_well;
connpos += num_perf_this_well;
}
// The perforation rates and perforation pressures are
// not expected to be consistent with bhp_ and wellrates_
// after init().
perfrates_.resize(connpos, 0.0);
perfpress_.resize(connpos, -1e100);
}
}
@ -146,8 +139,7 @@ void WellState::shutWell(int well_index)
this->thp_[well_index] = 0;
this->bhp_[well_index] = 0;
const int np = numPhases();
for (int p = 0; p < np; ++p)
this->wellrates_[np * well_index + p] = 0;
this->wellrates_[well_index].assign(np, 0);
}
void WellState::stopWell(int well_index)
@ -196,18 +188,17 @@ data::Wells WellState::report(const int* globalCellIdxMap,
well.thp = this->thp( well_index );
well.temperature = this->temperature( well_index );
const auto wellrate_index = well_index * pu.num_phases;
const auto& wv = this->wellRates();
const auto& wv = this->wellRates(well_index);
if( pu.phase_used[BlackoilPhases::Aqua] ) {
well.rates.set( rt::wat, wv[ wellrate_index + pu.phase_pos[BlackoilPhases::Aqua] ] );
well.rates.set( rt::wat, wv[ pu.phase_pos[BlackoilPhases::Aqua] ] );
}
if( pu.phase_used[BlackoilPhases::Liquid] ) {
well.rates.set( rt::oil, wv[ wellrate_index + pu.phase_pos[BlackoilPhases::Liquid] ] );
well.rates.set( rt::oil, wv[ pu.phase_pos[BlackoilPhases::Liquid] ] );
}
if( pu.phase_used[BlackoilPhases::Vapour] ) {
well.rates.set( rt::gas, wv[ wellrate_index + pu.phase_pos[BlackoilPhases::Vapour] ] );
well.rates.set( rt::gas, wv[ pu.phase_pos[BlackoilPhases::Vapour] ] );
}
if (pwinfo.communication().size()==1)
@ -239,8 +230,8 @@ void WellState::reportConnections(data::Well& well,
const int num_perf_well = pd.size();
well.connections.resize(num_perf_well);
const auto * perf_rates = &this->perfRates()[itr.second[1]];
const auto * perf_pressure = &this->perfPress()[itr.second[1]];
const auto& perf_rates = this->perfRates(well_index);
const auto& perf_pressure = this->perfPress(well_index);
for( int i = 0; i < num_perf_well; ++i ) {
const auto active_index = this->well_perf_data_[well_index][i].cell_index;
auto& connection = well.connections[ i ];
@ -277,7 +268,8 @@ void WellState::gatherVectorsOnRoot(const std::vector<data::Connection>& from_co
void WellState::initSingleWell(const std::vector<double>& cellPressures,
const int w,
const Well& well,
const ParallelWellInfo& well_info,
const std::vector<PerforationData>& well_perf_data,
const ParallelWellInfo* well_info,
const SummaryState& summary_state)
{
assert(well.isInjector() || well.isProducer());
@ -286,15 +278,18 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
// May be overwritten below.
const auto& pu = this->phase_usage_;
const int np = pu.num_phases;
for (int p = 0; p < np; ++p) {
wellrates_[np*w + p] = 0.0;
}
if ( well.isInjector() ) {
temperature_[w] = well.injectionControls(summary_state).temperature;
}
this->status_.add(well.name(), Well::Status::OPEN);
this->well_perf_data_.add(well.name(), well_perf_data);
this->parallel_well_info_.add(well.name(), well_info);
this->wellrates_.add(well.name(), std::vector<double>(np, 0));
const int num_perf_this_well = well_info.communication().sum(well_perf_data_[w].size());
const int num_perf_this_well = well_info->communication().sum(well_perf_data_[w].size());
this->perfpress_.add(well.name(), std::vector<double>(num_perf_this_well, -1e100));
this->perfrates_.add(well.name(), std::vector<double>(num_perf_this_well, 0));
if ( num_perf_this_well == 0 ) {
// No perforations of the well. Initialize to zero.
bhp_[w] = 0.;
@ -315,7 +310,7 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
const double local_pressure = well_perf_data_[w].empty() ?
0 : cellPressures[well_perf_data_[w][0].cell_index];
const double global_pressure = well_info.broadcastFirstPerforationValue(local_pressure);
const double global_pressure = well_info->broadcastFirstPerforationValue(local_pressure);
if (well.getStatus() == Well::Status::OPEN) {
this->openWell(w);
@ -348,20 +343,21 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
// (producer) or RATE (injector).
// Otherwise, we cannot set the correct
// value here and initialize to zero rate.
auto & well_rates = this->wellrates_[w];
if (well.isInjector()) {
if (inj_controls.cmode == Well::InjectorCMode::RATE) {
switch (inj_controls.injector_type) {
case InjectorType::WATER:
assert(pu.phase_used[BlackoilPhases::Aqua]);
wellrates_[np*w + pu.phase_pos[BlackoilPhases::Aqua]] = inj_surf_rate;
well_rates[pu.phase_pos[BlackoilPhases::Aqua]] = inj_surf_rate;
break;
case InjectorType::GAS:
assert(pu.phase_used[BlackoilPhases::Vapour]);
wellrates_[np*w + pu.phase_pos[BlackoilPhases::Vapour]] = inj_surf_rate;
well_rates[pu.phase_pos[BlackoilPhases::Vapour]] = inj_surf_rate;
break;
case InjectorType::OIL:
assert(pu.phase_used[BlackoilPhases::Liquid]);
wellrates_[np*w + pu.phase_pos[BlackoilPhases::Liquid]] = inj_surf_rate;
well_rates[pu.phase_pos[BlackoilPhases::Liquid]] = inj_surf_rate;
break;
case InjectorType::MULTI:
// Not currently handled, keep zero init.
@ -376,15 +372,15 @@ void WellState::initSingleWell(const std::vector<double>& cellPressures,
switch (prod_controls.cmode) {
case Well::ProducerCMode::ORAT:
assert(pu.phase_used[BlackoilPhases::Liquid]);
wellrates_[np*w + pu.phase_pos[BlackoilPhases::Liquid]] = -prod_controls.oil_rate;
well_rates[pu.phase_pos[BlackoilPhases::Liquid]] = -prod_controls.oil_rate;
break;
case Well::ProducerCMode::WRAT:
assert(pu.phase_used[BlackoilPhases::Aqua]);
wellrates_[np*w + pu.phase_pos[BlackoilPhases::Aqua]] = -prod_controls.water_rate;
well_rates[pu.phase_pos[BlackoilPhases::Aqua]] = -prod_controls.water_rate;
break;
case Well::ProducerCMode::GRAT:
assert(pu.phase_used[BlackoilPhases::Vapour]);
wellrates_[np*w + pu.phase_pos[BlackoilPhases::Vapour]] = -prod_controls.gas_rate;
well_rates[pu.phase_pos[BlackoilPhases::Vapour]] = -prod_controls.gas_rate;
break;
default:
// Keep zero init.

View File

@ -24,6 +24,7 @@
#include <opm/output/data/Wells.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp>
#include <opm/simulators/wells/PerforationData.hpp>
#include <opm/simulators/wells/WellContainer.hpp>
#include <array>
#include <cstddef>
@ -92,16 +93,21 @@ public:
double temperature(std::size_t well_index) const { return temperature_[well_index]; }
/// One rate per well and phase.
std::vector<double>& wellRates() { return wellrates_; }
const std::vector<double>& wellRates() const { return wellrates_; }
const WellContainer<std::vector<double>>& wellRates() const { return wellrates_; }
std::vector<double>& wellRates(std::size_t well_index) { return wellrates_[well_index]; }
const std::vector<double>& wellRates(std::size_t well_index) const { return wellrates_[well_index]; }
/// One rate per well connection.
std::vector<double>& perfRates() { return perfrates_; }
const std::vector<double>& perfRates() const { return perfrates_; }
std::vector<double>& perfRates(std::size_t well_index) { return this->perfrates_[well_index]; }
const std::vector<double>& perfRates(std::size_t well_index) const { return this->perfrates_[well_index]; }
std::vector<double>& perfRates(const std::string& wname) { return this->perfrates_[wname]; }
const std::vector<double>& perfRates(const std::string& wname) const { return this->perfrates_[wname]; }
/// One pressure per well connection.
std::vector<double>& perfPress() { return perfpress_; }
const std::vector<double>& perfPress() const { return perfpress_; }
std::vector<double>& perfPress(std::size_t well_index) { return perfpress_[well_index]; }
const std::vector<double>& perfPress(std::size_t well_index) const { return perfpress_[well_index]; }
std::vector<double>& perfPress(const std::string& wname) { return perfpress_[wname]; }
const std::vector<double>& perfPress(const std::string& wname) const { return perfpress_[wname]; }
const WellMapType& wellMap() const { return wellMap_; }
WellMapType& wellMap() { return wellMap_; }
@ -148,18 +154,18 @@ public:
const int* globalCellIdxMap) const;
protected:
std::vector<Well::Status> status_;
std::vector<std::vector<PerforationData>> well_perf_data_;
std::vector<ParallelWellInfo*> parallel_well_info_;
WellContainer<Well::Status> status_;
WellContainer<std::vector<PerforationData>> well_perf_data_;
WellContainer<const ParallelWellInfo*> parallel_well_info_;
private:
PhaseUsage phase_usage_;
std::vector<double> bhp_;
std::vector<double> thp_;
std::vector<double> temperature_;
std::vector<double> wellrates_;
std::vector<double> perfrates_;
std::vector<double> perfpress_;
WellContainer<std::vector<double>> wellrates_;
WellContainer<std::vector<double>> perfrates_;
WellContainer<std::vector<double>> perfpress_;
WellMapType wellMap_;
@ -171,7 +177,8 @@ private:
void initSingleWell(const std::vector<double>& cellPressures,
const int w,
const Well& well,
const ParallelWellInfo& well_info,
const std::vector<PerforationData>& well_perf_data,
const ParallelWellInfo* well_info,
const SummaryState& summary_state);
};

View File

@ -62,7 +62,7 @@ void WellStateFullyImplicitBlackoil::init(const std::vector<double>& cellPressur
nperf += wpd.size();
}
well_reservoir_rates_.resize(nw * this->numPhases(), 0.0);
well_reservoir_rates_.clear();
well_dissolved_gas_rates_.resize(nw, 0.0);
well_vaporized_oil_rates_.resize(nw, 0.0);
@ -100,36 +100,42 @@ void WellStateFullyImplicitBlackoil::init(const std::vector<double>& cellPressur
const int connpos = well_info[1];
const int num_perf_this_well = well_info[2];
const int global_num_perf_this_well = parallel_well_info[w]->communication().sum(num_perf_this_well);
auto * perf_press = &this->perfPress()[connpos];
auto& perf_press = this->perfPress(w);
auto * phase_rates = &this->mutable_perfPhaseRates()[connpos * this->numPhases()];
for (int perf = 0; perf < num_perf_this_well; ++perf) {
if (wells_ecl[w].getStatus() == Well::Status::OPEN) {
for (int p = 0; p < this->numPhases(); ++p) {
phase_rates[this->numPhases()*perf + p] = wellRates()[this->numPhases()*w + p] / double(global_num_perf_this_well);
phase_rates[this->numPhases()*perf + p] = wellRates(w)[p] / double(global_num_perf_this_well);
}
}
perf_press[perf] = cellPressures[well_perf_data[w][perf].cell_index];
}
num_perf_[w] = num_perf_this_well;
first_perf_index_[w] = connpos;
this->well_reservoir_rates_.add(wname, std::vector<double>(np, 0));
}
is_producer_.resize(nw, false);
is_producer_.clear();
for (int w = 0; w < nw; ++w) {
is_producer_[w] = wells_ecl[w].isProducer();
const auto& ecl_well = wells_ecl[w];
this->is_producer_.add( ecl_well.name(), ecl_well.isProducer());
}
current_injection_controls_.resize(nw, Well::InjectorCMode::CMODE_UNDEFINED);
current_production_controls_.resize(nw, Well::ProducerCMode::CMODE_UNDEFINED);
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);
if (wells_ecl[w].isProducer()) {
const auto controls = wells_ecl[w].productionControls(summary_state);
currentProductionControls()[w] = controls.cmode;
currentProductionControl(w, controls.cmode);
}
else {
const auto controls = wells_ecl[w].injectionControls(summary_state);
currentInjectionControls()[w] = controls.cmode;
currentInjectionControl(w, controls.cmode);
}
}
@ -194,21 +200,12 @@ void WellStateFullyImplicitBlackoil::init(const std::vector<double>& cellPressur
// If new target is set using WCONPROD, WCONINJE etc. we use the new control
if (!this->events_[w].hasEvent(WellStateFullyImplicitBlackoil::event_mask)) {
current_injection_controls_[ newIndex ] = prevState->currentInjectionControls()[ oldIndex ];
current_production_controls_[ newIndex ] = prevState->currentProductionControls()[ oldIndex ];
current_injection_controls_[ newIndex ] = prevState->currentInjectionControl(oldIndex);
current_production_controls_[ newIndex ] = prevState->currentProductionControl(oldIndex);
}
// wellrates
for( int i=0, idx=newIndex*np, oldidx=oldIndex*np; i<np; ++i, ++idx, ++oldidx )
{
wellRates()[ idx ] = prevState->wellRates()[ oldidx ];
}
// wellResrates
for( int i=0, idx=newIndex*np, oldidx=oldIndex*np; i<np; ++i, ++idx, ++oldidx )
{
wellReservoirRates()[ idx ] = prevState->wellReservoirRates()[ oldidx ];
}
wellRates(w) = prevState->wellRates(oldIndex);
wellReservoirRates(w) = prevState->wellReservoirRates(oldIndex);
// Well potentials
for( int i=0, idx=newIndex*np, oldidx=oldIndex*np; i<np; ++i, ++idx, ++oldidx )
@ -253,7 +250,7 @@ void WellStateFullyImplicitBlackoil::init(const std::vector<double>& cellPressur
auto * target_rates = &this->mutable_perfPhaseRates()[connpos*np];
for (int perf_index = 0; perf_index < num_perf_this_well; perf_index++) {
for (int p = 0; p < np; ++p) {
target_rates[perf_index*np + p] = wellRates()[np*newIndex + p] / double(global_num_perf_this_well);
target_rates[perf_index*np + p] = wellRates(w)[p] / double(global_num_perf_this_well);
}
}
}
@ -261,8 +258,8 @@ void WellStateFullyImplicitBlackoil::init(const std::vector<double>& cellPressur
// perfPressures
if (global_num_perf_same)
{
auto * target_press = &perfPress()[connpos];
const auto * src_press = &prevState->perfPress()[oldPerf_idx_beg];
auto& target_press = perfPress(w);
const auto& src_press = prevState->perfPress(well.name());
for (int perf = 0; perf < num_perf_this_well; ++perf)
{
target_press[perf] = src_press[perf];
@ -335,8 +332,8 @@ void WellStateFullyImplicitBlackoil::init(const std::vector<double>& cellPressur
seg_number_[w] = 1; // Top segment is segment #1
this->seg_press_[w] = this->bhp(w);
}
seg_rates_ = wellRates();
//seg_rates_ = wellRates();
seg_rates_.assign(nw*np, 0);
seg_pressdrop_.assign(nw, 0.);
seg_pressdrop_hydorstatic_.assign(nw, 0.);
seg_pressdrop_friction_.assign(nw, 0.);
@ -420,24 +417,25 @@ WellStateFullyImplicitBlackoil::report(const int* globalCellIdxMap,
auto& well = res.at(wt.first);
const int well_rate_index = w * pu.num_phases;
const auto& reservoir_rates = this->well_reservoir_rates_[w];
if (pu.phase_used[Water]) {
const auto i = well_rate_index + pu.phase_pos[Water];
well.rates.set(rt::reservoir_water, this->well_reservoir_rates_[i]);
well.rates.set(rt::reservoir_water, reservoir_rates[pu.phase_pos[Water]]);
well.rates.set(rt::productivity_index_water, this->productivity_index_[i]);
well.rates.set(rt::well_potential_water, this->well_potentials_[i]);
}
if (pu.phase_used[Oil]) {
const auto i = well_rate_index + pu.phase_pos[Oil];
well.rates.set(rt::reservoir_oil, this->well_reservoir_rates_[i]);
well.rates.set(rt::reservoir_oil, reservoir_rates[pu.phase_pos[Oil]]);
well.rates.set(rt::productivity_index_oil, this->productivity_index_[i]);
well.rates.set(rt::well_potential_oil, this->well_potentials_[i]);
}
if (pu.phase_used[Gas]) {
const auto i = well_rate_index + pu.phase_pos[Gas];
well.rates.set(rt::reservoir_gas, this->well_reservoir_rates_[i]);
well.rates.set(rt::reservoir_gas, reservoir_rates[pu.phase_pos[Gas]]);
well.rates.set(rt::productivity_index_gas, this->productivity_index_[i]);
well.rates.set(rt::well_potential_gas, this->well_potentials_[i]);
}
@ -468,8 +466,8 @@ WellStateFullyImplicitBlackoil::report(const int* globalCellIdxMap,
auto& curr = well.current_control;
curr.isProducer = this->is_producer_[w];
curr.prod = this->currentProductionControls()[w];
curr.inj = this->currentInjectionControls() [w];
curr.prod = this->currentProductionControl(w);
curr.inj = this->currentInjectionControl(w);
}
const auto nseg = this->numSegments(w);
@ -559,13 +557,14 @@ void WellStateFullyImplicitBlackoil::initWellStateMSWell(const std::vector<Well>
const int connpos = well_info[1];
const int num_perf_this_well = well_info[2];
const auto& rates = this->wellRates(w);
top_segment_index_.push_back(nseg_);
if ( !well_ecl.isMultiSegment() ) { // not multi-segment well
nseg_ += 1;
seg_number_.push_back(1); // Assign single segment (top) as number 1.
seg_press_.push_back(bhp(w));
for (int p = 0; p < np; ++p) {
seg_rates_.push_back(wellRates()[np * w + p]);
seg_rates_.push_back(rates[p]);
}
} else { // it is a multi-segment well
const WellSegments& segment_set = well_ecl.getSegments();
@ -641,8 +640,7 @@ void WellStateFullyImplicitBlackoil::initWellStateMSWell(const std::vector<Well>
// top segment is always the first one, and its pressure is the well bhp
seg_press_.push_back(bhp(w));
const int top_segment = top_segment_index_[w];
const int start_perf = connpos;
const auto * perf_press = &this->perfPress()[start_perf];
const auto& perf_press = this->perfPress(w);
for (int seg = 1; seg < well_nseg; ++seg) {
if ( !segment_perforations[seg].empty() ) {
const int first_perf = segment_perforations[seg][0];
@ -769,7 +767,7 @@ void WellStateFullyImplicitBlackoil::shutWell(int well_index)
WellState::shutWell(well_index);
const int np = numPhases();
auto* resv = &this->well_reservoir_rates_[np*well_index + 0];
auto& resv = this->well_reservoir_rates_[well_index];
auto* wpi = &this->productivity_index_[np*well_index + 0];
for (int p = 0; p < np; ++p) {
@ -849,7 +847,7 @@ void WellStateFullyImplicitBlackoil::communicateGroupRates(const Comm& comm)
template<class Comm>
void WellStateFullyImplicitBlackoil::updateGlobalIsGrup(const Comm& comm)
{
this->global_well_info.value().update_group(this->status_, this->currentInjectionControls(), this->currentProductionControls());
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().communicate(comm);
}

View File

@ -99,12 +99,12 @@ public:
const std::vector<double>& perfPhaseRates() const { return perfphaserates_; }
/// One current control per injecting well.
std::vector<Opm::Well::InjectorCMode>& currentInjectionControls() { return current_injection_controls_; }
const std::vector<Opm::Well::InjectorCMode>& currentInjectionControls() const { return current_injection_controls_; }
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.
std::vector<Well::ProducerCMode>& currentProductionControls() { return current_production_controls_; }
const std::vector<Well::ProducerCMode>& currentProductionControls() const { return current_production_controls_; }
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>& rates ) {
well_rates[wellName].second = rates;
@ -161,14 +161,16 @@ public:
/// One rate pr well
double brineWellRate(const int w) const;
std::vector<double>& wellReservoirRates()
const WellContainer<std::vector<double>>& wellReservoirRates() const { return well_reservoir_rates_; }
std::vector<double>& wellReservoirRates(std::size_t well_index)
{
return well_reservoir_rates_;
return well_reservoir_rates_[well_index];
}
const std::vector<double>& wellReservoirRates() const
const std::vector<double>& wellReservoirRates(std::size_t well_index) const
{
return well_reservoir_rates_;
return well_reservoir_rates_[well_index];
}
std::vector<double>& wellDissolvedGasRates()
@ -365,15 +367,15 @@ public:
private:
std::vector<double> perfphaserates_;
std::vector<bool> is_producer_; // Size equal to number of local wells.
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)
std::vector<int> first_perf_index_;
std::vector<int> num_perf_;
std::vector<Opm::Well::InjectorCMode> current_injection_controls_;
std::vector<Well::ProducerCMode> current_production_controls_;
WellContainer<Opm::Well::InjectorCMode> current_injection_controls_;
WellContainer<Well::ProducerCMode> current_production_controls_;
// Use of std::optional<> here is a technical crutch, the
// WellStateFullyImplicitBlackoil class should be default constructible,
@ -405,7 +407,7 @@ private:
// phase rates under reservoir condition for wells
// or voidage phase rates
std::vector<double> well_reservoir_rates_;
WellContainer<std::vector<double>> well_reservoir_rates_;
// dissolved gas rates or solution gas production rates
// should be zero for injection wells

View File

@ -393,37 +393,61 @@ BOOST_AUTO_TEST_CASE(STOP_well)
std::vector<Opm::ParallelWellInfo> pinfos;
auto wstate = buildWellState(setup, 0, pinfos);
for (const auto& p : wstate.perfPress())
BOOST_CHECK(p > 0);
for (std::size_t well_index = 0; well_index < setup.sched.numWells(0); well_index++) {
for (const auto& p : wstate.perfPress(well_index))
BOOST_CHECK(p > 0);
}
}
// ---------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(GlobalWellInfo_TEST) {
const Setup setup{ "msw.data" };
std::vector<Opm::Well> local_wells = { setup.sched.getWell("PROD01", 1) };
Opm::GlobalWellInfo gwi(setup.sched, 1, local_wells);
BOOST_CHECK(!gwi.in_injecting_group("INJE01"));
BOOST_CHECK(!gwi.in_injecting_group("PROD01"));
BOOST_CHECK(!gwi.in_producing_group("INJE01"));
BOOST_CHECK(!gwi.in_producing_group("PROD01"));
BOOST_CHECK_EQUAL( gwi.well_name(0), "INJE01");
BOOST_CHECK_EQUAL( gwi.well_name(1), "PROD01");
BOOST_CHECK_EQUAL( gwi.well_index("PROD01"), 1);
BOOST_CHECK_THROW( gwi.update_group( {}, {}, {} ), std::exception);
gwi.update_group( {Opm::Well::Status::OPEN}, {Opm::Well::InjectorCMode::CMODE_UNDEFINED}, {Opm::Well::ProducerCMode::GRUP} );
BOOST_CHECK(!gwi.in_producing_group("INJE01"));
BOOST_CHECK(gwi.in_producing_group("PROD01"));
gwi.update_group( {Opm::Well::Status::OPEN}, {Opm::Well::InjectorCMode::CMODE_UNDEFINED}, {Opm::Well::ProducerCMode::NONE} );
BOOST_CHECK(!gwi.in_producing_group("INJE01"));
BOOST_CHECK(!gwi.in_producing_group("PROD01"));
}
//BOOST_AUTO_TEST_CASE(GlobalWellInfo_TEST) {
// const Setup setup{ "msw.data" };
// std::vector<Opm::Well> local_wells = { setup.sched.getWell("PROD01", 1) };
// Opm::GlobalWellInfo gwi(setup.sched, 1, local_wells);
// Opm::WellContainer<Opm::Well::Status> status({{"PROD01", Opm::Well::Status::OPEN}});
//
// BOOST_CHECK(!gwi.in_injecting_group("INJE01"));
// BOOST_CHECK(!gwi.in_injecting_group("PROD01"));
// BOOST_CHECK(!gwi.in_producing_group("INJE01"));
// BOOST_CHECK(!gwi.in_producing_group("PROD01"));
//
// BOOST_CHECK_EQUAL( gwi.well_name(0), "INJE01");
// BOOST_CHECK_EQUAL( gwi.well_name(1), "PROD01");
// BOOST_CHECK_EQUAL( gwi.well_index("PROD01"), 1);
//
// BOOST_CHECK_THROW( gwi.update_group( {}, {}, {} ), std::exception);
//
//
// Opm::WellContainer<Opm::Well::InjectorCMode> inj_cmode({{"PROD01", Opm::Well::InjectorCMode::CMODE_UNDEFINED}});
// {
// Opm::WellContainer<Opm::Well::ProducerCMode> prod_cmode({{"PROD01", Opm::Well::ProducerCMode::GRUP}});
// gwi.update_group(status, inj_cmode, prod_cmode);
// }
// BOOST_CHECK(!gwi.in_producing_group("INJE01"));
// BOOST_CHECK(gwi.in_producing_group("PROD01"));
//
// {
// Opm::WellContainer<Opm::Well::ProducerCMode> prod_cmode(
// {{"PROD01", Opm::Well::ProducerCMode::CMODE_UNDEFINED}});
// gwi.update_group(status, inj_cmode, prod_cmode);
// }
//
// {
// Opm::WellContainer<Opm::Well::ProducerCMode> prod_cmode({{"PROD01", Opm::Well::ProducerCMode::GRUP}});
// gwi.update_group(status, inj_cmode, prod_cmode);
// }
// BOOST_CHECK(!gwi.in_producing_group("INJE01"));
// BOOST_CHECK(gwi.in_producing_group("PROD01"));
//
// {
// Opm::WellContainer<Opm::Well::ProducerCMode> prod_cmode({{"PROD01", Opm::Well::ProducerCMode::NONE}});
// gwi.update_group(status, inj_cmode, prod_cmode);
// }
// BOOST_CHECK(!gwi.in_producing_group("INJE01"));
// BOOST_CHECK(!gwi.in_producing_group("PROD01"));
//}
BOOST_AUTO_TEST_CASE(TESTWellContainer) {
Opm::WellContainer<int> wc;