Merge pull request #3695 from vkip/grupnet_reroute_hack
Allow rerouting in standard and extended network
This commit is contained in:
commit
16c6ee3bbb
@ -45,6 +45,7 @@ public:
|
||||
|
||||
const std::string& downtree_node() const;
|
||||
const std::string& uptree_node() const;
|
||||
void set_uptree_node(const std::string& new_uptree_node);
|
||||
std::optional<int> vfp_table() const;
|
||||
AlqEQ alq_eq() const;
|
||||
std::optional<double> alq_value() const;
|
||||
|
@ -37,7 +37,10 @@ class ExtNetwork {
|
||||
public:
|
||||
ExtNetwork() = default;
|
||||
bool active() const;
|
||||
bool is_standard_network() const;
|
||||
void set_standard_network(bool is_standard_network);
|
||||
void add_branch(Branch branch);
|
||||
void add_or_replace_branch(Branch branch);
|
||||
void drop_branch(const std::string& uptree_node, const std::string& downtree_node);
|
||||
bool has_node(const std::string& name) const;
|
||||
void update_node(Node node);
|
||||
@ -58,12 +61,14 @@ public:
|
||||
serializer(m_branches);
|
||||
serializer(insert_indexed_node_names);
|
||||
serializer(m_nodes);
|
||||
serializer(m_is_standard_network);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Branch> m_branches;
|
||||
std::vector<std::string> insert_indexed_node_names;
|
||||
std::map<std::string, Node> m_nodes;
|
||||
bool m_is_standard_network{false};
|
||||
bool has_indexed_node_name(const std::string& name) const;
|
||||
void add_indexed_node_name(std::string name);
|
||||
};
|
||||
|
@ -168,7 +168,11 @@ namespace {
|
||||
|
||||
void Schedule::handleBRANPROP(HandlerContext& handlerContext) {
|
||||
auto ext_network = this->snapshots.back().network.get();
|
||||
|
||||
if (ext_network.active() && ext_network.is_standard_network()) {
|
||||
std::string msg = "Cannot have standard and extended network defined simultaneously.";
|
||||
throw OpmInputError(msg, handlerContext.keyword.location());
|
||||
}
|
||||
ext_network.set_standard_network(false);
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const auto& downtree_node = record.getItem<ParserKeywords::BRANPROP::DOWNTREE_NODE>().get<std::string>(0);
|
||||
const auto& uptree_node = record.getItem<ParserKeywords::BRANPROP::UPTREE_NODE>().get<std::string>(0);
|
||||
@ -181,9 +185,9 @@ namespace {
|
||||
|
||||
if (alq_eq == Network::Branch::AlqEQ::ALQ_INPUT) {
|
||||
double alq_value = record.getItem<ParserKeywords::BRANPROP::ALQ>().get<double>(0);
|
||||
ext_network.add_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_value));
|
||||
ext_network.add_or_replace_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_value));
|
||||
} else {
|
||||
ext_network.add_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_eq));
|
||||
ext_network.add_or_replace_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_eq));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -843,6 +847,11 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
||||
|
||||
void Schedule::handleGRUPNET(HandlerContext& handlerContext) {
|
||||
auto network = this->snapshots.back().network.get();
|
||||
if (network.active() && !network.is_standard_network()) {
|
||||
std::string msg = "Cannot have standard and extended network defined simultaneously.";
|
||||
throw OpmInputError(msg, handlerContext.keyword.location());
|
||||
}
|
||||
network.set_standard_network(true);
|
||||
std::vector<Network::Node> nodes;
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const std::string& groupNamePattern = record.getItem<ParserKeywords::GRUPNET::NAME>().getTrimmedString(0);
|
||||
@ -888,9 +897,9 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
||||
const auto alq_eq = Network::Branch::AlqEqfromString(record.getItem<ParserKeywords::GRUPNET::ALQ_SURFACE_DENSITY>().get<std::string>(0));
|
||||
if (alq_eq == Network::Branch::AlqEQ::ALQ_INPUT) {
|
||||
const double alq_value = record.getItem<ParserKeywords::GRUPNET::ALQ>().get<double>(0);
|
||||
network.add_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_value));
|
||||
network.add_or_replace_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_value));
|
||||
} else {
|
||||
network.add_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_eq));
|
||||
network.add_or_replace_branch(Network::Branch(downtree_node, uptree_node, vfp_table, alq_eq));
|
||||
}
|
||||
}
|
||||
nodes.push_back(node);
|
||||
@ -1008,6 +1017,10 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
||||
|
||||
void Schedule::handleNODEPROP(HandlerContext& handlerContext) {
|
||||
auto ext_network = this->snapshots.back().network.get();
|
||||
if (ext_network.active() && ext_network.is_standard_network()) {
|
||||
std::string msg = "Cannot have standard and extended network defined simultaneously.";
|
||||
throw OpmInputError(msg, handlerContext.keyword.location());
|
||||
}
|
||||
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const auto& name = record.getItem<ParserKeywords::NODEPROP::NAME>().get<std::string>(0);
|
||||
|
@ -65,6 +65,10 @@ const std::string& Branch::downtree_node() const {
|
||||
return this->m_downtree_node;
|
||||
}
|
||||
|
||||
void Branch::set_uptree_node(const std::string& new_uptree_node) {
|
||||
this->m_uptree_node = new_uptree_node;
|
||||
}
|
||||
|
||||
bool Branch::operator==(const Branch& other) const {
|
||||
return this->m_downtree_node == other.m_downtree_node &&
|
||||
this->m_uptree_node == other.m_uptree_node &&
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
|
||||
|
||||
@ -30,6 +31,7 @@ ExtNetwork ExtNetwork::serializationTestObject() {
|
||||
object.m_branches = {Branch::serializationTestObject()};
|
||||
object.insert_indexed_node_names = {"test1", "test2"};
|
||||
object.m_nodes = {{"test3", Node::serializationTestObject()}};
|
||||
object.m_is_standard_network = false;
|
||||
return object;
|
||||
}
|
||||
|
||||
@ -37,6 +39,14 @@ bool ExtNetwork::active() const {
|
||||
return !this->m_branches.empty() && !this->m_nodes.empty();
|
||||
}
|
||||
|
||||
bool ExtNetwork::is_standard_network() const {
|
||||
return this->m_is_standard_network;
|
||||
}
|
||||
|
||||
void ExtNetwork::set_standard_network(bool is_standard_network) {
|
||||
this->m_is_standard_network = is_standard_network;
|
||||
}
|
||||
|
||||
bool ExtNetwork::operator==(const ExtNetwork& rhs) const {
|
||||
return this->m_branches == rhs.m_branches
|
||||
&& this->insert_indexed_node_names == rhs.insert_indexed_node_names
|
||||
@ -86,24 +96,47 @@ void ExtNetwork::add_branch(Branch branch)
|
||||
this->m_branches.push_back( std::move(branch) );
|
||||
}
|
||||
|
||||
void ExtNetwork::drop_branch(const std::string& uptree_node, const std::string& downtree_node) {
|
||||
auto downtree_branches = this->downtree_branches( downtree_node );
|
||||
if (downtree_branches.empty()) {
|
||||
auto branch_iter = std::find_if(this->m_branches.begin(), this->m_branches.end(), [&uptree_node, &downtree_node](const Branch& b) { return (b.uptree_node() == uptree_node && b.downtree_node() == downtree_node); });
|
||||
if (branch_iter != this->m_branches.end())
|
||||
this->m_branches.erase( branch_iter );
|
||||
void ExtNetwork::add_or_replace_branch(Branch branch)
|
||||
{
|
||||
const std::string& uptree_node = branch.uptree_node();
|
||||
const std::string& downtree_node = branch.downtree_node();
|
||||
|
||||
this->m_nodes.erase( downtree_node );
|
||||
} else {
|
||||
for (const auto& branch : downtree_branches)
|
||||
this->drop_branch(branch.uptree_node(), branch.downtree_node());
|
||||
// Add any missing nodes
|
||||
for (const std::string& nodename : { downtree_node, uptree_node }) {
|
||||
if (!this->has_node(nodename)) {
|
||||
this->m_nodes.insert_or_assign(nodename, Node{nodename});
|
||||
}
|
||||
if (!this->has_indexed_node_name(nodename)) {
|
||||
this->add_indexed_node_name(nodename);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any existing branch uptree from downtree_node (gathering tree structure required)
|
||||
// (If it is an existing branch that should be updated, it will be added again below)
|
||||
auto uptree_link = this->uptree_branch( downtree_node );
|
||||
if (uptree_link.has_value()){
|
||||
const auto& old_uptree_node = uptree_link.value().uptree_node();
|
||||
this->drop_branch(old_uptree_node, downtree_node);
|
||||
}
|
||||
|
||||
this->m_branches.push_back( std::move(branch) );
|
||||
}
|
||||
|
||||
void ExtNetwork::drop_branch(const std::string& uptree_node, const std::string& downtree_node) {
|
||||
auto branch_iter = std::find_if(this->m_branches.begin(),
|
||||
this->m_branches.end(),
|
||||
[&uptree_node, &downtree_node](const Branch& b) { return (b.uptree_node() == uptree_node && b.downtree_node() == downtree_node); });
|
||||
if (branch_iter != this->m_branches.end()) {
|
||||
this->m_branches.erase(branch_iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::optional<Branch> ExtNetwork::uptree_branch(const std::string& node) const {
|
||||
if (!this->has_node(node))
|
||||
throw std::out_of_range("No such node: " + node);
|
||||
if (!this->has_node(node)) {
|
||||
auto msg = fmt::format("Requesting uptree branch of undefined node: {}", node);
|
||||
throw std::out_of_range(msg);
|
||||
}
|
||||
|
||||
std::vector<Branch> branches;
|
||||
std::copy_if(this->m_branches.begin(), this->m_branches.end(), std::back_inserter(branches), [&node](const Branch& b) { return b.downtree_node() == node; });
|
||||
@ -113,13 +146,15 @@ std::optional<Branch> ExtNetwork::uptree_branch(const std::string& node) const {
|
||||
if (branches.size() == 1)
|
||||
return std::move(branches[0]);
|
||||
|
||||
throw std::logic_error("Bug - more than upstree branch for node: " + node);
|
||||
throw std::logic_error("Bug - more than one uptree branch for node: " + node);
|
||||
}
|
||||
|
||||
|
||||
std::vector<Branch> ExtNetwork::downtree_branches(const std::string& node) const {
|
||||
if (!this->has_node(node))
|
||||
throw std::out_of_range("No such node: " + node);
|
||||
if (!this->has_node(node)) {
|
||||
auto msg = fmt::format("Requesting downtree branches of undefined node: {}", node);
|
||||
throw std::out_of_range(msg);
|
||||
}
|
||||
|
||||
std::vector<Branch> branches;
|
||||
std::copy_if(this->m_branches.begin(), this->m_branches.end(), std::back_inserter(branches), [&node](const Branch& b) { return b.uptree_node() == node; });
|
||||
@ -161,11 +196,7 @@ void ExtNetwork::update_node(Node node)
|
||||
auto branch = std::find_if(this->m_branches.begin(), this->m_branches.end(),
|
||||
[&name](const Branch& b) { return b.uptree_node() == name || b.downtree_node() == name;});
|
||||
|
||||
if (branch == this->m_branches.end())
|
||||
throw std::invalid_argument("Node: " + name + " is not referenced by any branch and would be dangling.");
|
||||
|
||||
|
||||
if (branch->downtree_node() == name) {
|
||||
if (branch != this->m_branches.end() && branch->downtree_node() == name) {
|
||||
if (node.as_choke() && branch->vfp_table().has_value())
|
||||
throw std::invalid_argument("Node: " + name + " should serve as a choke => upstream branch can not have VFP table");
|
||||
}
|
||||
|
@ -1395,6 +1395,21 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
|
||||
new_child_group.updateParent(parent_name);
|
||||
this->snapshots.back().groups.update( std::move(new_child_group) );
|
||||
}
|
||||
|
||||
// Update standard network if required
|
||||
auto network = this->snapshots.back().network.get();
|
||||
if (!network.is_standard_network())
|
||||
return;
|
||||
if (network.has_node(child_name)) {
|
||||
auto old_branch = network.uptree_branch(child_name);
|
||||
if (old_branch.has_value()) {
|
||||
auto new_branch = old_branch.value();
|
||||
new_branch.set_uptree_node(parent_name);
|
||||
network.add_or_replace_branch(new_branch);
|
||||
this->snapshots.back().network.update( std::move(network));
|
||||
}
|
||||
// If no previous uptree branch the child is a fixed-pressure node, so no need to update network
|
||||
}
|
||||
}
|
||||
|
||||
void Schedule::addWellToGroup( const std::string& group_name, const std::string& well_name , std::size_t timeStep) {
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/input/eclipse/Units/Units.hpp>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@ -233,6 +234,9 @@ double nodePressure(const Opm::Schedule& sched,
|
||||
// find fixed pressure higher in the node tree
|
||||
bool fp_flag = false;
|
||||
auto node_name = nodeName;
|
||||
auto upt_br_opt = network.uptree_branch(node_name);
|
||||
if (!upt_br_opt.has_value()) return 0.0; // Node not belonging to the network right now
|
||||
|
||||
auto upt_br = network.uptree_branch(node_name).value();
|
||||
while (!fp_flag) {
|
||||
if (fixedPressureNode(sched, upt_br.uptree_node(), lookup_step)) {
|
||||
@ -243,8 +247,11 @@ double nodePressure(const Opm::Schedule& sched,
|
||||
if (network.uptree_branch(node_name).has_value()) {
|
||||
upt_br = network.uptree_branch(node_name).value();
|
||||
} else {
|
||||
auto msg = fmt::format("Node: {} has no uptree node with fixed pressure condition, uppermost node is: {} ", nodeName, node_name);
|
||||
throw std::logic_error(msg);
|
||||
auto msg = fmt::format("Node: {} does not belong to the network at report step: {} - node pressure set to zero.",
|
||||
node_name,
|
||||
lookup_step+1);
|
||||
Opm::OpmLog::warning(msg);
|
||||
return 0.0; // Subtree not belonging to the network right now
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -407,7 +414,7 @@ int numberOfBranchesConnToNode(const Opm::Schedule& sched, const std::string& no
|
||||
noBranches = (network.uptree_branch(nodeName).has_value()) ? noBranches+1 : noBranches;
|
||||
return noBranches;
|
||||
} else {
|
||||
auto msg = fmt::format("Actual node: {} has not been defined at report time: {} ", nodeName, lookup_step+1);
|
||||
auto msg = fmt::format("Trying to find number of branches connected to undefined node: {} at report time: {} ", nodeName, lookup_step+1);
|
||||
throw std::logic_error(msg);
|
||||
}
|
||||
}
|
||||
@ -438,6 +445,7 @@ template <class INodeArray>
|
||||
void staticContrib(const Opm::Schedule& sched,
|
||||
const std::string& nodeName,
|
||||
const std::size_t lookup_step,
|
||||
const std::size_t ngroups,
|
||||
INodeArray& iNode)
|
||||
{
|
||||
//
|
||||
@ -447,6 +455,9 @@ void staticContrib(const Opm::Schedule& sched,
|
||||
if (sched.hasGroup(nodeName, lookup_step)) {
|
||||
iNode[Ix::Group] = sched.getGroup(nodeName, lookup_step).insert_index();
|
||||
}
|
||||
if (nodeName == "FIELD") {
|
||||
iNode[Ix::Group] = ngroups;
|
||||
}
|
||||
iNode[Ix::FixedPresNode] = (fixedPressureNode(sched, nodeName, lookup_step)) ? 1 : 0;
|
||||
// the meaning of the value of item [4] is currently not known, the constant value used cover all cases so far
|
||||
iNode[4] = 1;
|
||||
@ -486,7 +497,7 @@ void staticContrib(const Opm::Schedule& sched,
|
||||
auto uptr_nd_res = findInVector<std::string>(nodeNames, branch.uptree_node());
|
||||
iBran[Ix::UpTreeNode] = (uptr_nd_res) ? uptr_nd_res.value() + 1 : 0 ;
|
||||
|
||||
iBran[Ix::VfpTableNo] = (branch.vfp_table().has_value()) ? branch.vfp_table().value() : 0;
|
||||
iBran[Ix::VfpTableNo] = (branch.vfp_table().has_value()) ? branch.vfp_table().value() : 9999;
|
||||
}
|
||||
} // Ibran
|
||||
|
||||
@ -670,13 +681,14 @@ captureDeclaredNetworkData(const Opm::EclipseState& es,
|
||||
const auto& networkNodePtrs = ndNmPt;
|
||||
const auto& branchPtrs = sched[lookup_step].network().branches();
|
||||
|
||||
const std::size_t ngroups = inteHead[VI::NGMAXZ];
|
||||
// Define Static Contributions to INode Array.
|
||||
nodeLoop(networkNodePtrs, [&sched, lookup_step, this]
|
||||
nodeLoop(networkNodePtrs, [&sched, lookup_step, ngroups, this]
|
||||
(const std::string& nodeName, const std::size_t nodeID) -> void
|
||||
{
|
||||
auto ind = this->iNode_[nodeID];
|
||||
|
||||
INode::staticContrib(sched, nodeName, lookup_step, ind);
|
||||
INode::staticContrib(sched, nodeName, lookup_step, ngroups, ind);
|
||||
});
|
||||
|
||||
// Define Static Contributions to IBran Array.
|
||||
|
@ -96,7 +96,9 @@ NODEPROP
|
||||
/
|
||||
)";
|
||||
|
||||
BOOST_CHECK_THROW( make_schedule(deck_string), std::exception);
|
||||
const auto& schedule = make_schedule(deck_string);
|
||||
const auto& network = schedule[0].network.get();
|
||||
BOOST_CHECK(network.has_node("B1X"));
|
||||
}
|
||||
|
||||
|
||||
@ -130,7 +132,9 @@ NODEPROP
|
||||
/
|
||||
)";
|
||||
|
||||
BOOST_CHECK_THROW( make_schedule(deck_string), std::exception);
|
||||
const auto& schedule = make_schedule(deck_string);
|
||||
const auto& network = schedule[0].network.get();
|
||||
BOOST_CHECK(network.has_node("PLAT-AX"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(INVALID_VFP_NODE) {
|
||||
@ -264,9 +268,9 @@ BRANPROP
|
||||
BOOST_CHECK_EQUAL(B1_uptree->downtree_node(), "B1");
|
||||
BOOST_CHECK_EQUAL(B1_uptree->uptree_node(), "PLAT-A");
|
||||
|
||||
BOOST_CHECK_THROW( network.uptree_branch("C1"), std::out_of_range);
|
||||
BOOST_CHECK_THROW( network.node("C1"), std::out_of_range);
|
||||
|
||||
BOOST_CHECK( network.has_node("C1") );
|
||||
BOOST_CHECK( !network.uptree_branch("C1") );
|
||||
|
||||
BOOST_CHECK(network.active());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user