Skip to content
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

Avoid lookup of node type from Node metadata #1120

Merged
merged 4 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions core/src/allocation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
use_node = false
has_fractional_flow_outneighbors =
get_fractional_flow_connected_basins(node_id, basin, fractional_flow, graph)[3]
node_type = graph[node_id].type
if node_type in [:user, :basin, :terminal]
if node_id.type in [NodeType.User, NodeType.Basin, NodeType.Terminal]
use_node = true
elseif has_fractional_flow_outneighbors
use_node = true
Expand Down Expand Up @@ -244,8 +243,7 @@
# edge are now nodes that have an equivalent in the allocation graph,
# 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_type = graph[node_id_2].type
node = getfield(p, node_type)
node = getfield(p, graph[node_id_2].type)

# Find flow constraints
if is_flow_constraining(node)
Expand Down Expand Up @@ -281,7 +279,8 @@
return capacity
end

const allocation_source_nodetypes = Set{Symbol}([:level_boundary, :flow_boundary])
const allocation_source_nodetypes =
Set{NodeType.T}([NodeType.LevelBoundary, NodeType.FlowBoundary])

"""
Remove allocation user return flow edges that are upstream of the user itself.
Expand All @@ -290,7 +289,7 @@
(; graph) = p
node_ids = graph[].node_ids[allocation_network_id]
edge_ids = graph[].edge_ids[allocation_network_id]
node_ids_user = [node_id for node_id in node_ids if graph[node_id].type == :user]
node_ids_user = [node_id for node_id in node_ids if node_id.type == NodeType.User]

for node_id_user in node_ids_user
node_id_return_flow = only(outflow_ids_allocation(graph, node_id_user))
Expand Down Expand Up @@ -384,7 +383,7 @@
(; main_network_connections) = allocation
if startswith(config.allocation.objective_type, "linear")
node_ids = graph[].node_ids[allocation_network_id]
node_ids_user = [node_id for node_id in node_ids if graph[node_id].type == :user]
node_ids_user = [node_id for node_id in node_ids if node_id.type == NodeType.User]

# For the main network, connections to subnetworks are treated as users
if is_main_network(allocation_network_id)
Expand Down Expand Up @@ -506,7 +505,7 @@
F = problem[:F]
node_ids = graph[].node_ids[allocation_network_id]
node_ids_conservation =
[node_id for node_id in node_ids if graph[node_id].type == :basin]
[node_id for node_id in node_ids if node_id.type == NodeType.Basin]
main_network_source_edges = get_main_network_connections(p, allocation_network_id)
for edge in main_network_source_edges
push!(node_ids_conservation, edge[2])
Expand Down Expand Up @@ -544,8 +543,8 @@

node_ids = graph[].node_ids[allocation_network_id]
node_ids_user_with_returnflow = [
node_id for node_id in node_ids if
graph[node_id].type == :user && !isempty(outflow_ids_allocation(graph, node_id))
node_id for node_id in node_ids if node_id.type == NodeType.User &&
!isempty(outflow_ids_allocation(graph, node_id))
]
problem[:return_flow] = JuMP.@constraint(
problem,
Expand Down Expand Up @@ -576,7 +575,7 @@
objective_type = config.allocation.objective_type
if startswith(objective_type, "linear")
node_ids = graph[].node_ids[allocation_network_id]
node_ids_user = [node_id for node_id in node_ids if graph[node_id].type == :user]
node_ids_user = [node_id for node_id in node_ids if node_id.type == NodeType.User]

# For the main network, connections to subnetworks are treated as users
if is_main_network(allocation_network_id)
Expand Down Expand Up @@ -655,12 +654,12 @@
inflows = Dict{NodeID, JuMP.AffExpr}()
for node_id in node_ids
for outflow_id_ in outflow_ids(graph, node_id)
if graph[outflow_id_].type == :fractional_flow
if outflow_id_.type == NodeType.FractionalFlow
# The fractional flow nodes themselves are not represented in
# the allocation graph
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) && graph[dst_id].type == :basin
if haskey(graph, node_id, dst_id) && dst_id.type == NodeType.Basin
edge = (node_id, dst_id)
push!(edges_to_fractional_flow, edge)
node_idx = findsorted(fractional_flow.node_id, outflow_id_)
Expand Down Expand Up @@ -837,7 +836,7 @@
# Terms for user nodes
for edge_id in edge_ids
node_id_user = edge_id[2]
if graph[node_id_user].type != :user
if node_id_user.type != NodeType.User
continue
end

Expand Down Expand Up @@ -892,7 +891,7 @@

user_node_id = edge_id[2]

if graph[user_node_id].type == :user
if user_node_id.type == NodeType.User
allocated = JuMP.value(F[edge_id])
user_idx = findsorted(user.node_id, user_node_id)
user.allocated[user_idx][priority_idx] = allocated
Expand Down Expand Up @@ -1109,7 +1108,7 @@
@debug JuMP.solution_summary(problem)
if JuMP.termination_status(problem) !== JuMP.OPTIMAL
(; allocation_network_id) = allocation_model
priority = priorities[priority_idx]
priority = priorities[priority_index]

Check warning on line 1111 in core/src/allocation.jl

View check run for this annotation

Codecov / codecov/patch

core/src/allocation.jl#L1111

Added line #L1111 was not covered by tests
error(
"Allocation of subnetwork $allocation_network_id, priority $priority coudn't find optimal solution.",
)
Expand Down
10 changes: 5 additions & 5 deletions core/src/validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -551,19 +551,19 @@ function valid_discrete_control(p::Parameters, config::Config)::Bool
end
for (Δt, var, node_id) in zip(look_ahead, variable, listen_node_id)
if !iszero(Δt)
node_type = graph[node_id].type
node_type = node_id.type
# TODO: If more transient listen variables must be supported, this validation must be more specific
# (e.g. for some node some variables are transient, some not).
if node_type ∉ [:flow_boundary, :level_boundary]
if node_type ∉ [NodeType.FlowBoundary, NodeType.LevelBoundary]
errors = true
@error "Look ahead supplied for non-timeseries listen variable '$var' from listen node $node_id."
else
if Δt < 0
errors = true
@error "Negative look ahead supplied for listen variable '$var' from listen node $node_id."
else
node = getfield(p, node_type)
idx = if node_type == :Basin
node = getfield(p, graph[node_id].type)
idx = if node_type == NodeType.Basin
id_index(node.node_id, node_id)
else
searchsortedfirst(node.node_id, node_id)
Expand Down Expand Up @@ -593,7 +593,7 @@ function valid_sources(p::Parameters, allocation_network_id::Int)::Bool
for edge in edge_ids
(id_source, id_dst) = edge
if graph[id_source, id_dst].allocation_network_id_source == allocation_network_id
from_source_node = graph[id_source].type in allocation_source_nodetypes
from_source_node = id_source.type in allocation_source_nodetypes

if is_main_network(allocation_network_id)
if !from_source_node
Expand Down
Loading