diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index 7023d41f9..5b5abccb7 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -1576,7 +1576,7 @@ calculateEfficiencyFactors(const int reportStepIdx) for (auto& well : well_container_generic_) { const Well& wellEcl = well->wellEcl(); Scalar well_efficiency_factor = wellEcl.getEfficiencyFactor() * - wellState()[well->name()].efficiency_scaling_factor; + wellState().getGlobalEfficiencyScalingFactor(well->name()); WellGroupHelpers::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(), reportStepIdx), schedule(), diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index 58c9b281b..cbbaceba8 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -657,7 +657,7 @@ namespace Opm { well->init(&this->phase_usage_, depth_, gravity_, B_avg_, true); Scalar well_efficiency_factor = wellEcl.getEfficiencyFactor() * - this->wellState()[well_name].efficiency_scaling_factor; + this->wellState().getGlobalEfficiencyScalingFactor(well_name); WellGroupHelpers::accumulateGroupEfficiencyFactor(this->schedule().getGroup(wellEcl.groupName(), timeStepIdx), this->schedule(), @@ -1063,7 +1063,7 @@ namespace Opm { this->well_open_times_, schedule_open)) { - this->wellState()[wname].efficiency_scaling_factor = wscale; + this->wellState().updateEfficiencyScalingFactor(wname, wscale); this->schedule_.add_event(ScheduleEvents::WELLGROUP_EFFICIENCY_UPDATE, report_step); } } diff --git a/opm/simulators/wells/GasLiftGroupInfo.cpp b/opm/simulators/wells/GasLiftGroupInfo.cpp index 93ba9d831..2f73c6b50 100644 --- a/opm/simulators/wells/GasLiftGroupInfo.cpp +++ b/opm/simulators/wells/GasLiftGroupInfo.cpp @@ -585,7 +585,7 @@ initializeGroupRatesRecursive_(const Group& group) auto [sw_oil_rate, sw_gas_rate, sw_water_rate, sw_oil_pot, sw_gas_pot, sw_water_pot] = getProducerWellRates_(well, index); auto sw_alq = this->well_state_.getALQ(well_name); const Scalar factor = well->getEfficiencyFactor() * - this->well_state_[well_name].efficiency_scaling_factor; + this->well_state_.getGlobalEfficiencyScalingFactor(well_name); oil_rate += (factor * sw_oil_rate); gas_rate += (factor * sw_gas_rate); water_rate += (factor * sw_water_rate); @@ -707,7 +707,7 @@ initializeWell2GroupMapRecursive_(const Group& group, const auto &well = this->schedule_.getWell( well_name, this->report_step_idx_); const Scalar wfac = well.getEfficiencyFactor() * - this->well_state_[well_name].efficiency_scaling_factor; + this->well_state_.getGlobalEfficiencyScalingFactor(well_name); auto [itr, success] = this->well_group_map_.insert( {well_name, /*empty vector*/ {}}); assert(success); diff --git a/opm/simulators/wells/GlobalWellInfo.cpp b/opm/simulators/wells/GlobalWellInfo.cpp index 0bdaaf6eb..294a4d117 100644 --- a/opm/simulators/wells/GlobalWellInfo.cpp +++ b/opm/simulators/wells/GlobalWellInfo.cpp @@ -29,14 +29,17 @@ namespace Opm { - - -GlobalWellInfo::GlobalWellInfo(const Schedule& sched, std::size_t report_step, const std::vector& local_wells) +template +GlobalWellInfo:: +GlobalWellInfo(const Schedule& sched, + std::size_t report_step, + const std::vector& local_wells) { auto num_wells = sched.numWells(report_step); this->m_in_injecting_group.resize(num_wells); this->m_in_producing_group.resize(num_wells); this->m_is_open.resize(num_wells); + this->m_efficiency_scaling_factors.resize(num_wells); for (const auto& wname : sched.wellNames(report_step)) { const auto& well = sched.getWell(wname, report_step); auto global_well_index = well.seqIndex(); @@ -47,24 +50,36 @@ GlobalWellInfo::GlobalWellInfo(const Schedule& sched, std::size_t report_step, c this->local_map.push_back( well.seqIndex() ); } - -bool GlobalWellInfo::in_injecting_group(const std::string& wname) const { +template +bool GlobalWellInfo:: +in_injecting_group(const std::string& wname) const +{ auto global_well_index = this->name_map.at(wname); return this->m_in_injecting_group[global_well_index]; } - -bool GlobalWellInfo::in_producing_group(const std::string& wname) const { +template +bool GlobalWellInfo:: +in_producing_group(const std::string& wname) const +{ auto global_well_index = this->name_map.at(wname); return this->m_in_producing_group[global_well_index]; } -bool GlobalWellInfo::is_open(const std::string& wname) const { +template +bool GlobalWellInfo:: +is_open(const std::string& wname) const +{ auto global_well_index = this->name_map.at(wname); return this->m_is_open[global_well_index]; } -void GlobalWellInfo::update_injector(std::size_t well_index, Well::Status well_status, Well::InjectorCMode injection_cmode) { +template +void GlobalWellInfo:: +update_injector(std::size_t well_index, + Well::Status well_status, + Well::InjectorCMode injection_cmode) +{ if (well_status == Well::Status::OPEN) { this->m_is_open[this->local_map[well_index]] = 1; if (injection_cmode == Well::InjectorCMode::GRUP) { @@ -73,7 +88,12 @@ void GlobalWellInfo::update_injector(std::size_t well_index, Well::Status well_s } } -void GlobalWellInfo::update_producer(std::size_t well_index, Well::Status well_status, Well::ProducerCMode production_cmode) { +template +void GlobalWellInfo:: +update_producer(std::size_t well_index, + Well::Status well_status, + Well::ProducerCMode production_cmode) +{ if (well_status == Well::Status::OPEN) { this->m_is_open[this->local_map[well_index]] = 1; if (production_cmode == Well::ProducerCMode::GRUP) { @@ -82,22 +102,53 @@ void GlobalWellInfo::update_producer(std::size_t well_index, Well::Status well_s } } -void GlobalWellInfo::clear() { +template +void GlobalWellInfo:: +update_efficiency_scaling_factor(std::size_t well_index, + const Scalar efficiency_scaling_factor) +{ + this->m_efficiency_scaling_factors[this->local_map[well_index]] = efficiency_scaling_factor; +} + +template +void GlobalWellInfo::clear() +{ this->m_in_injecting_group.assign(this->name_map.size(), 0); this->m_in_producing_group.assign(this->name_map.size(), 0); this->m_is_open.assign(this->name_map.size(), 0); + this->m_efficiency_scaling_factors.assign(this->name_map.size(), 1.0); } +template +Scalar GlobalWellInfo:: +efficiency_scaling_factor(const std::string& wname) const +{ + auto global_well_index = this->name_map.at(wname); + return this->m_efficiency_scaling_factors[global_well_index]; +} -std::size_t GlobalWellInfo::well_index(const std::string& wname) const { +template +std::size_t GlobalWellInfo:: +well_index(const std::string& wname) const +{ return this->name_map.at(wname); } -const std::string& GlobalWellInfo::well_name(std::size_t well_index) const { +template +const std::string& GlobalWellInfo:: +well_name(std::size_t well_index) const +{ for (const auto& [name, index] : this->name_map) { if (index == well_index) return name; } throw std::logic_error("No well with index: " + std::to_string(well_index)); } + +template class GlobalWellInfo; + +#if FLOW_INSTANTIATE_FLOAT +template class GlobalWellInfo; +#endif + } diff --git a/opm/simulators/wells/GlobalWellInfo.hpp b/opm/simulators/wells/GlobalWellInfo.hpp index a57408015..03c9152cb 100644 --- a/opm/simulators/wells/GlobalWellInfo.hpp +++ b/opm/simulators/wells/GlobalWellInfo.hpp @@ -49,7 +49,7 @@ enum class WellStatus; under group control. */ - +template class GlobalWellInfo { public: @@ -64,6 +64,7 @@ public: comm.sum( this->m_in_injecting_group.data(), size); comm.sum( this->m_in_producing_group.data(), size); comm.sum( this->m_is_open.data(), size); + comm.min( this->m_efficiency_scaling_factors.data(), size); } @@ -76,6 +77,8 @@ public: const std::string& well_name(std::size_t well_index) const; void update_injector(std::size_t well_index, WellStatus well_status, WellInjectorCMode injection_cmode); void update_producer(std::size_t well_index, WellStatus well_status, WellProducerCMode production_cmode); + void update_efficiency_scaling_factor(std::size_t well_index, const Scalar efficiency_scaling_factor); + Scalar efficiency_scaling_factor(const std::string& wname) const; void clear(); private: @@ -85,6 +88,7 @@ private: std::vector m_in_injecting_group; // global_index -> int/bool std::vector m_in_producing_group; // global_index -> int/bool std::vector m_is_open; // global_index -> int/bool + std::vector m_efficiency_scaling_factors; // global_index --> double }; diff --git a/opm/simulators/wells/WellGroupHelpers.cpp b/opm/simulators/wells/WellGroupHelpers.cpp index eb91f96df..f8206f282 100644 --- a/opm/simulators/wells/WellGroupHelpers.cpp +++ b/opm/simulators/wells/WellGroupHelpers.cpp @@ -873,7 +873,7 @@ computeNetworkPressures(const Network::ExtNetwork& network, // available and using those (for wells with WEFAC(3) true only) when accumulating group // rates, but ONLY for network calculations. const Scalar efficiency = well.getEfficiencyFactor() * - well_state[well.name()].efficiency_scaling_factor; + well_state.getGlobalEfficiencyScalingFactor(wellname); node_inflows[node][BlackoilPhases::Vapour] += well_state.getALQ(wellname) * efficiency; } } diff --git a/opm/simulators/wells/WellState.cpp b/opm/simulators/wells/WellState.cpp index 9d8429cca..561546cc7 100644 --- a/opm/simulators/wells/WellState.cpp +++ b/opm/simulators/wells/WellState.cpp @@ -271,7 +271,7 @@ void WellState::init(const std::vector& cellPressures, this->base_init(cellPressures, cellTemperatures, wells_ecl, parallel_well_info, well_perf_data, summary_state); this->enableDistributedWells_ = enableDistributedWells; - this->global_well_info = std::make_optional(schedule, + this->global_well_info = std::make_optional>(schedule, report_step, wells_ecl); well_rates.clear(); @@ -969,6 +969,7 @@ void WellState::updateGlobalIsGrup(const Parallel::Communication& comm) this->global_well_info.value().clear(); for (std::size_t well_index = 0; well_index < this->size(); well_index++) { const auto& ws = this->well(well_index); + this->global_well_info.value().update_efficiency_scaling_factor(well_index, ws.efficiency_scaling_factor); if (ws.producer) this->global_well_info.value().update_producer(well_index, ws.status, ws.production_cmode); else @@ -977,6 +978,16 @@ void WellState::updateGlobalIsGrup(const Parallel::Communication& comm) this->global_well_info.value().communicate(comm); } +template +void WellState:: +updateEfficiencyScalingFactor(const std::string& wellName, + const Scalar value) +{ + const auto idx = this->index(wellName); + this->global_well_info.value().update_efficiency_scaling_factor(*idx, value); + this->well(*idx).efficiency_scaling_factor = value; +} + template data::Segment WellState::reportSegmentResults(const int well_id, diff --git a/opm/simulators/wells/WellState.hpp b/opm/simulators/wells/WellState.hpp index 0056e7359..fb5e4d063 100644 --- a/opm/simulators/wells/WellState.hpp +++ b/opm/simulators/wells/WellState.hpp @@ -164,6 +164,8 @@ public: void communicateGroupRates(const Parallel::Communication& comm); void updateGlobalIsGrup(const Parallel::Communication& comm); + void updateEfficiencyScalingFactor(const std::string& wellName, + const Scalar value); bool isInjectionGrup(const std::string& name) const { @@ -180,6 +182,11 @@ public: return this->global_well_info.value().is_open(name); } + Scalar getGlobalEfficiencyScalingFactor(const std::string& name) const + { + return this->global_well_info.value().efficiency_scaling_factor(name); + } + Scalar getALQ(const std::string& name) const { return this->alq_state.get(name); @@ -373,7 +380,7 @@ private: // Use of std::optional<> here is a technical crutch, the // WellStateFullyImplicitBlackoil class should be default constructible, // whereas the GlobalWellInfo is not. - std::optional global_well_info; + std::optional> global_well_info; ALQState alq_state; // The well_rates variable is defined for all wells on all processors. The