Skip to content

Commit

Permalink
Implement NEFAC + clean up implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
vkip committed Jan 20, 2025
1 parent ea28607 commit 9102c16
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 81 deletions.
63 changes: 27 additions & 36 deletions opm/input/eclipse/Schedule/Network/ExtNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cassert>
#include <iterator>
#include <stdexcept>
#include <fmt/format.h>
#include <vector>
#include <stack>
#include <functional>

#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
Expand All @@ -36,8 +38,6 @@ ExtNetwork ExtNetwork::serializationTestObject() {
object.insert_indexed_node_names = {"test1", "test2"};
object.m_nodes = {{"test3", Node::serializationTestObject()}};
object.m_is_standard_network = false;
object.m_needs_instantaneous_rates = false;
object.m_previous_update_report_step = -1;
return object;
}

Expand All @@ -56,9 +56,7 @@ void ExtNetwork::set_standard_network(bool 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
&& this->m_nodes == rhs.m_nodes
&& this->m_needs_instantaneous_rates == rhs.m_needs_instantaneous_rates
&& this->m_previous_update_report_step == rhs.m_previous_update_report_step;
&& this->m_nodes == rhs.m_nodes;
}


Expand Down Expand Up @@ -224,37 +222,6 @@ void ExtNetwork::update_node(Node node)
this->m_nodes.insert_or_assign(name, std::move(node) );
}

// @TODO@ : Make this ACTION safe
bool ExtNetwork::needs_instantaneous_rates(const Opm::Schedule& schedule, const int report_step) const {
// Just return value if we already checked this report step
if (report_step == this->m_previous_update_report_step) {
return this->m_needs_instantaneous_rates;
}
// Otherwise, check and update
for (const auto& it : this->m_nodes) {
const auto& node_name = it.second.name();
if (!schedule.hasGroup(node_name, report_step))
continue;
const auto& group = schedule.getGroup(node_name, report_step);
if (!group.useEfficiencyInNetwork()) {
this->m_needs_instantaneous_rates = true;
this->m_previous_update_report_step = report_step;
return true;
}
for (const std::string& well_name : group.wells()) {
const auto& well = schedule.getWell(well_name, report_step);
if(!well.useEfficiencyInNetwork()) {
this->m_needs_instantaneous_rates = true;
this->m_previous_update_report_step = report_step;
return true;
}
}
}
this->m_previous_update_report_step = report_step;
this->m_needs_instantaneous_rates = false;
return false;
}

void ExtNetwork::add_indexed_node_name(std::string name)
{
this->insert_indexed_node_names.emplace_back(name);
Expand All @@ -272,5 +239,29 @@ std::vector<std::string> ExtNetwork::node_names() const
{
return this->insert_indexed_node_names;
}

std::set<std::string> ExtNetwork::leaf_nodes() const
{
std::set<std::string> leaf_nodes;
auto roots = this->roots();
for (const auto& root : roots) {
std::stack<std::string> children;
children.push(root.get().name());
while (!children.empty()) {
const auto node = children.top();
children.pop();
auto branches = this->downtree_branches(node);
if (branches.empty()) {
leaf_nodes.insert(node);
}
for (const auto& branch : branches) {
children.push(branch.downtree_node());
}
}
assert(children.empty());
}
return leaf_nodes;
}

}
}
7 changes: 2 additions & 5 deletions opm/input/eclipse/Schedule/Network/ExtNetwork.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <optional>
#include <string>
#include <vector>
#include <set>
#include <functional>

#include <opm/input/eclipse/Schedule/Network/Branch.hpp>
Expand All @@ -47,13 +48,13 @@ class ExtNetwork {
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);
bool needs_instantaneous_rates(const Opm::Schedule& schedule, const int report_step) const;
const Node& node(const std::string& name) const;
std::vector<std::reference_wrapper<const Node>> roots() const;
std::vector<Branch> downtree_branches(const std::string& node) const;
std::vector<const Branch*> branches() const;
std::optional<Branch> uptree_branch(const std::string& node) const;
std::vector<std::string> node_names() const;
std::set<std::string> leaf_nodes() const;
int NoOfBranches() const;
int NoOfNodes() const;

Expand All @@ -67,17 +68,13 @@ class ExtNetwork {
serializer(insert_indexed_node_names);
serializer(m_nodes);
serializer(m_is_standard_network);
serializer(m_needs_instantaneous_rates);
serializer(m_previous_update_report_step);
}

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};
mutable bool m_needs_instantaneous_rates{false};
mutable int m_previous_update_report_step{-1};
bool has_indexed_node_name(const std::string& name) const;
void add_indexed_node_name(std::string name);
};
Expand Down
101 changes: 68 additions & 33 deletions opm/input/eclipse/Schedule/Network/NetworkKeywordHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,36 @@ void handleGRUPNET(HandlerContext& handlerContext)
handlerContext.state().network.update( std::move(network));
}

void handleNEFAC(HandlerContext& handlerContext)
{
auto ext_network = handlerContext.state().network.get();
if (!ext_network.active())
return;
if (ext_network.is_standard_network()) {
const std::string& msg = "NEFAC has no effect for a standard network: file {filename} line {lineno}";
OpmLog::warning(handlerContext.keyword.location().format(msg));
return;
}

bool updated = false;
for (const auto& record : handlerContext.keyword) {
const auto& node_name = record.getItem<ParserKeywords::NEFAC::NODE>().get<std::string>(0);
const auto efficiency = record.getItem<ParserKeywords::NEFAC::EFF_FACTOR>().getSIDouble(0);

if (ext_network.has_node(node_name)) {
auto node = ext_network.node(node_name);
if (node.efficiency() != efficiency) {
node.set_efficiency(efficiency);
ext_network.update_node(node);
updated = true;
}
}
}

if (updated)
handlerContext.state().network.update( std::move(ext_network) );
}

void handleNETBALAN(HandlerContext& handlerContext)
{
handlerContext.state().network_balance
Expand Down Expand Up @@ -180,44 +210,48 @@ void handleNODEPROP(HandlerContext& handlerContext)
node.terminal_pressure(pressure_item.getSIDouble(0));
}

if (as_choke) {
if (handlerContext.state().groups.has(name)) {
auto& group = handlerContext.state().groups.get(name);
group.as_choke(name);
if (group.wellgroup()) {
// Wells belong to a group with autochoke enabled are to be run on a common THP and should not have guide rates
for (const std::string& wellName : group.wells()) {
auto well = handlerContext.state().wells.get(wellName);

// Let the wells be operating on a THP Constraint
auto properties = std::make_shared<Well::WellProductionProperties>(well.getProductionProperties());
// The wells are not to be under GRUP control using guide rates but under THP control
properties->addProductionControl(Well::ProducerCMode::THP);
properties->controlMode = Well::ProducerCMode::THP;
well.updateProduction(properties);

// Guide rate availability should be set to false
well.updateAvailableForGroupControl(false);
auto new_config = handlerContext.state().guide_rate();
new_config.update_well(well);
handlerContext.state().guide_rate.update( std::move(new_config) );
handlerContext.state().wells.update( std::move(well) );
}
std::string target_group = name;
const auto& target_item = record.getItem<ParserKeywords::NODEPROP::CHOKE_GROUP>();

if (target_item.hasValue(0)) {
target_group = target_item.get<std::string>(0);
node.set_efficiency(group.getGroupEfficiencyFactor(/*network*/ true));

if (as_choke) {
group.as_choke(name);
if (group.wellgroup()) {
// Wells belong to a group with autochoke enabled are to be run on a common THP and should not have guide rates
for (const std::string& wellName : group.wells()) {
auto well = handlerContext.state().wells.get(wellName);

// Let the wells be operating on a THP Constraint
auto properties = std::make_shared<Well::WellProductionProperties>(well.getProductionProperties());
// The wells are not to be under GRUP control using guide rates but under THP control
properties->addProductionControl(Well::ProducerCMode::THP);
properties->controlMode = Well::ProducerCMode::THP;
well.updateProduction(properties);

// Guide rate availability should be set to false
well.updateAvailableForGroupControl(false);
auto new_config = handlerContext.state().guide_rate();
new_config.update_well(well);
handlerContext.state().guide_rate.update( std::move(new_config) );
handlerContext.state().wells.update( std::move(well) );
}
std::string target_group = name;
const auto& target_item = record.getItem<ParserKeywords::NODEPROP::CHOKE_GROUP>();

if (target_item.hasValue(0)) {
target_group = target_item.get<std::string>(0);
}
if (target_group != name) {
const std::string msg = "A manifold group must respond to its own target.";
throw OpmInputError(msg, handlerContext.keyword.location());
}
node.as_choke(target_group);
}
if (target_group != name) {
const std::string msg = "A manifold group must respond to its own target.";
else {
std::string msg = "The auto-choke option is implemented only for well groups.";
throw OpmInputError(msg, handlerContext.keyword.location());
}
node.as_choke(target_group);
}
else {
std::string msg = "The auto-choke option is implemented only for well groups.";
throw OpmInputError(msg, handlerContext.keyword.location());
}
}

node.add_gas_lift_gas(add_gas_lift_gas);
Expand All @@ -235,6 +269,7 @@ getNetworkHandlers()
return {
{ "BRANPROP", &handleBRANPROP },
{ "GRUPNET", &handleGRUPNET },
{ "NEFAC", &handleNEFAC },
{ "NETBALAN", &handleNETBALAN },
{ "NODEPROP", &handleNODEPROP },
};
Expand Down
21 changes: 15 additions & 6 deletions opm/input/eclipse/Schedule/Network/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ bool Node::as_choke() const {
return this->m_choke_target_group.has_value();
}

double Node::efficiency() const {
return this->m_efficiency;
}

void Node::terminal_pressure(double pressure) {
this->m_terminal_pressure = pressure;
}
Expand All @@ -59,23 +63,28 @@ void Node::as_choke(const std::string& target_group) {
this->m_choke_target_group = target_group;
}

void Node::set_efficiency(const double& efficiency) {
this->m_efficiency = efficiency;
}

bool Node::operator==(const Node& other) const {
return this->m_name == other.m_name &&
this->m_terminal_pressure == other.m_terminal_pressure &&
this->m_add_gas_lift_gas == other.m_add_gas_lift_gas &&
this->m_choke_target_group == other.m_choke_target_group;
this->m_choke_target_group == other.m_choke_target_group &&
this->m_efficiency == other.m_efficiency;
}


Node Node::serializationTestObject()
{
Node result;
result.m_name = "test";
result.m_terminal_pressure = 1.0;
result.m_add_gas_lift_gas = true;
Node result;
result.m_name = "test";
result.m_terminal_pressure = 1.0;
result.m_add_gas_lift_gas = true;
result.m_efficiency = 1.0;

return result;
return result;
}


Expand Down
6 changes: 5 additions & 1 deletion opm/input/eclipse/Schedule/Network/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ class Node {
const std::string& name() const;
const std::optional<double>& terminal_pressure() const;
bool as_choke() const;
double efficiency() const;
bool add_gas_lift_gas() const;
const std::optional<std::string>& target_group() const;

void terminal_pressure(double pressure);
void add_gas_lift_gas(bool add_gas);
void as_choke(const std::string& target_group);
void set_efficiency(const double& efficiency);

static Node serializationTestObject();
bool operator==(const Node& other) const;
Expand All @@ -52,12 +54,14 @@ class Node {
serializer(m_terminal_pressure);
serializer(m_add_gas_lift_gas);
serializer(m_choke_target_group);
serializer(m_efficiency);
}
private:
std::string m_name;
std::optional<double> m_terminal_pressure;
std::optional<std::string> m_choke_target_group;
bool m_add_gas_lift_gas = false;
bool m_add_gas_lift_gas{false};
double m_efficiency{1.0};
};
}
}
Expand Down

0 comments on commit 9102c16

Please sign in to comment.