Merge pull request #5816 from akva2/fix_wcycle_glob

Allow query for efficiency scaling factor in off-process wells where required
This commit is contained in:
Arne Morten Kvarving 2024-12-19 13:53:30 +01:00 committed by GitHub
commit 4f5c86d72c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 95 additions and 22 deletions

View File

@ -1575,7 +1575,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<Scalar>::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(),
reportStepIdx),
schedule(),

View File

@ -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<Scalar>::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);
}
}

View File

@ -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);

View File

@ -29,14 +29,17 @@
namespace Opm {
GlobalWellInfo::GlobalWellInfo(const Schedule& sched, std::size_t report_step, const std::vector<Well>& local_wells)
template<class Scalar>
GlobalWellInfo<Scalar>::
GlobalWellInfo(const Schedule& sched,
std::size_t report_step,
const std::vector<Well>& 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<class Scalar>
bool GlobalWellInfo<Scalar>::
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<class Scalar>
bool GlobalWellInfo<Scalar>::
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<class Scalar>
bool GlobalWellInfo<Scalar>::
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<class Scalar>
void GlobalWellInfo<Scalar>::
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<class Scalar>
void GlobalWellInfo<Scalar>::
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<class Scalar>
void GlobalWellInfo<Scalar>::
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<class Scalar>
void GlobalWellInfo<Scalar>::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<class Scalar>
Scalar GlobalWellInfo<Scalar>::
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<class Scalar>
std::size_t GlobalWellInfo<Scalar>::
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<class Scalar>
const std::string& GlobalWellInfo<Scalar>::
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<double>;
#if FLOW_INSTANTIATE_FLOAT
template class GlobalWellInfo<float>;
#endif
}

View File

@ -49,7 +49,7 @@ enum class WellStatus;
under group control.
*/
template<class Scalar>
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<int> m_in_injecting_group; // global_index -> int/bool
std::vector<int> m_in_producing_group; // global_index -> int/bool
std::vector<int> m_is_open; // global_index -> int/bool
std::vector<Scalar> m_efficiency_scaling_factors; // global_index --> double
};

View File

@ -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;
}
}

View File

@ -271,7 +271,7 @@ void WellState<Scalar>::init(const std::vector<Scalar>& 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<GlobalWellInfo>(schedule,
this->global_well_info = std::make_optional<GlobalWellInfo<Scalar>>(schedule,
report_step,
wells_ecl);
well_rates.clear();
@ -969,6 +969,7 @@ void WellState<Scalar>::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<Scalar>::updateGlobalIsGrup(const Parallel::Communication& comm)
this->global_well_info.value().communicate(comm);
}
template<class Scalar>
void WellState<Scalar>::
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<class Scalar>
data::Segment
WellState<Scalar>::reportSegmentResults(const int well_id,

View File

@ -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<GlobalWellInfo> global_well_info;
std::optional<GlobalWellInfo<Scalar>> global_well_info;
ALQState<Scalar> alq_state;
// The well_rates variable is defined for all wells on all processors. The