marking some groups are NONE group control

based whether the group contribute to some SingleWellState::group_target
This commit is contained in:
Kai Bao committed 2026-01-27 10:34:03 +01:00
1 parent 5e5a57dfd3
commit 7c70f91109
7 files changed
+103 -15

No files matched your search

@@ -1947,6 +1947,82 @@ operator==(const BlackoilWellModelGeneric& rhs) const
&& this->gen_gaslift_ == rhs.gen_gaslift_;
}
template <typename Scalar, typename IndexTraits>
void
BlackoilWellModelGeneric<Scalar, IndexTraits>::
updateNONEProductionGroups(DeferredLogger& deferred_logger)
{
auto& group_state = this->groupState();
const auto& prod_group_controls = group_state.get_production_controls();
if (prod_group_controls.empty()) {
return;
}
const auto& well_state = this->wellState();
// numbers of the group production controls
// one group can have multiple controls, including NONE
const std::size_t size_pc = prod_group_controls.size();
// Collect groups that currently provide production targets to any well on this rank
std::unordered_set<std::string> targeted_production_groups; // TODO: better name
targeted_production_groups.reserve(size_pc);
for (const auto& wname : well_state.wells()) {
const auto& ws = well_state.well(wname);
if (ws.producer && ws.production_cmode == WellProducerCMode::GRUP) {
const auto& group_target = ws.group_target;
if (group_target.has_value()) {
targeted_production_groups.insert(group_target->first);
}
}
}
// parallel communication to synchronize production groups used on all processes
std::vector<std::string> gnames;
gnames.reserve(size_pc);
for (const auto& gprod : prod_group_controls) {
gnames.push_back(gprod.first);
}
std::vector<int> local_used(size_pc, 0);
for (std::size_t i = 0; i < size_pc; ++i) {
if (targeted_production_groups.find(gnames[i]) != targeted_production_groups.end()) {
local_used[i] = 1;
}
}
std::vector<int> global_used(size_pc, 0);
// with the following code, we only need to communicate once
if (comm_.size() > 1 && size_pc > 0) {
std::vector<int> gathered(comm_.size() * size_pc, 0);
comm_.allgather(local_used.data(), static_cast<int>(size_pc), gathered.data());
for (int r = 0; r < comm_.size(); ++r) {
const std::size_t base = static_cast<std::size_t>(r) * size_pc;
for (std::size_t i = 0; i < size_pc; ++i) {
global_used[i] = global_used[i] || gathered[base + i];
}
}
} else {
global_used = local_used;
}
for (std::size_t i = 0; i < size_pc; ++i) {
if (global_used[i] > 0) {
continue;
}
const auto& gname = gnames[i];
if (group_state.production_control(gname) != Group::ProductionCMode::NONE) {
if (comm_.rank() == 0) {
const std::string msg = fmt::format("Production group {} has no constraints active, setting control mode to NONE", gname);
deferred_logger.info(msg);
}
group_state.production_control(gname, Group::ProductionCMode::NONE);
}
}
}
template class BlackoilWellModelGeneric<double, BlackOilDefaultFluidSystemIndices>;
#if FLOW_INSTANTIATE_FLOAT
@@ -508,6 +508,8 @@ protected:
void assignMassGasRate(data::Wells& wsrpt,
const Scalar gasDensity) const;
void updateNONEProductionGroups(DeferredLogger& deferred_logger);
Schedule& schedule_;
const SummaryState& summaryState_;
@@ -770,6 +770,8 @@ namespace Opm {
this->calculateProductivityIndexValues(local_deferredLogger);
this->updateNONEProductionGroups(local_deferredLogger);
this->commitWGState();
//reporting output temperatures
+7
View File
@@ -412,6 +412,13 @@ GroupState<Scalar>::production_control(const std::string& gname) const
return group_iter->second;
}
template<class Scalar>
const std::map<std::string, Group::ProductionCMode>&
GroupState<Scalar>::get_production_controls() const
{
return this->production_controls;
};
//-------------------------------------------------------------------------
template<class Scalar>
+1
View File
@@ -99,6 +99,7 @@ public:
bool has_production_control(const std::string& gname) const;
void production_control(const std::string& gname, Group::ProductionCMode cmode);
Group::ProductionCMode production_control(const std::string& gname) const;
const std::map<std::string, Group::ProductionCMode>& get_production_controls() const;
bool has_injection_control(const std::string& gname, Phase phase) const;
void injection_control(const std::string& gname, Phase phase, Group::InjectionCMode cmode);
+3 -3
View File
@@ -553,7 +553,7 @@ getGroupRatesAvailableForHigherLevelControl(const Group& group, const bool is_in
}
template <typename Scalar, typename IndexTraits>
std::optional<Scalar>
std::optional<std::pair<std::string, Scalar>>
GroupStateHelper<Scalar, IndexTraits>::getWellGroupTargetInjector(const std::string& name,
const std::string& parent,
const Group& group,
@@ -644,7 +644,7 @@ GroupStateHelper<Scalar, IndexTraits>::getWellGroupTargetInjector(const std::str
do_addback);
// Avoid negative target rates coming from too large local reductions.
return std::max(Scalar(0.0), target / efficiency_factor);
return std::make_pair(group.name(), std::max(Scalar(0.0), target / efficiency_factor));
}
template <typename Scalar, typename IndexTraits>
@@ -660,7 +660,7 @@ GroupStateHelper<Scalar, IndexTraits>::getWellGroupTargetProducer(const std::str
// 'parent' will be the name of 'group'. But if we recurse, 'name' and
// 'parent' will stay fixed while 'group' will be higher up
// in the group tree.
// Eficiencyfactor is the well efficiency factor for the first group the well is
// Efficiency factor is the well efficiency factor for the first group the well is
// part of. Later it is the accumulated factor including the group efficiency factor
// of the child of group.
OPM_TIMEFUNCTION();
+12 -12
View File
@@ -243,20 +243,20 @@ public:
GuideRate::RateVector getProductionGroupRateVector(const std::string& group_name) const;
std::optional<Scalar> getWellGroupTargetInjector(const std::string& name,
const std::string& parent,
const Group& group,
const Scalar* rates,
const Phase injection_phase,
const Scalar efficiency_factor,
const std::vector<Scalar>& resv_coeff) const;
std::optional<std::pair<std::string, Scalar>> getWellGroupTargetInjector(const std::string& name,
const std::string& parent,
const Group& group,
const Scalar* rates,
const Phase injection_phase,
const Scalar efficiency_factor,
const std::vector<Scalar>& resv_coeff) const;
std::optional<std::pair<std::string, Scalar>> getWellGroupTargetProducer(const std::string& name,
const std::string& parent,
const Group& group,
const Scalar* rates,
const Scalar efficiency_factor,
const std::vector<Scalar>& resv_coeff) const;
const std::string& parent,
const Group& group,
const Scalar* rates,
const Scalar efficiency_factor,
const std::vector<Scalar>& resv_coeff) const;
GuideRate::RateVector getWellRateVector(const std::string& name) const;