Skip to content

Commit 22da731

Browse files
committed
move GroupStateHelper::computeNetworkPressures to BlackoilWellModelNetworkGeneric
it is the only consumer
1 parent 0e247a3 commit 22da731

File tree

4 files changed

+185
-171
lines changed

4 files changed

+185
-171
lines changed

opm/simulators/wells/BlackoilWellModelNetworkGeneric.cpp

Lines changed: 174 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
#include <opm/input/eclipse/Schedule/Schedule.hpp>
3131
#include <opm/input/eclipse/Schedule/Network/Balance.hpp>
32-
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
3332

3433
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
3534
#include <opm/simulators/wells/GroupStateHelper.hpp>
@@ -144,10 +143,10 @@ updatePressures(const int reportStepIdx,
144143

145144
const auto previous_node_pressures = node_pressures_;
146145

147-
node_pressures_ = well_model_.groupStateHelper().
148-
computeNetworkPressures(network,
149-
*well_model_.getVFPProperties().getProd(),
150-
well_model_.comm());
146+
node_pressures_ = this->computePressures(network,
147+
*well_model_.getVFPProperties().getProd(),
148+
reportStepIdx,
149+
well_model_.comm());
151150

152151
// here, the network imbalance is the difference between the previous nodal pressure and the new nodal pressure
153152
Scalar network_imbalance = 0.;
@@ -233,11 +232,10 @@ assignNodeValues(std::map<std::string, data::NodeData>& nodevalues,
233232
return;
234233
}
235234

236-
auto converged_pressures =
237-
well_model_.groupStateHelper().
238-
computeNetworkPressures(network,
239-
*well_model_.getVFPProperties().getProd(),
240-
well_model_.comm());
235+
auto converged_pressures = this->computePressures(network,
236+
*well_model_.getVFPProperties().getProd(),
237+
reportStepIdx,
238+
well_model_.comm());
241239
for (const auto& [node, converged_pressure] : converged_pressures) {
242240
auto it = nodevalues.find(node);
243241
assert(it != nodevalues.end() );
@@ -285,6 +283,172 @@ initializeWell(WellInterfaceGeneric<Scalar,IndexTraits>& well)
285283
}
286284
}
287285

286+
template <typename Scalar, typename IndexTraits>
287+
std::map<std::string, Scalar>
288+
BlackoilWellModelNetworkGeneric<Scalar, IndexTraits>::
289+
computePressures(const Network::ExtNetwork& network,
290+
const VFPProdProperties<Scalar>& vfp_prod_props,
291+
const int reportStepIdx,
292+
const Parallel::Communication& comm) const
293+
{
294+
// TODO: Only dealing with production networks for now.
295+
OPM_TIMEFUNCTION();
296+
if (!network.active()) {
297+
return {};
298+
}
299+
300+
const auto& group_state = well_model_.groupStateHelper().groupState();
301+
const auto& well_state = well_model_.groupStateHelper().wellState();
302+
303+
std::map<std::string, Scalar> node_pressures;
304+
auto roots = network.roots();
305+
for (const auto& root : roots) {
306+
// Fixed pressure nodes of the network are the roots of trees.
307+
// Leaf nodes must correspond to groups in the group structure.
308+
// Let us first find all leaf nodes of the network. We also
309+
// create a vector of all nodes, ordered so that a child is
310+
// always after its parent.
311+
std::stack<std::string> children;
312+
std::set<std::string> leaf_nodes;
313+
std::vector<std::string> root_to_child_nodes;
314+
// children.push(network.root().name());
315+
children.push(root.get().name());
316+
while (!children.empty()) {
317+
const auto node = children.top();
318+
children.pop();
319+
root_to_child_nodes.push_back(node);
320+
auto branches = network.downtree_branches(node);
321+
if (branches.empty()) {
322+
leaf_nodes.insert(node);
323+
}
324+
for (const auto& branch : branches) {
325+
children.push(branch.downtree_node());
326+
}
327+
}
328+
assert(children.empty());
329+
330+
// Starting with the leaf nodes of the network, get the flow rates
331+
// from the corresponding groups.
332+
std::map<std::string, std::vector<Scalar>> node_inflows;
333+
const std::vector<Scalar> zero_rates(3, 0.0);
334+
for (const auto& node : leaf_nodes) {
335+
// Guard against empty leaf nodes (may not be present in GRUPTREE)
336+
if (!well_model_.groupStateHelper().groupState().has_production_rates(node)) {
337+
node_inflows[node] = zero_rates;
338+
continue;
339+
}
340+
341+
node_inflows[node] = group_state.network_leaf_node_production_rates(node);
342+
// Add the ALQ amounts to the gas rates if requested.
343+
if (network.node(node).add_gas_lift_gas()) {
344+
const auto& group = well_model_.schedule().getGroup(node, reportStepIdx);
345+
Scalar alq = 0.0;
346+
for (const std::string& wellname : group.wells()) {
347+
const Well& well = well_model_.schedule().getWell(wellname, reportStepIdx);
348+
if (well.isInjector() || !well_state.isOpen(wellname)) {
349+
continue;
350+
}
351+
const Scalar efficiency = well.getEfficiencyFactor(/*network*/ true)
352+
* well_state.getGlobalEfficiencyScalingFactor(wellname);
353+
if (const auto& well_index = well_state.index(wellname);
354+
well_index.has_value() && well_state.wellIsOwned(well_index.value(), wellname))
355+
{
356+
alq += well_state.well(wellname).alq_state.get() * efficiency;
357+
}
358+
}
359+
alq = comm.sum(alq);
360+
node_inflows[node][IndexTraits::gasPhaseIdx] += alq;
361+
}
362+
}
363+
364+
// Accumulate in the network, towards the roots. Note that a
365+
// root (i.e. fixed pressure node) can still be contributing
366+
// flow towards other nodes in the network, i.e. a node is
367+
// the root of a subtree.
368+
auto child_to_root_nodes = root_to_child_nodes;
369+
std::reverse(child_to_root_nodes.begin(), child_to_root_nodes.end());
370+
for (const auto& node : child_to_root_nodes) {
371+
const auto upbranch = network.uptree_branch(node);
372+
if (upbranch) {
373+
// Add downbranch rates to upbranch.
374+
std::vector<Scalar>& up = node_inflows[(*upbranch).uptree_node()];
375+
const std::vector<Scalar>& down = node_inflows[node];
376+
// We now also support NEFAC
377+
const Scalar efficiency = network.node(node).efficiency();
378+
if (up.empty()) {
379+
up = std::vector<Scalar>(down.size(), 0.0);
380+
}
381+
assert(up.size() == down.size());
382+
for (std::size_t ii = 0; ii < up.size(); ++ii) {
383+
up[ii] += efficiency * down[ii];
384+
}
385+
}
386+
}
387+
388+
// Going the other way (from roots to leafs), calculate the pressure
389+
// at each node using VFP tables and rates.
390+
// std::map<std::string, double> node_pressures;
391+
for (const auto& node : root_to_child_nodes) {
392+
auto press = network.node(node).terminal_pressure();
393+
if (press) {
394+
node_pressures[node] = *press;
395+
}
396+
else {
397+
const auto upbranch = network.uptree_branch(node);
398+
assert(upbranch);
399+
const Scalar up_press = node_pressures[(*upbranch).uptree_node()];
400+
const auto vfp_table = (*upbranch).vfp_table();
401+
if (vfp_table) {
402+
OPM_TIMEBLOCK(NetworkVfpCalculations);
403+
// The rates are here positive, but the VFP code expects the
404+
// convention that production rates are negative, so we must
405+
// take a copy and flip signs.
406+
auto rates = node_inflows[node];
407+
std::transform(
408+
rates.begin(), rates.end(), rates.begin(), [](const auto r) { return -r; });
409+
assert(rates.size() == 3);
410+
// NB! ALQ in extended network is never implicitly the gas lift rate (GRAT), i.e., the
411+
// gas lift rates only enters the network pressure calculations through the rates
412+
// (e.g., in GOR calculations) unless a branch ALQ is set in BRANPROP.
413+
//
414+
// @TODO: Standard network
415+
Scalar alq = (*upbranch).alq_value().value_or(0.0);
416+
node_pressures[node]
417+
= vfp_prod_props.bhp(*vfp_table,
418+
rates[IndexTraits::waterPhaseIdx],
419+
rates[IndexTraits::oilPhaseIdx],
420+
rates[IndexTraits::gasPhaseIdx],
421+
up_press,
422+
alq,
423+
0.0, // explicit_wfr
424+
0.0, // explicit_gfr
425+
false); // use_expvfp we dont support explicit lookup
426+
#define EXTRA_DEBUG_NETWORK 0
427+
#if EXTRA_DEBUG_NETWORK
428+
std::ostringstream oss;
429+
oss << "parent: " << (*upbranch).uptree_node() << " child: " << node << " rates = [ "
430+
<< rates[0] * 86400 << ", " << rates[1] * 86400 << ", " << rates[2] * 86400 << " ]"
431+
<< " p(parent) = " << up_press / 1e5 << " p(child) = " << node_pressures[node] / 1e5
432+
<< std::endl;
433+
OpmLog::debug(oss.str());
434+
#endif
435+
}
436+
else {
437+
// Table number specified as 9999 in the deck, no pressure loss.
438+
if (network.node(node).as_choke()) {
439+
// Node pressure is set to the group THP.
440+
node_pressures[node] = well_model_.groupStateHelper().groupState().well_group_thp(node);
441+
}
442+
else {
443+
node_pressures[node] = up_press;
444+
}
445+
}
446+
}
447+
}
448+
}
449+
return node_pressures;
450+
}
451+
288452
template<typename Scalar, typename IndexTraits>
289453
bool BlackoilWellModelNetworkGeneric<Scalar, IndexTraits>::
290454
operator==(const BlackoilWellModelNetworkGeneric<Scalar,IndexTraits>& rhs) const

opm/simulators/wells/BlackoilWellModelNetworkGeneric.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
#ifndef OPM_BLACKOILWELLMODEL_NETWORK_GENERIC_HEADER_INCLUDED
2424
#define OPM_BLACKOILWELLMODEL_NETWORK_GENERIC_HEADER_INCLUDED
2525

26+
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
27+
2628
#include <opm/output/data/Groups.hpp>
29+
2730
#include <opm/simulators/utils/ParallelCommunication.hpp>
2831

2932
#include <map>
@@ -34,6 +37,7 @@ namespace Opm {
3437
class Schedule;
3538
template<class Scalar, class IndexTraits> class BlackoilWellModelGeneric;
3639
template<typename Scalar, typename IndexTraits> class WellInterfaceGeneric;
40+
template<typename Scalar> class VFPProdProperties;
3741
}
3842

3943
namespace Opm {
@@ -100,6 +104,13 @@ class BlackoilWellModelNetworkGeneric
100104
bool operator==(const BlackoilWellModelNetworkGeneric<Scalar,IndexTraits>& rhs) const;
101105

102106
protected:
107+
std::map<std::string, Scalar>
108+
computePressures(const Network::ExtNetwork& network,
109+
const VFPProdProperties<Scalar>& vfp_prod_props,
110+
const int reportStepIdx,
111+
const Parallel::Communication& comm) const;
112+
113+
103114
bool active_{false};
104115
BlackoilWellModelGeneric<Scalar,IndexTraits>& well_model_;
105116

0 commit comments

Comments
 (0)