mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #5410 from vkip/extnet_efficiency
Support instantaneous flow rates in extended network (WEFAC and GEFAC item 3)
This commit is contained in:
commit
1e89fe7013
@ -32,6 +32,12 @@ const SupportedKeywordItems<std::string>&
|
||||
fullySupported()
|
||||
{
|
||||
static const SupportedKeywordItems<std::string> fully_supported_keywords_strings = {
|
||||
{
|
||||
"GEFAC",
|
||||
{
|
||||
{3,{true, is_bool_convertible {}, "GEFAC(GRPNETWK): String value must be convertible to bool."}}, // USE_GEFAC_IN_NETWORK
|
||||
},
|
||||
},
|
||||
{
|
||||
"NEXTSTEP",
|
||||
{
|
||||
@ -44,6 +50,12 @@ fullySupported()
|
||||
{3,{true, allow_values<std::string> {"ORAT", "WRAT", "GRAT", "LRAT", "RESV", "BHP"}, "WCONHIST(TARGET): should be set to ORAT/WRAT/GRAT/LRAT/RESV or BHP"}}, // CMODE
|
||||
},
|
||||
},
|
||||
{
|
||||
"WEFAC",
|
||||
{
|
||||
{3,{true, is_bool_convertible {}, "WEFAC(WELNETWK): String value must be convertible to bool."}}, // USE_WEFAC_IN_NETWORK
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return fully_supported_keywords_strings;
|
||||
@ -66,6 +78,12 @@ const SupportedKeywordItems<double>&
|
||||
fullySupported()
|
||||
{
|
||||
static const SupportedKeywordItems<double> fully_supported_keywords_double = {
|
||||
{
|
||||
"NEFAC",
|
||||
{
|
||||
{2,{true, [](double x) { return x > 0 && x <= 1.0; }, "NEFAC(EFF_FACTOR: Efficiency must be in the range (0,1]"}}, // NETWORK_EFF_FACTOR
|
||||
},
|
||||
},
|
||||
{
|
||||
"WPIMULT",
|
||||
{
|
||||
|
@ -111,12 +111,6 @@ partiallySupported()
|
||||
{8,{true, allow_values<std::string> {"NO"}, "GECON(ENDRUN): End run not implemented"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"GEFAC",
|
||||
{
|
||||
{3,{true, allow_values<std::string> {"YES"}, "GEFAC(GRPNETWK): Extended Network Model efficiency NO option not implemented"}}, // TRANSFER_EXT_NET
|
||||
},
|
||||
},
|
||||
{
|
||||
"GRIDOPTS",
|
||||
{
|
||||
@ -273,12 +267,6 @@ partiallySupported()
|
||||
{5,{true, allow_values<std::string> {"NO"}, "WAGHYSTR(WATER_MODEL): only the NO option is supported – will STOP"}}, // WATER_MODEL
|
||||
},
|
||||
},
|
||||
{
|
||||
"WEFAC",
|
||||
{
|
||||
{3,{true, allow_values<std::string> {"YES"}, "WEFAC(WELNETWK): only the YES option is supported"}}, // EXTENDED_NETWORK_OPT
|
||||
},
|
||||
},
|
||||
{
|
||||
"WELSPECS",
|
||||
{
|
||||
|
@ -397,7 +397,6 @@ const KeywordValidation::UnsupportedKeywords& unsupportedKeywords()
|
||||
{"NARROW", {true, std::nullopt}},
|
||||
{"NCONSUMP", {true, std::nullopt}},
|
||||
{"NCOMPS", {false, std::nullopt}},
|
||||
{"NEFAC", {true, std::nullopt}},
|
||||
{"NETCOMPA", {true, std::nullopt}},
|
||||
{"NEXT", {false, std::nullopt}},
|
||||
{"NEXTSTPL", {true, std::nullopt}},
|
||||
|
@ -1373,6 +1373,10 @@ updateAndCommunicateGroupData(const int reportStepIdx,
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
this->groupState());
|
||||
WellGroupHelpers<Scalar>::updateNetworkLeafNodeProductionRates(schedule(),
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
this->groupState());
|
||||
|
||||
WellGroupHelpers<Scalar>::updateGroupProductionRates(fieldGroup,
|
||||
schedule(),
|
||||
|
@ -41,6 +41,7 @@ GroupState<Scalar> GroupState<Scalar>::serializationTestObject()
|
||||
{
|
||||
GroupState result(3);
|
||||
result.m_production_rates = {{"test1", {1.0, 2.0}}};
|
||||
result.m_network_leaf_node_production_rates={{"test1", {1.0, 20}}};
|
||||
result.production_controls = {{"test2", Group::ProductionCMode::LRAT}};
|
||||
result.prod_red_rates = {{"test3", {3.0, 4.0, 5.0}}};
|
||||
result.inj_red_rates = {{"test4", {6.0, 7.0}}};
|
||||
@ -61,6 +62,7 @@ template<class Scalar>
|
||||
bool GroupState<Scalar>::operator==(const GroupState& other) const
|
||||
{
|
||||
return this->m_production_rates == other.m_production_rates &&
|
||||
this->m_network_leaf_node_production_rates == other.m_network_leaf_node_production_rates &&
|
||||
this->production_controls == other.production_controls &&
|
||||
this->prod_red_rates == other.prod_red_rates &&
|
||||
this->inj_red_rates == other.inj_red_rates &&
|
||||
@ -93,6 +95,16 @@ void GroupState<Scalar>::update_production_rates(const std::string& gname,
|
||||
this->m_production_rates[gname] = rates;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
void GroupState<Scalar>::update_network_leaf_node_production_rates(const std::string& gname,
|
||||
const std::vector<Scalar>& rates)
|
||||
{
|
||||
if (rates.size() != this->num_phases)
|
||||
throw std::logic_error("Wrong number of phases");
|
||||
|
||||
this->m_network_leaf_node_production_rates[gname] = rates;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
const std::vector<Scalar>&
|
||||
GroupState<Scalar>::production_rates(const std::string& gname) const
|
||||
@ -104,6 +116,17 @@ GroupState<Scalar>::production_rates(const std::string& gname) const
|
||||
return group_iter->second;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
const std::vector<Scalar>&
|
||||
GroupState<Scalar>::network_leaf_node_production_rates(const std::string& gname) const
|
||||
{
|
||||
auto group_iter = this->m_network_leaf_node_production_rates.find(gname);
|
||||
if (group_iter == this->m_network_leaf_node_production_rates.end())
|
||||
throw std::logic_error("No such group");
|
||||
|
||||
return group_iter->second;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<class Scalar>
|
||||
|
@ -52,7 +52,10 @@ public:
|
||||
bool has_production_rates(const std::string& gname) const;
|
||||
void update_production_rates(const std::string& gname,
|
||||
const std::vector<Scalar>& rates);
|
||||
void update_network_leaf_node_production_rates(const std::string& gname,
|
||||
const std::vector<Scalar>& rates);
|
||||
const std::vector<Scalar>& production_rates(const std::string& gname) const;
|
||||
const std::vector<Scalar>& network_leaf_node_production_rates(const std::string& gname) const;
|
||||
|
||||
void update_well_group_thp(const std::string& gname, const double& thp);
|
||||
Scalar well_group_thp(const std::string& gname) const;
|
||||
@ -130,6 +133,7 @@ public:
|
||||
|
||||
auto forAllGroupData = [&](auto& func) {
|
||||
iterateContainer(m_production_rates, func);
|
||||
iterateContainer(m_network_leaf_node_production_rates, func);
|
||||
iterateContainer(prod_red_rates, func);
|
||||
iterateContainer(inj_red_rates, func);
|
||||
iterateContainer(inj_resv_rates, func);
|
||||
@ -187,6 +191,7 @@ public:
|
||||
{
|
||||
serializer(num_phases);
|
||||
serializer(m_production_rates);
|
||||
serializer(m_network_leaf_node_production_rates);
|
||||
serializer(production_controls);
|
||||
serializer(group_thp);
|
||||
serializer(prod_red_rates);
|
||||
@ -205,6 +210,7 @@ public:
|
||||
private:
|
||||
std::size_t num_phases{};
|
||||
std::map<std::string, std::vector<Scalar>> m_production_rates;
|
||||
std::map<std::string, std::vector<Scalar>> m_network_leaf_node_production_rates;
|
||||
std::map<std::string, Group::ProductionCMode> production_controls;
|
||||
std::map<std::string, std::vector<Scalar>> prod_red_rates;
|
||||
std::map<std::string, std::vector<Scalar>> inj_red_rates;
|
||||
|
@ -90,14 +90,15 @@ namespace Opm {
|
||||
const Opm::WellState<Scalar>& wellState,
|
||||
const int reportStepIdx,
|
||||
const int phasePos,
|
||||
const bool injector)
|
||||
const bool injector,
|
||||
const bool network)
|
||||
{
|
||||
|
||||
Scalar rate = 0.0;
|
||||
for (const std::string& groupName : group.groups()) {
|
||||
const auto& groupTmp = schedule.getGroup(groupName, reportStepIdx);
|
||||
const auto& gefac = groupTmp.getGroupEfficiencyFactor();
|
||||
rate += gefac * sumWellPhaseRates(res_rates, groupTmp, schedule, wellState, reportStepIdx, phasePos, injector);
|
||||
const auto& gefac = groupTmp.getGroupEfficiencyFactor(network);
|
||||
rate += gefac * sumWellPhaseRates(res_rates, groupTmp, schedule, wellState, reportStepIdx, phasePos, injector, network);
|
||||
}
|
||||
|
||||
// only sum satelite production once
|
||||
@ -126,8 +127,7 @@ namespace Opm {
|
||||
if (wellEcl.getStatus() == Opm::Well::Status::SHUT)
|
||||
continue;
|
||||
|
||||
const Scalar factor = wellEcl.getEfficiencyFactor() *
|
||||
wellState[wellEcl.name()].efficiency_scaling_factor;
|
||||
const Scalar factor = wellEcl.getEfficiencyFactor(network) * wellState[wellEcl.name()].efficiency_scaling_factor;
|
||||
const auto& ws = wellState.well(well_index.value());
|
||||
if (res_rates) {
|
||||
const auto& well_rates = ws.reservoir_rates;
|
||||
@ -744,6 +744,30 @@ updateGroupProductionRates(const Group& group,
|
||||
group_state.update_production_rates(group.name(), rates);
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
void WellGroupHelpers<Scalar>::
|
||||
updateNetworkLeafNodeProductionRates(const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellState<Scalar>& wellState,
|
||||
GroupState<Scalar>& group_state)
|
||||
{
|
||||
const auto& network = schedule[reportStepIdx].network();
|
||||
if (network.active()) {
|
||||
const int np = wellState.numPhases();
|
||||
for (const auto& group_name : network.leaf_nodes()) {
|
||||
assert(schedule[reportStepIdx].groups.has(group_name));
|
||||
const auto& group = schedule[reportStepIdx].groups.get(group_name);
|
||||
std::vector<Scalar> network_rates(np, 0.0);
|
||||
if (group.numWells() > 0) {
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
network_rates[phase] = sumWellPhaseRates(false, group, schedule, wellState, reportStepIdx, phase, /*isInjector*/ false, /*network*/ true);
|
||||
}
|
||||
}
|
||||
group_state.update_network_leaf_node_production_rates(group_name, network_rates);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
void WellGroupHelpers<Scalar>::
|
||||
updateREINForGroups(const Group& group,
|
||||
@ -928,23 +952,15 @@ computeNetworkPressures(const Network::ExtNetwork& network,
|
||||
continue;
|
||||
}
|
||||
|
||||
node_inflows[node] = group_state.production_rates(node);
|
||||
node_inflows[node] = group_state.network_leaf_node_production_rates(node);
|
||||
// Add the ALQ amounts to the gas rates if requested.
|
||||
if (network.node(node).add_gas_lift_gas()) {
|
||||
const auto& group = schedule.getGroup(node, report_time_step);
|
||||
for (const std::string& wellname : group.wells()) {
|
||||
const Well& well = schedule.getWell(wellname, report_time_step);
|
||||
|
||||
if (well.isInjector() || !well_state.isOpen(wellname)) continue;
|
||||
// Here we use the efficiency unconditionally, but if WEFAC item 3
|
||||
// for the well is false (it defaults to true) then we should NOT use
|
||||
// the efficiency factor. Fixing this requires not only changing the
|
||||
// code here, but also:
|
||||
// - Adding a member to the well for this flag, and setting it in Schedule::handleWEFAC().
|
||||
// - Making the wells' maximum flows (i.e. not time-averaged by using a efficiency factor)
|
||||
// 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.getGlobalEfficiencyScalingFactor(wellname);
|
||||
const Scalar efficiency = well.getEfficiencyFactor(/*network*/ true) * well_state.getGlobalEfficiencyScalingFactor(wellname);
|
||||
node_inflows[node][BlackoilPhases::Vapour] += well_state.getALQ(wellname) * efficiency;
|
||||
}
|
||||
}
|
||||
@ -962,13 +978,14 @@ computeNetworkPressures(const Network::ExtNetwork& network,
|
||||
// Add downbranch rates to upbranch.
|
||||
std::vector<Scalar>& up = node_inflows[(*upbranch).uptree_node()];
|
||||
const std::vector<Scalar>& down = node_inflows[node];
|
||||
// We now also support NEFAC
|
||||
const Scalar efficiency = network.node(node).efficiency();
|
||||
if (up.empty()) {
|
||||
up = down;
|
||||
} else {
|
||||
assert (up.size() == down.size());
|
||||
for (std::size_t ii = 0; ii < up.size(); ++ii) {
|
||||
up[ii] += down[ii];
|
||||
}
|
||||
up = std::vector<Scalar>(down.size(), 0.0);
|
||||
}
|
||||
assert (up.size() == down.size());
|
||||
for (std::size_t ii = 0; ii < up.size(); ++ii) {
|
||||
up[ii] += efficiency*down[ii];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,8 @@ public:
|
||||
const Opm::WellState<Scalar>& wellState,
|
||||
const int reportStepIdx,
|
||||
const int phasePos,
|
||||
const bool injector);
|
||||
const bool injector,
|
||||
const bool network = false);
|
||||
|
||||
static Scalar satelliteProduction(const ScheduleState& sched,
|
||||
const std::vector<std::string>& groups,
|
||||
@ -199,6 +200,12 @@ public:
|
||||
const WellState<Scalar>& wellState,
|
||||
GroupState<Scalar>& group_state);
|
||||
|
||||
static void updateNetworkLeafNodeProductionRates(const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellState<Scalar>& wellState,
|
||||
GroupState<Scalar>& group_state);
|
||||
|
||||
|
||||
static void updateWellRatesFromGroupTargetScale(const Scalar scale,
|
||||
const Group& group,
|
||||
const Schedule& schedule,
|
||||
|
Loading…
Reference in New Issue
Block a user