-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support instantaneous flow rates in extended network (WEFAC and GEFAC item 3) #5410
Conversation
jenkins build this opm-common=4094 please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hei, I struggled to understand the roles of m_network_production_rates
and node_inflows
. It is node_inflows
that is used to update the network pressure. There is some overlap between these two.
I left some comments for consideration and discussion.
@@ -284,7 +284,7 @@ partiallySupported() | |||
{ | |||
"WEFAC", | |||
{ | |||
{3,{true, allow_values<std::string> {"YES"}, "WEFAC(WELNETWK): only the YES option is supported"}}, // EXTENDED_NETWORK_OPT | |||
{3,{true, allow_values<std::string> {"YES","NO"}, "WEFAC(WELNETWK): value must be YES or NO"}}, // USE_WEFAC_IN_NETWORK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this PR, should we move WEFAC
and GEFAC
out of PartiallySupportedFlowKeywords.cpp file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, and probably should, do that, but I think we give users a better error message by leaving it in there.
By explicitly listing only YES and NO as supported we get, e.g.:
WEFAC: invalid value 'YESss' for item 3
In file: TEST.DATA, line NNN
WEFAC(WELNETWK): value must be YES or NO
whereas we get something like the following (and at a later stage) if we remove the keywords from PartiallySupported:
In TEST.DATA line NNN
Internal error: Could not convert string 'NOSE' to bool
So what I would actually like is better first-level checking of fully supported keywords, but maybe we can leave it as is until that is in place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I share your view regarding what is a good error message. At the same time, for the item 3, it is only supposed to have YES
or NO
two options, then we are fully supporting item (keyword) when we can handle YES
and NO
, it is a little weird to have it in the file that indicating PartiallySupported
.
Not sure whether we should enforce good error message through this strategy. Maybe @bska can comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not optimal, for sure, but maybe ok for now if I add a comment that it is actually fully supported and kept in there for better validation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My current view is that we should enforce the good error message in the parser side. Unless we want to have a FullySupportedFlowKeywords.cpp
to regulate from the simulator side in an systematic level. It is confusing to have it in the PartiallySupportedFlowKeywords
file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, fair enough, will remove and extend handling in handle?EFAC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I changed my mind on this one, so added support for 'FullySupportedKeywords' within the current validation framework. With this we can pick up multiple simple parsing errors early and report them to the user, instead of taking them one-by-one in the keyword handlers. Added WEFAC and GEFAC for now, but with the framework in place it should be easy to add more keywords as we see fit.
opm/simulators/wells/GroupState.cpp
Outdated
template<class Scalar> | ||
bool GroupState<Scalar>::has_network_production_rates(const std::string& gname) const | ||
{ | ||
auto group_iter = this->m_network_production_rates.find(gname); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want, you can use the following,
return this->m_network_production_rates.count(gname) > 0;
to me it is easier to read and less code. but you do not have to.
And also, I do not think this function is used anywhere. Maybe can consider to remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't disagree, but I just copied the style of the existing 'has_production_rates' function. Can update that as well then. I would like to keep the function, I expect it to be required for output purposes (see below).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is fine and partly personal preference. When we support c++20, we can use the member function contains
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll leave this as is then 👍
std::vector<Scalar> network_rates = rates; | ||
if (network.needs_instantaneous_rates(schedule, reportStepIdx)) { | ||
for (int phase = 0; phase < np; ++phase) { | ||
network_rates[phase] = sumWellPhaseRates(false, group, schedule, wellState, reportStepIdx, phase, /*isInjector*/ false, /*network*/ true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can be wrong here. It looks like for the network_production_rates
, we only use the values for all the leaf_nodes
in its current form.
Maybe we should only need to do differently for the leaf_nodes
. It looks like we will deal with other non-leaf nodes in the function computeNetworkPressures
based on the rates of the leaf_nodes
.
If that sounds correct to you, maybe we can deal with this in the function computeNetworkPressures
where the leaf_nodes
information are available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, only the leaf nodes are used in computeNetworkPressures, but this seemed to be the easies way to get those correctly. Also, to be able to report the rates I expect we will need to have all the rates actually used in the network available.
I may have missed something, but to handle this entirely within the computeNetworkPressures it appears that large parts of the sumWellPhaseRates function would need to be duplicated (essentially everything below the recursive call), so I fail to see how that would be simpler (?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One important thing missing from current m_network_production_rates
in the current form is that, if a network node is not in the GRUPTREE, it will not be in the m_network_production_rates
. Because network nodes and group nodes can be different.
And also, can we call sumWellPhaseRates
through computeNetworkPressures
in some way instead of duplicating them. I could not tell why we can not do that by looking at the code.
Ideally, we might need a function called updateNetworkProductionRates()
. You do not have to do it unless you are really up to it. We can make a refactoring PR following this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not yet support NEFAC so the rates of non-group nodes would always be full rates, but I can see that it probably would be cleaner to also have these stored and co-located with the others. This should be fairly straightforward to change so I can have a go at it.
Regarding the leaf node rates, if I have understood tings correctly this requires global communication after calling sumWellPhaseRates
, so I still think it is better to leverage the machinery in GroupState for this. If you insist on doing this within computeNetworkPressures
I kindly ask that you provide a working implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct when coming to the parallel communication. I did not think about it and my apologizes. Will respond with more looking into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries, and thanks! I'll await further input then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(without considering NEFAC, then basically, NEFAC is 1.0 for the nodes not in the GRUPTREE)
In the current way, m_network_production_rates
holds the values for all the group nodes. node_inflows
holds a complete version of the rates for all the network nodes.
When all the group nodes are in the network, for the nodes they both contain, they should have the same values. although calculated through different paths and NEFAC is 1.0.
For the situations where some group nodes are not in the network, for example, they have different levels of hierarchy, how to calculate the values (using the efficiency factors) I think is something we can only test to find out, it is not totally clear to me about how things should be done. Likely, m_network_production_rates
can have different values from the values in node_inflows
, depending on the understanding we use at the end.
In the current code, computeNetworkPressures
is going through the network branches, and updateGroupProductionRates
is going through the group tree. We do not want to do global communication in the function computeNetworkPressures
. Ideally we can borrow the function updateGroupProductionRates
to get leaf-nodes (only leaf-nodes), and handle the network-way of production rates in computeNetworkPressures
.
Now I agree with you that the current way is a simpler way to get things done. And also, I see that with NEFAC and nodes in the GRUPTREE and not in the network probably introduces re-working in these parts. We can get the results correct first and follow with re-factoring in these parts.
Sorry for the previous misunderstandings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, I can see it is confusing with the member m_network_production_rates
where only leaf rates are used, and will try to make it more clear with proper comments. Glad we can agree to move forward with the current overall approach for now. Thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When all the group nodes are in the network, for the nodes they both contain, they should have the same values. although calculated through different paths and NEFAC is 1.0.
Just for record in case it helps understanding and design or for later usage.
Not totally sure though. With extended network model, we might have different hierarchy layout between nodes, then for the non-leaf nodes, they will have very different values between m_network_production_rates
and node_inflows
. Luckily, the leaf nodes in the m_network_production_rates
should still have the correct/desired value. node_inflows
will most likely be the one holding the correct/desired values that represent the network structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated now to support NEFAC and only compute and store the leaf node rates in GroupState.
Please give a hint when the update is finished with this PR. And maybe @bska can have a look at the changes related to KeywordValidition and FullySupportedFlowKeywords? |
Will do, placing this and the companion in opm-common in draft for now. |
Plan to rebase on #5866 |
dd05f93
to
8cf2876
Compare
Now contains 5866 for testing - will rebase once that is merged. |
8cf2876
to
c871709
Compare
jenkins build this opm-common=4094 please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks correct to me. Assuming the results have been verified and I only left a few minor comments.
} | ||
assert (up.size() == down.size()); | ||
for (std::size_t ii = 0; ii < up.size(); ++ii) { | ||
up[ii] += (efficiency*down[ii]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the bracket ( )
is not necessary.
opm/simulators/wells/GroupState.cpp
Outdated
@@ -83,6 +85,13 @@ bool GroupState<Scalar>::has_production_rates(const std::string& gname) const | |||
return (group_iter != this->m_production_rates.end()); | |||
} | |||
|
|||
template<class Scalar> | |||
bool GroupState<Scalar>::has_network_leaf_node_production_rates(const std::string& gname) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function does not looks like used.
@@ -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; | |||
Scalar factor = wellEcl.getEfficiencyFactor(network) * wellState[wellEcl.name()].efficiency_scaling_factor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const
can be kept here.
@@ -962,13 +977,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]; | |||
// @TODO@ Also support NEFAC (for nodes that do not correspond to groups) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What else do we need to do to support this scenario?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this is now supported, updated comment.
@@ -962,13 +977,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]; | |||
// @TODO@ Also support NEFAC (for nodes that do not correspond to groups) | |||
const double efficiency = network.node(node).efficiency(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scalar
here.
With OPM/opm-tests#1175 merged, I think we can have a regression test with it. It can go in with this PR or go in with a separate following up PR. |
Thank you for the review, will update now. I agree that we should add the test, but let's do that in a follow-up PR. |
146db86
to
1913186
Compare
jenkins build this opm-common=4094 please |
Thanks for the update. The upstream PR OPM/opm-common#4094 has been merged. I am also getting this PR in now. |
Needs OPM/opm-common#4094