Skip to content

Commit

Permalink
Introduce consistent naming of subnetworks and allocation networks (#…
Browse files Browse the repository at this point in the history
…1130)

Fixes #709.

The idea is that the modeler inputs a _subnetwork_, and what is derived
from that by allocation initialization is called an _allocation
network_.

The breaking change is that in the `Node` and `Edge` input tables, as
well as the `allocation.arrow` output table, `allocation_network_id` has
been replaced by `subnetwork_id`.
  • Loading branch information
SouthEndMusic committed Feb 16, 2024
1 parent 41a9803 commit ce50a74
Show file tree
Hide file tree
Showing 15 changed files with 134 additions and 144 deletions.
54 changes: 27 additions & 27 deletions core/src/allocation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function allocation_graph_used_nodes!(p::Parameters, allocation_network_id::Int)
end
end

# Add nodes in the allocation graph for nodes connected to the source edges
# Add nodes in the allocation network for nodes connected to the source edges
# One of these nodes can be outside the subnetwork, as long as the edge
# connects to the subnetwork
edges_source = graph[].edges_source
Expand Down Expand Up @@ -98,10 +98,10 @@ function indicate_allocation_flow!(
end

"""
This loop finds allocation graph edges in several ways:
- Between allocation graph nodes whose equivalent in the subnetwork are directly connected
- Between allocation graph nodes whose equivalent in the subnetwork are connected
with one or more allocation graph nodes in between
This loop finds allocation network edges in several ways:
- Between allocation network nodes whose equivalent in the subnetwork are directly connected
- Between allocation network nodes whose equivalent in the subnetwork are connected
with one or more allocation network nodes in between
"""
function find_allocation_graph_edges!(
p::Parameters,
Expand All @@ -125,7 +125,7 @@ function find_allocation_graph_edges!(
# If the current node_id is in the current subnetwork
if node_id in node_ids
# Direct connections in the subnetwork between nodes that
# are in the allocation graph
# are in the allocation network
for inneighbor_id in inneighbor_ids
if inneighbor_id in node_ids
# The opposite of source edges must not be made
Expand All @@ -139,7 +139,7 @@ function find_allocation_graph_edges!(
end
end
# Direct connections in the subnetwork between nodes that
# are in the allocation graph
# are in the allocation network
for outneighbor_id in outneighbor_ids
if outneighbor_id in node_ids
# The opposite of source edges must not be made
Expand All @@ -156,7 +156,7 @@ function find_allocation_graph_edges!(

elseif graph[node_id].allocation_network_id == allocation_network_id

# Try to find an existing allocation graph composite edge to add the current subnetwork_node_id to
# Try to find an existing allocation network composite edge to add the current subnetwork_node_id to
found_edge = false
for edge_composite in edges_composite
if edge_composite[1] in neighbor_ids
Expand All @@ -170,7 +170,7 @@ function find_allocation_graph_edges!(
end
end

# Start a new allocation graph composite edge if no existing edge to append to was found
# Start a new allocation network composite edge if no existing edge to append to was found
if !found_edge
push!(edges_composite, [node_id])
end
Expand All @@ -180,8 +180,8 @@ function find_allocation_graph_edges!(
end

"""
For the composite allocation graph edges:
- Find out whether they are connected to allocation graph nodes on both ends
For the composite allocation network edges:
- Find out whether they are connected to allocation network nodes on both ends
- Compute their capacity
- Find out their allowed flow direction(s)
"""
Expand All @@ -196,7 +196,7 @@ function process_allocation_graph_edges!(
edge_ids = graph[].edge_ids[allocation_network_id]

for edge_composite in edges_composite
# Find allocation graph node connected to this edge on the first end
# Find allocation network node connected to this edge on the first end
node_id_1 = nothing
neighbors_side_1 = inoutflow_ids(graph, edge_composite[1])
for neighbor_node_id in neighbors_side_1
Expand All @@ -212,21 +212,21 @@ function process_allocation_graph_edges!(
continue
end

# Find allocation graph node connected to this edge on the second end
# Find allocation network node connected to this edge on the second end
node_id_2 = nothing
neighbors_side_2 = inoutflow_ids(graph, edge_composite[end])
for neighbor_node_id in neighbors_side_2
if neighbor_node_id in node_ids
node_id_2 = neighbor_node_id
# Make sure this allocation graph node is distinct from the other one
# Make sure this allocation network node is distinct from the other one
if node_id_2 node_id_1
push!(edge_composite, neighbor_node_id)
break
end
end
end

# No connection to allocation graph node found on this side, so edge is discarded
# No connection to allocation network node found on this side, so edge is discarded
if isnothing(node_id_2)
continue
end
Expand All @@ -235,12 +235,12 @@ function process_allocation_graph_edges!(
continue
end

# Find capacity of this composite allocation graph edge
# Find capacity of this composite allocation network edge
positive_flow = true
negative_flow = true
edge_capacity = Inf
# The start and end subnetwork nodes of the composite allocation graph
# edge are now nodes that have an equivalent in the allocation graph,
# The start and end subnetwork nodes of the composite allocation network
# edge are now nodes that have an equivalent in the allocation network,
# these do not constrain the composite edge capacity
for (node_id_1, node_id_2, node_id_3) in IterTools.partition(edge_composite, 3, 1)
node = getfield(p, graph[node_id_2].type)
Expand All @@ -263,7 +263,7 @@ function process_allocation_graph_edges!(
end
end

# Add composite allocation graph edge(s)
# Add composite allocation network edge(s)
if positive_flow
indicate_allocation_flow!(graph, edge_composite)
capacity[node_id_1, node_id_2] = edge_capacity
Expand Down Expand Up @@ -307,7 +307,7 @@ end

"""
Add the edges connecting the main network work to a subnetwork to both the main network
and subnetwork allocation graph.
and subnetwork allocation network.
"""
function add_subnetwork_connections!(p::Parameters, allocation_network_id::Int)::Nothing
(; graph, allocation) = p
Expand All @@ -334,15 +334,15 @@ function allocation_graph(
# Find out which nodes in the subnetwork are used in the allocation network
allocation_graph_used_nodes!(p, allocation_network_id)

# Find the edges in the allocation graph
# Find the edges in the allocation network
edges_composite, capacity = find_allocation_graph_edges!(p, allocation_network_id)

# Process the edges in the allocation graph
# Process the edges in the allocation network
process_allocation_graph_edges!(capacity, edges_composite, p, allocation_network_id)
add_subnetwork_connections!(p, allocation_network_id)

if !valid_sources(p, allocation_network_id)
error("Errors in sources in allocation graph.")
error("Errors in sources in allocation network.")
end

# Discard user return flow in allocation if this leads to a closed loop of flow
Expand Down Expand Up @@ -656,7 +656,7 @@ function add_constraints_fractional_flow!(
for outflow_id_ in outflow_ids(graph, node_id)
if outflow_id_.type == NodeType.FractionalFlow
# The fractional flow nodes themselves are not represented in
# the allocation graph
# the allocation network
dst_id = outflow_id(graph, outflow_id_)
# For now only consider fractional flow nodes which end in a basin
if haskey(graph, node_id, dst_id) && dst_id.type == NodeType.Basin
Expand Down Expand Up @@ -731,7 +731,7 @@ function AllocationModel(
p::Parameters,
Δt_allocation::Float64,
)::AllocationModel
# Add allocation graph data to the model MetaGraph
# Add allocation network data to the model MetaGraph
capacity = allocation_graph(p, allocation_network_id)

# The JuMP.jl allocation problem
Expand Down Expand Up @@ -898,7 +898,7 @@ function assign_allocations!(

# Save allocations to record
push!(record.time, t)
push!(record.allocation_network_id, allocation_model.allocation_network_id)
push!(record.subnetwork_id, allocation_model.allocation_network_id)
push!(record.user_node_id, Int(user_node_id))
push!(record.priority, user.priorities[priority_idx])
push!(record.demand, user.demand[user_idx])
Expand Down Expand Up @@ -1050,7 +1050,7 @@ function save_allocation_flows!(
push!(record.edge_id, edge_metadata.id)
push!(record.from_node_id, node_ids[i])
push!(record.to_node_id, node_ids[i + 1])
push!(record.allocation_network_id, allocation_network_id)
push!(record.subnetwork_id, allocation_network_id)
push!(record.priority, priority)
push!(record.flow, flow)
push!(record.collect_demands, collect_demands)
Expand Down
34 changes: 13 additions & 21 deletions core/src/graph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ and data of edges (EdgeMetadata):
[`EdgeMetadata`](@ref)
"""
function create_graph(db::DB, config::Config, chunk_sizes::Vector{Int})::MetaGraph
node_rows =
execute(db, "SELECT fid, type, allocation_network_id FROM Node ORDER BY fid")
node_rows = execute(db, "SELECT fid, type, subnetwork_id FROM Node ORDER BY fid")
edge_rows = execute(
db,
"SELECT fid, from_node_type, from_node_id, to_node_type, to_node_id, edge_type, allocation_network_id FROM Edge ORDER BY fid",
"SELECT fid, from_node_type, from_node_id, to_node_type, to_node_id, edge_type, subnetwork_id FROM Edge ORDER BY fid",
)
# Node IDs per subnetwork
node_ids = Dict{Int, Set{NodeID}}()
Expand All @@ -36,10 +35,10 @@ function create_graph(db::DB, config::Config, chunk_sizes::Vector{Int})::MetaGra
for row in node_rows
node_id = NodeID(row.type, row.fid)
# Process allocation network ID
if ismissing(row.allocation_network_id)
if ismissing(row.subnetwork_id)
allocation_network_id = 0
else
allocation_network_id = row.allocation_network_id
allocation_network_id = row.subnetwork_id
if !haskey(node_ids, allocation_network_id)
node_ids[allocation_network_id] = Set{NodeID}()
end
Expand All @@ -58,7 +57,7 @@ function create_graph(db::DB, config::Config, chunk_sizes::Vector{Int})::MetaGra
to_node_type,
to_node_id,
edge_type,
allocation_network_id,
subnetwork_id,
) in edge_rows
try
# hasfield does not work
Expand All @@ -68,28 +67,21 @@ function create_graph(db::DB, config::Config, chunk_sizes::Vector{Int})::MetaGra
end
id_src = NodeID(from_node_type, from_node_id)
id_dst = NodeID(to_node_type, to_node_id)
if ismissing(allocation_network_id)
allocation_network_id = 0
if ismissing(subnetwork_id)
subnetwork_id = 0
end
edge_metadata = EdgeMetadata(
fid,
edge_type,
allocation_network_id,
id_src,
id_dst,
false,
NodeID[],
)
edge_metadata =
EdgeMetadata(fid, edge_type, subnetwork_id, id_src, id_dst, false, NodeID[])
graph[id_src, id_dst] = edge_metadata
if edge_type == EdgeType.flow
flow_counter += 1
flow_dict[(id_src, id_dst)] = flow_counter
end
if allocation_network_id != 0
if !haskey(edges_source, allocation_network_id)
edges_source[allocation_network_id] = Set{EdgeMetadata}()
if subnetwork_id != 0
if !haskey(edges_source, subnetwork_id)
edges_source[subnetwork_id] = Set{EdgeMetadata}()
end
push!(edges_source[allocation_network_id], edge_metadata)
push!(edges_source[subnetwork_id], edge_metadata)
end
end

Expand Down
8 changes: 4 additions & 4 deletions core/src/parameter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Store information for a subnetwork used for allocation.
objective_type: The name of the type of objective used
allocation_network_id: The ID of this allocation network
capacity: The capacity per edge of the allocation graph, as constrained by nodes that have a max_flow_rate
capacity: The capacity per edge of the allocation network, as constrained by nodes that have a max_flow_rate
problem: The JuMP.jl model for solving the allocation problem
Δt_allocation: The time interval between consecutive allocation solves
"""
Expand Down Expand Up @@ -78,7 +78,7 @@ struct Allocation
edge_id::Vector{Int},
from_node_id::Vector{Int},
to_node_id::Vector{Int},
allocation_network_id::Vector{Int},
subnetwork_id::Vector{Int},
priority::Vector{Int},
flow::Vector{Float64},
collect_demands::BitVector,
Expand All @@ -103,7 +103,7 @@ allocation_network_id_source: ID of allocation network where this edge is a sour
(0 if not a source)
from_id: the node ID of the source node
to_id: the node ID of the destination node
allocation_flow: whether this edge has a flow in an allocation graph
allocation_flow: whether this edge has a flow in an allocation network
node_ids: if this edge has allocation flow, these are all the
nodes from the physical layer this edge consists of
"""
Expand Down Expand Up @@ -477,7 +477,7 @@ struct User <: AbstractParameterNode
priorities::Vector{Int}
record::@NamedTuple{
time::Vector{Float64},
allocation_network_id::Vector{Int},
subnetwork_id::Vector{Int},
user_node_id::Vector{Int},
priority::Vector{Int},
demand::Vector{Float64},
Expand Down
4 changes: 2 additions & 2 deletions core/src/read.jl
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ function User(db::DB, config::Config)::User

record = (
time = Float64[],
allocation_network_id = Int[],
subnetwork_id = Int[],
user_node_id = Int[],
priority = Int[],
demand = Float64[],
Expand Down Expand Up @@ -822,7 +822,7 @@ function Parameters(db::DB, config::Config)::Parameters
edge_id = Int[],
from_node_id = Int[],
to_node_id = Int[],
allocation_network_id = Int[],
subnetwork_id = Int[],
priority = Int[],
flow = Float64[],
collect_demands = BitVector(),
Expand Down
4 changes: 2 additions & 2 deletions core/src/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ function get_level(
storage::Union{AbstractArray, Number} = 0,
)::Union{Real, Nothing}
(; basin, level_boundary) = p
if node_id.type == NodeType.Basin
if node_id.type == NodeType.Basin
_, i = id_index(basin.node_id, node_id)
current_level = get_tmp(basin.current_level, storage)
current_level[i]
Expand Down Expand Up @@ -588,7 +588,7 @@ is_flow_constraining(node::AbstractParameterNode) = hasfield(typeof(node), :max_
is_flow_direction_constraining(node::AbstractParameterNode) =
(nameof(typeof(node)) [:Pump, :Outlet, :TabulatedRatingCurve, :FractionalFlow])

"""Find out whether a path exists between a start node and end node in the given allocation graph."""
"""Find out whether a path exists between a start node and end node in the given allocation network."""
function allocation_path_exists_in_graph(
graph::MetaGraph,
start_node_id::NodeID,
Expand Down
8 changes: 4 additions & 4 deletions core/src/write.jl
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ function allocation_table(
model::Model,
)::@NamedTuple{
time::Vector{DateTime},
allocation_network_id::Vector{Int},
subnetwork_id::Vector{Int},
user_node_id::Vector{Int},
priority::Vector{Int},
demand::Vector{Float64},
Expand All @@ -183,7 +183,7 @@ function allocation_table(
time = datetime_since.(record.time, config.starttime)
return (;
time,
record.allocation_network_id,
record.subnetwork_id,
record.user_node_id,
record.priority,
record.demand,
Expand All @@ -199,7 +199,7 @@ function allocation_flow_table(
edge_id::Vector{Int},
from_node_id::Vector{Int},
to_node_id::Vector{Int},
allocation_network_id::Vector{Int},
subnetwork_id::Vector{Int},
priority::Vector{Int},
flow::Vector{Float64},
collect_demands::BitVector,
Expand All @@ -214,7 +214,7 @@ function allocation_flow_table(
record.edge_id,
record.from_node_id,
record.to_node_id,
record.allocation_network_id,
record.subnetwork_id,
record.priority,
record.flow,
record.collect_demands,
Expand Down
2 changes: 1 addition & 1 deletion core/test/allocation_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ end
@test only(main_network_connections[3]) == (NodeID(:Basin, 6), NodeID(:Pump, 24))
@test only(main_network_connections[4]) == (NodeID(:Basin, 10), NodeID(:Pump, 38))

# main-sub connections are part of main network allocation graph
# main-sub connections are part of main network allocation network
allocation_edges_main_network = graph[].edge_ids[1]
@test [
(NodeID(:Basin, 2), NodeID(:Pump, 11)),
Expand Down
Loading

0 comments on commit ce50a74

Please sign in to comment.