mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-10-24 22:57:42 -05:00
Merge pull request #6355 from totto82/replaceGroupControlsWellsAndFix
Replace group controls wells and fix
This commit is contained in:
6 files changed
+185
-34
No files matched your search
@@ -1372,10 +1372,24 @@ updateAndCommunicateGroupData(const int reportStepIdx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto& well_state = this->wellState();
|
||||
const auto& well_state_nupcol = this->nupcolWellState();
|
||||
|
||||
constexpr int num_configs = 4;
|
||||
constexpr std::array<bool, num_configs> is_production_group = {true, false, false, false};
|
||||
constexpr std::array<Phase, num_configs> phases = { Phase::OIL, Phase::WATER, Phase::OIL, Phase::GAS };
|
||||
for (int i = 0; i < num_configs; i++) {
|
||||
WellGroupHelpers<Scalar>::updateGroupControlledWells(schedule(),
|
||||
well_state,
|
||||
this->groupState(),
|
||||
summaryState_,
|
||||
&guideRate_,
|
||||
reportStepIdx,
|
||||
"FIELD",
|
||||
is_production_group[i],
|
||||
phases[i]);
|
||||
}
|
||||
|
||||
// the group target reduction rates needs to be update since wells may have switched to/from GRUP control
|
||||
// The group target reduction does not honor NUPCOL.
|
||||
std::vector<Scalar> groupTargetReduction(numPhases(), 0.0);
|
||||
@@ -2186,9 +2200,12 @@ reportGroupSwitching(DeferredLogger& local_deferredLogger) const
|
||||
const Group::InjectionCMode& oldControl =
|
||||
this->prevWGState().group_state.injection_control(grname, phase);
|
||||
if (ctrls.back() != oldControl) {
|
||||
std::ostringstream ss;
|
||||
ss << phase;
|
||||
const std::string msg =
|
||||
fmt::format(" Injection Group {} control model changed from {} to {}",
|
||||
fmt::format(" Injection Group {} (phase = {}) control model changed from {} to {}",
|
||||
grname,
|
||||
ss.str(),
|
||||
Group::InjectionCMode2String(oldControl),
|
||||
Group::InjectionCMode2String(ctrls.back()));
|
||||
local_deferredLogger.info(msg);
|
||||
|
||||
@@ -190,8 +190,6 @@ groupControlledWells(const std::string& group_name,
|
||||
return WellGroupHelpers<Scalar>::groupControlledWells(schedule_,
|
||||
well_state_,
|
||||
this->group_state_,
|
||||
this->summary_state_,
|
||||
this->guide_rate_,
|
||||
report_step_,
|
||||
group_name,
|
||||
always_included_child,
|
||||
|
||||
@@ -54,6 +54,8 @@ GroupState<Scalar> GroupState<Scalar>::serializationTestObject()
|
||||
result.injection_controls = {{{Phase::FOAM, "test12"}, Group::InjectionCMode::REIN}};
|
||||
result.gpmaint_state.add("foo", GPMaint::State::serializationTestObject());
|
||||
result.m_gconsump_rates = {{"testA", {0.2, 0.1}}};
|
||||
result.m_number_of_wells_under_group_control = {{"test13", 3}};
|
||||
result.m_number_of_wells_under_inj_group_control = {{ {Phase::WATER, "test14"}, 3}};
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -72,6 +74,8 @@ bool GroupState<Scalar>::operator==(const GroupState& other) const
|
||||
this->inj_surface_rates == other.inj_surface_rates &&
|
||||
this->m_grat_sales_target == other.m_grat_sales_target &&
|
||||
this->injection_controls == other.injection_controls &&
|
||||
this->m_number_of_wells_under_group_control == m_number_of_wells_under_group_control &&
|
||||
this->m_number_of_wells_under_inj_group_control == m_number_of_wells_under_inj_group_control &&
|
||||
this->gpmaint_state == other.gpmaint_state &&
|
||||
this->m_gconsump_rates == other.m_gconsump_rates;
|
||||
}
|
||||
@@ -416,6 +420,48 @@ injection_control(const std::string& gname, Phase phase) const
|
||||
return group_iter->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<class Scalar>
|
||||
void GroupState<Scalar>::
|
||||
update_number_of_wells_under_group_control(const std::string& gname, int number)
|
||||
{
|
||||
this->m_number_of_wells_under_group_control[gname] = number;
|
||||
}
|
||||
template<class Scalar>
|
||||
int GroupState<Scalar>::
|
||||
number_of_wells_under_group_control(const std::string& gname) const
|
||||
{
|
||||
auto group_iter = this->m_number_of_wells_under_group_control.find(gname);
|
||||
if (group_iter == this->m_number_of_wells_under_group_control.end())
|
||||
throw std::logic_error("No such group");
|
||||
|
||||
return group_iter->second;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
|
||||
template<class Scalar>
|
||||
void GroupState<Scalar>::
|
||||
update_number_of_wells_under_inj_group_control(const std::string& gname, Phase phase, int number)
|
||||
{
|
||||
this->m_number_of_wells_under_inj_group_control[{phase, gname}] = number;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
int GroupState<Scalar>::
|
||||
number_of_wells_under_inj_group_control(const std::string& gname, Phase phase) const
|
||||
{
|
||||
auto group_iter = this->m_number_of_wells_under_inj_group_control.find({phase, gname});
|
||||
if (group_iter == this->m_number_of_wells_under_inj_group_control.end())
|
||||
throw std::logic_error("No such group");
|
||||
|
||||
return group_iter->second;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<class Scalar>
|
||||
|
||||
@@ -104,6 +104,13 @@ public:
|
||||
void injection_control(const std::string& gname, Phase phase, Group::InjectionCMode cmode);
|
||||
Group::InjectionCMode injection_control(const std::string& gname, Phase phase) const;
|
||||
|
||||
void update_number_of_wells_under_group_control(const std::string& gname, int number);
|
||||
int number_of_wells_under_group_control(const std::string& gname) const;
|
||||
|
||||
void update_number_of_wells_under_inj_group_control(const std::string& gname, Phase phase, int number);
|
||||
int number_of_wells_under_inj_group_control(const std::string& gname, Phase phase) const;
|
||||
|
||||
|
||||
void update_gconsump(const Schedule& schedule, const int report_step, const SummaryState& summary_state);
|
||||
const std::pair<Scalar, Scalar>& gconsump_rates(const std::string& gname) const;
|
||||
|
||||
@@ -217,6 +224,8 @@ public:
|
||||
serializer(injection_controls);
|
||||
serializer(gpmaint_state);
|
||||
serializer(m_gconsump_rates);
|
||||
serializer(m_number_of_wells_under_group_control);
|
||||
serializer(m_number_of_wells_under_inj_group_control);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -234,6 +243,9 @@ private:
|
||||
std::map<std::string, Scalar> m_gpmaint_target;
|
||||
std::map<std::string, Scalar> group_thp;
|
||||
std::map<std::string, GroupPotential> production_group_potentials;
|
||||
std::map<std::string, int> m_number_of_wells_under_group_control;
|
||||
std::map<std::pair<Phase, std::string>, int> m_number_of_wells_under_inj_group_control;
|
||||
|
||||
|
||||
std::map<std::pair<Phase, std::string>, Group::InjectionCMode> injection_controls;
|
||||
WellContainer<GPMaint::State> gpmaint_state;
|
||||
|
||||
@@ -392,7 +392,7 @@ updateGroupTargetReduction(const Group& group,
|
||||
const bool individual_control = (currentGroupControl != Group::InjectionCMode::FLD
|
||||
&& currentGroupControl != Group::InjectionCMode::NONE);
|
||||
const int num_group_controlled_wells
|
||||
= groupControlledWells(schedule, wellState, group_state, summaryState, &guide_rate, reportStepIdx, subGroupName, "", !isInjector, phase);
|
||||
= groupControlledWells(schedule, wellState, group_state, reportStepIdx, subGroupName, "", !isInjector, phase);
|
||||
if (individual_control || num_group_controlled_wells == 0) {
|
||||
groupTargetReduction[phase_pos]
|
||||
+= subGroupEfficiency * sumWellSurfaceRates(subGroup, schedule, wellState, reportStepIdx, phase_pos, isInjector);
|
||||
@@ -408,7 +408,7 @@ updateGroupTargetReduction(const Group& group,
|
||||
const bool individual_control = (currentGroupControl != Group::ProductionCMode::FLD
|
||||
&& currentGroupControl != Group::ProductionCMode::NONE);
|
||||
const int num_group_controlled_wells
|
||||
= groupControlledWells(schedule, wellState, group_state, summaryState, &guide_rate, reportStepIdx, subGroupName, "", !isInjector, /*injectionPhaseNotUsed*/Phase::OIL);
|
||||
= groupControlledWells(schedule, wellState, group_state, reportStepIdx, subGroupName, "", !isInjector, /*injectionPhaseNotUsed*/Phase::OIL);
|
||||
if (individual_control || num_group_controlled_wells == 0) {
|
||||
for (int phase = 0; phase < np; phase++) {
|
||||
groupTargetReduction[phase]
|
||||
@@ -1112,23 +1112,22 @@ getGuideRateInj(const std::string& name,
|
||||
|
||||
template<class Scalar>
|
||||
int WellGroupHelpers<Scalar>::
|
||||
groupControlledWells(const Schedule& schedule,
|
||||
const WellState<Scalar>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const SummaryState& summary_state,
|
||||
const GuideRate* guideRate,
|
||||
const int report_step,
|
||||
const std::string& group_name,
|
||||
const std::string& always_included_child,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase)
|
||||
updateGroupControlledWells(const Schedule& schedule,
|
||||
const WellState<Scalar>& well_state,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summary_state,
|
||||
const GuideRate* guideRate,
|
||||
const int report_step,
|
||||
const std::string& group_name,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
const Group& group = schedule.getGroup(group_name, report_step);
|
||||
int num_wells = 0;
|
||||
for (const std::string& child_group : group.groups()) {
|
||||
|
||||
bool included = (child_group == always_included_child);
|
||||
bool included = false;
|
||||
if (is_production_group) {
|
||||
const auto ctrl = group_state.production_control(child_group);
|
||||
included = included || (ctrl == Group::ProductionCMode::FLD) || (ctrl == Group::ProductionCMode::NONE);
|
||||
@@ -1139,15 +1138,25 @@ groupControlledWells(const Schedule& schedule,
|
||||
|
||||
if (included) {
|
||||
num_wells
|
||||
+= groupControlledWells(schedule, well_state, group_state, summary_state, guideRate, report_step, child_group, always_included_child, is_production_group, injection_phase);
|
||||
+= updateGroupControlledWells(schedule, well_state, group_state, summary_state, guideRate, report_step, child_group, is_production_group, injection_phase);
|
||||
} else {
|
||||
updateGroupControlledWells(schedule, well_state, group_state, summary_state, guideRate, report_step, child_group, is_production_group, injection_phase);
|
||||
}
|
||||
}
|
||||
for (const std::string& child_well : group.wells()) {
|
||||
bool included = (child_well == always_included_child);
|
||||
if (is_production_group) {
|
||||
included = included || well_state.isProductionGrup(child_well) || group.as_choke();
|
||||
} else {
|
||||
included = included || well_state.isInjectionGrup(child_well);
|
||||
bool included = false;
|
||||
const Well& well = schedule.getWell(child_well, report_step);
|
||||
if (is_production_group && well.isProducer()) {
|
||||
included = included || well_state.isProductionGrup(child_well) || group.as_choke();
|
||||
} else if (!is_production_group && !well.isProducer()) {
|
||||
const auto& well_controls = well.injectionControls(summary_state);
|
||||
auto injectorType = well_controls.injector_type;
|
||||
if ( (injection_phase == Phase::WATER && injectorType == InjectorType::WATER ) ||
|
||||
(injection_phase == Phase::OIL && injectorType == InjectorType::OIL ) ||
|
||||
(injection_phase == Phase::GAS && injectorType == InjectorType::GAS ))
|
||||
{
|
||||
included = included || well_state.isInjectionGrup(child_well);
|
||||
}
|
||||
}
|
||||
const auto ctrl1 = group_state.production_control(group.name());
|
||||
if (group.as_choke() && ((ctrl1 == Group::ProductionCMode::FLD) || (ctrl1 == Group::ProductionCMode::NONE))){
|
||||
@@ -1218,6 +1227,37 @@ groupControlledWells(const Schedule& schedule,
|
||||
++num_wells;
|
||||
}
|
||||
}
|
||||
if (is_production_group) {
|
||||
group_state.update_number_of_wells_under_group_control(group_name, num_wells);
|
||||
} else {
|
||||
group_state.update_number_of_wells_under_inj_group_control(group_name, injection_phase, num_wells);
|
||||
}
|
||||
|
||||
return num_wells;
|
||||
}
|
||||
|
||||
|
||||
template<class Scalar>
|
||||
int WellGroupHelpers<Scalar>::
|
||||
groupControlledWells(const Schedule& schedule,
|
||||
const WellState<Scalar>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int report_step,
|
||||
const std::string& group_name,
|
||||
const std::string& always_included_child,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase)
|
||||
{
|
||||
auto num_wells = is_production_group ? group_state.number_of_wells_under_group_control(group_name)
|
||||
: group_state.number_of_wells_under_inj_group_control(group_name, injection_phase);
|
||||
if (schedule.hasWell(always_included_child, report_step)) {
|
||||
const bool isInGroup = isInGroupChainTopBot(always_included_child, group_name, schedule, report_step);
|
||||
const bool already_included = is_production_group ? well_state.isProductionGrup(always_included_child)
|
||||
: well_state.isInjectionGrup(always_included_child);
|
||||
if (!already_included && isInGroup) {
|
||||
num_wells++;
|
||||
}
|
||||
}
|
||||
return num_wells;
|
||||
}
|
||||
|
||||
@@ -1252,6 +1292,33 @@ groupChainTopBot(const std::string& bottom,
|
||||
return chain;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
bool
|
||||
WellGroupHelpers<Scalar>::
|
||||
isInGroupChainTopBot(const std::string& bottom,
|
||||
const std::string& top,
|
||||
const Schedule& schedule,
|
||||
const int report_step)
|
||||
{
|
||||
// Get initial parent, 'bottom' can be a well or a group.
|
||||
std::string parent;
|
||||
if (schedule.hasWell(bottom, report_step)) {
|
||||
parent = schedule.getWell(bottom, report_step).groupName();
|
||||
} else {
|
||||
parent = schedule.getGroup(bottom, report_step).parent();
|
||||
}
|
||||
|
||||
while (parent != top) {
|
||||
parent = schedule.getGroup(parent, report_step).parent();
|
||||
if (parent == top) {
|
||||
return true;
|
||||
} else if (parent == "FIELD") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
std::string
|
||||
WellGroupHelpers<Scalar>::
|
||||
@@ -1431,8 +1498,6 @@ checkGroupConstraintsProd(const std::string& name,
|
||||
const int num_gr_ctrl = groupControlledWells(schedule,
|
||||
wellState,
|
||||
group_state,
|
||||
summaryState,
|
||||
guideRate,
|
||||
reportStepIdx,
|
||||
chain[ii],
|
||||
"",
|
||||
@@ -1583,8 +1648,6 @@ getWellGroupTargetProducer(const std::string& name,
|
||||
const int num_gr_ctrl = groupControlledWells(schedule,
|
||||
wellState,
|
||||
group_state,
|
||||
summaryState,
|
||||
guideRate,
|
||||
reportStepIdx,
|
||||
chain[ii],
|
||||
"",
|
||||
@@ -1737,8 +1800,6 @@ checkGroupConstraintsInj(const std::string& name,
|
||||
const int num_gr_ctrl = groupControlledWells(schedule,
|
||||
wellState,
|
||||
group_state,
|
||||
summaryState,
|
||||
guideRate,
|
||||
reportStepIdx,
|
||||
chain[ii],
|
||||
"",
|
||||
@@ -1933,8 +1994,6 @@ getWellGroupTargetInjector(const std::string& name,
|
||||
const int num_gr_ctrl = groupControlledWells(schedule,
|
||||
wellState,
|
||||
group_state,
|
||||
summaryState,
|
||||
guideRate,
|
||||
reportStepIdx,
|
||||
chain[ii],
|
||||
"",
|
||||
|
||||
@@ -262,11 +262,22 @@ public:
|
||||
const Phase& injectionPhase,
|
||||
const PhaseUsage& pu);
|
||||
|
||||
/// update the number of wells that are actively under group control for a given group with name given by group_name
|
||||
/// its main usage is to detect cases where there is no wells under group control
|
||||
static int updateGroupControlledWells(const Schedule& schedule,
|
||||
const WellState<Scalar>& well_state,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summary_state,
|
||||
const GuideRate* guideRate,
|
||||
const int report_step,
|
||||
const std::string& group_name,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase);
|
||||
|
||||
/// returns the number of wells that are actively under group control for a given group with name given by group_name
|
||||
static int groupControlledWells(const Schedule& schedule,
|
||||
const WellState<Scalar>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const SummaryState& summary_state,
|
||||
const GuideRate* guideRate,
|
||||
const int report_step,
|
||||
const std::string& group_name,
|
||||
const std::string& always_included_child,
|
||||
@@ -314,6 +325,14 @@ public:
|
||||
const Schedule& schedule,
|
||||
const int report_step);
|
||||
|
||||
|
||||
// check if well/group bottom is a sub well/group of the group top
|
||||
static bool
|
||||
isInGroupChainTopBot(const std::string& bottom,
|
||||
const std::string& top,
|
||||
const Schedule& schedule,
|
||||
const int report_step);
|
||||
|
||||
static std::string
|
||||
control_group(const Group& group,
|
||||
const GroupState<Scalar>& group_state,
|
||||
|
||||
Reference in new issue
Block a user