Skip to content

Commit

Permalink
feat: Support for exclusive flows in AggregatedNode.
Browse files Browse the repository at this point in the history
A refactor of the aggregated node implementation to allow
support for sets of nodes. These are typically created when a
compound node (e.g. PiecewiseLink) is added to an AggregatedNode.
The compound node creates multiple "core" nodes, and these should
all be constrained by the AggregatedNode's factors or exclusivity.

The same consideration applies to the virtual storage nodes.

To do this there is a new method on Node in the schema to retrieve
the core node indices which that node has added to the core model.
For now this is a static implementation, but there are some nodes
which the user may to configure how this is done. E.g. should a
LossLink be constrained on its net or gross flow.
  • Loading branch information
jetuk committed Aug 2, 2024
1 parent 92d61a0 commit 9825b96
Show file tree
Hide file tree
Showing 33 changed files with 1,540 additions and 505 deletions.
361 changes: 290 additions & 71 deletions pywr-core/src/aggregated_node.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pywr-core/src/derived_metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl DerivedMetric {
Self::NodeInFlowDeficit(idx) => {
let node = network.get_node(idx)?;
let flow = state.get_network_state().get_node_in_flow(idx)?;
let max_flow = node.get_current_max_flow(network, state)?;
let max_flow = node.get_max_flow(network, state)?;
Ok(max_flow - flow)
}
Self::PowerFromNodeFlow(idx, turbine_data) => {
Expand Down
1 change: 0 additions & 1 deletion pywr-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ pub mod derived_metric;
pub mod edge;
pub mod metric;
pub mod models;
mod mutual_exclusivity;
pub mod network;
pub mod node;
pub mod parameters;
Expand Down
8 changes: 4 additions & 4 deletions pywr-core/src/metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,15 @@ impl MetricF64 {
MetricF64::NodeVolume(idx) => Ok(state.get_network_state().get_node_volume(idx)?),
MetricF64::AggregatedNodeInFlow(idx) => {
let node = model.get_aggregated_node(idx)?;
node.get_nodes()
.iter()
node.iter_nodes()
.flat_map(|indices| indices.iter())
.map(|idx| state.get_network_state().get_node_in_flow(idx))
.sum::<Result<_, _>>()
}
MetricF64::AggregatedNodeOutFlow(idx) => {
let node = model.get_aggregated_node(idx)?;
node.get_nodes()
.iter()
node.iter_nodes()
.flat_map(|indices| indices.iter())
.map(|idx| state.get_network_state().get_node_out_flow(idx))
.sum::<Result<_, _>>()
}
Expand Down
183 changes: 0 additions & 183 deletions pywr-core/src/mutual_exclusivity.rs

This file was deleted.

49 changes: 12 additions & 37 deletions pywr-core/src/network.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::aggregated_node::{AggregatedNode, AggregatedNodeIndex, AggregatedNodeVec, Factors};
use crate::aggregated_node::{AggregatedNode, AggregatedNodeIndex, AggregatedNodeVec, Relationship};
use crate::aggregated_storage_node::{AggregatedStorageNode, AggregatedStorageNodeIndex, AggregatedStorageNodeVec};
use crate::derived_metric::{DerivedMetric, DerivedMetricIndex};
use crate::edge::{Edge, EdgeIndex, EdgeVec};
use crate::metric::{MetricF64, SimpleMetricF64};
use crate::models::ModelDomain;
use crate::mutual_exclusivity::{MutualExclusivityNodeIndex, MutualExclusivityNodeVec};
use crate::node::{Node, NodeVec, StorageInitialVolume};
use crate::parameters::{GeneralParameterType, ParameterCollection, ParameterIndex, ParameterStates, VariableConfig};
use crate::recorders::{MetricSet, MetricSetIndex, MetricSetState};
Expand Down Expand Up @@ -201,7 +200,6 @@ pub struct Network {
aggregated_nodes: AggregatedNodeVec,
aggregated_storage_nodes: AggregatedStorageNodeVec,
virtual_storage_nodes: VirtualStorageVec,
mutual_exclusivity_nodes: MutualExclusivityNodeVec,
parameters: ParameterCollection,
derived_metrics: Vec<DerivedMetric>,
metric_sets: Vec<MetricSet>,
Expand Down Expand Up @@ -229,10 +227,6 @@ impl Network {
&self.virtual_storage_nodes
}

pub fn mutual_exclusivity_nodes(&self) -> &MutualExclusivityNodeVec {
&self.mutual_exclusivity_nodes
}

/// Setup the network and create the initial state for each scenario.
pub fn setup_network(
&self,
Expand Down Expand Up @@ -578,16 +572,16 @@ impl Network {
features.insert(SolverFeatures::AggregatedNodeDynamicFactors);
}

// Aggregated nodes with exclusivities require the MutualExclusivity feature.
if self.aggregated_nodes.iter().any(|n| n.has_exclusivity()) {
features.insert(SolverFeatures::MutualExclusivity);
}

// The presence of any virtual storage node requires the VirtualStorage feature.
if self.virtual_storage_nodes.len() > 0 {
features.insert(SolverFeatures::VirtualStorage);
}

// The presence of any mutual exclusivity nodes requires the MutualExclusivity feature.
if self.mutual_exclusivity_nodes.len() > 0 {
features.insert(SolverFeatures::MutualExclusivity);
}

features
}

Expand Down Expand Up @@ -957,14 +951,14 @@ impl Network {
Ok(())
}

pub fn set_aggregated_node_factors(
pub fn set_aggregated_node_relationship(
&mut self,
name: &str,
sub_name: Option<&str>,
factors: Option<Factors>,
relationship: Option<Relationship>,
) -> Result<(), PywrError> {
let node = self.get_mut_aggregated_node_by_name(name, sub_name)?;
node.set_factors(factors);
node.set_relationship(relationship);
Ok(())
}

Expand Down Expand Up @@ -1286,14 +1280,14 @@ impl Network {
&mut self,
name: &str,
sub_name: Option<&str>,
nodes: &[NodeIndex],
factors: Option<Factors>,
nodes: &[Vec<NodeIndex>],
relationship: Option<Relationship>,
) -> Result<AggregatedNodeIndex, PywrError> {
if let Ok(_agg_node) = self.get_aggregated_node_by_name(name, sub_name) {
return Err(PywrError::NodeNameAlreadyExists(name.to_string()));
}

let node_index = self.aggregated_nodes.push_new(name, sub_name, nodes, factors);
let node_index = self.aggregated_nodes.push_new(name, sub_name, nodes, relationship);
Ok(node_index)
}

Expand Down Expand Up @@ -1333,25 +1327,6 @@ impl Network {
Ok(vs_node_index)
}

/// Add a new `aggregated_node::AggregatedNode` to the network.
pub fn add_mutual_exclusivity_node(
&mut self,
name: &str,
sub_name: Option<&str>,
nodes: &[NodeIndex],
min_active: usize,
max_active: usize,
) -> Result<MutualExclusivityNodeIndex, PywrError> {
// if let Ok(_agg_node) = self.get_aggregated_node_by_name(name, sub_name) {
// return Err(PywrError::NodeNameAlreadyExists(name.to_string()));
// }

let node_index = self
.mutual_exclusivity_nodes
.push_new(name, sub_name, nodes, min_active, max_active);
Ok(node_index)
}

/// Add a [`parameters::GeneralParameter`] to the network
pub fn add_parameter(
&mut self,
Expand Down
Loading

0 comments on commit 9825b96

Please sign in to comment.