Skip to content

Commit

Permalink
make demand, allocated matrices and index these directly (#1353)
Browse files Browse the repository at this point in the history
Fixes #1277
  • Loading branch information
SouthEndMusic authored Apr 4, 2024
1 parent 89b4525 commit 17d1fea
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 85 deletions.
26 changes: 13 additions & 13 deletions core/src/allocation_optim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function set_objective_priority!(
)::Nothing
(; problem, allocation_network_id) = allocation_model
(; graph, user_demand, flow_demand, allocation, basin) = p
(; node_id) = user_demand
(; node_id, demand_reduced) = user_demand
(; main_network_connections, subnetwork_demands) = allocation
edge_ids = graph[].edge_ids[allocation_network_id]

Expand Down Expand Up @@ -114,7 +114,8 @@ function set_objective_priority!(

if to_node_id.type == NodeType.UserDemand
# UserDemand
d = get_user_demand(p, to_node_id, priority_idx)
user_demand_idx = findsorted(node_id, to_node_id)
d = demand_reduced[user_demand_idx, priority_idx]
add_user_demand_term!(edge_id, d, problem)
else
has_demand, demand_node_id =
Expand Down Expand Up @@ -183,7 +184,7 @@ function assign_allocations!(
if user_demand_node_id.type == NodeType.UserDemand
allocated = JuMP.value(F[edge_id])
user_demand_idx = findsorted(user_demand.node_id, user_demand_node_id)
user_demand.allocated[user_demand_idx][priority_idx] = allocated
user_demand.allocated[user_demand_idx, priority_idx] = allocated
end
end
end
Expand Down Expand Up @@ -481,20 +482,19 @@ function set_initial_demands_user!(
)::Nothing
(; allocation_network_id) = allocation_model
(; graph, user_demand, allocation) = p
(; node_id, demand_from_timeseries, demand_itp) = user_demand
(; node_id, demand_from_timeseries, demand_itp, demand, demand_reduced) = user_demand

# Read the demand from the interpolated timeseries
# for users for which the demand comes from there
for (i, id) in enumerate(node_id)
if demand_from_timeseries[i] &&
graph[id].allocation_network_id == allocation_network_id
for priority_idx in eachindex(allocation.priorities)
d = demand_itp[i][priority_idx](t)
set_user_demand!(p, id, priority_idx, d; reduced = false)
demand[i, priority_idx] = demand_itp[i][priority_idx](t)
end
end
end
copy!(user_demand.demand_reduced, user_demand.demand)
copy!(demand_reduced, demand)
return nothing
end

Expand Down Expand Up @@ -576,17 +576,17 @@ function adjust_demands_user!(
)::Nothing
(; problem, allocation_network_id) = allocation_model
(; graph, user_demand) = p
(; node_id, demand_reduced) = user_demand
F = problem[:F]

# Reduce the demand by what was allocated
for id in user_demand.node_id
for (i, id) in enumerate(node_id)
if graph[id].allocation_network_id == allocation_network_id
d = max(
0.0,
get_user_demand(p, id, priority_idx) -
JuMP.value(F[(inflow_id(graph, id), id)]),
demand_reduced[i, priority_idx] - JuMP.value(F[(inflow_id(graph, id), id)]),
)
set_user_demand!(p, id, priority_idx, d)
demand_reduced[i, priority_idx] = d
end
end
return nothing
Expand Down Expand Up @@ -755,8 +755,8 @@ function save_demands_and_allocations!(
if node_id.type == NodeType.UserDemand
has_demand = true
user_demand_idx = findsorted(user_demand.node_id, node_id)
demand = get_user_demand(p, node_id, priority_idx; reduced = false)
allocated = user_demand.allocated[user_demand_idx][priority_idx]
demand = user_demand.demand[user_demand_idx, priority_idx]
allocated = user_demand.allocated[user_demand_idx, priority_idx]
#NOTE: instantaneous
realized = get_flow(graph, inflow_id(graph, node_id), node_id, 0)

Expand Down
6 changes: 3 additions & 3 deletions core/src/parameter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,11 @@ struct UserDemand <: AbstractParameterNode
node_id::Vector{NodeID}
active::BitVector
realized_bmi::Vector{Float64}
demand::Vector{Float64}
demand_reduced::Vector{Float64}
demand::Matrix{Float64}
demand_reduced::Matrix{Float64}
demand_itp::Vector{Vector{ScalarInterpolation}}
demand_from_timeseries::BitVector
allocated::Vector{Vector{Float64}}
allocated::Matrix{Float64}
return_factor::Vector{Float64}
min_level::Vector{Float64}

Expand Down
15 changes: 7 additions & 8 deletions core/src/read.jl
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ end

function user_demand_static!(
active::BitVector,
demand::Vector{Float64},
demand::Matrix{Float64},
demand_itp::Vector{Vector{ScalarInterpolation}},
return_factor::Vector{Float64},
min_level::Vector{Float64},
Expand All @@ -672,15 +672,15 @@ function user_demand_static!(
for row in group
priority_idx = findsorted(priorities, row.priority)
demand_itp[user_demand_idx][priority_idx].u .= row.demand
demand[(user_demand_idx - 1) * length(priorities) + priority_idx] = row.demand
demand[user_demand_idx, priority_idx] = row.demand
end
end
return nothing
end

function user_demand_time!(
active::BitVector,
demand::Vector{Float64},
demand::Matrix{Float64},
demand_itp::Vector{Vector{ScalarInterpolation}},
demand_from_timeseries::BitVector,
return_factor::Vector{Float64},
Expand Down Expand Up @@ -712,8 +712,7 @@ function user_demand_time!(
:demand;
default_value = 0.0,
)
demand[(user_demand_idx - 1) * length(priorities) + priority_idx] =
demand_p_itp(0.0)
demand[user_demand_idx, priority_idx] = demand_p_itp(0.0)

if is_valid
demand_itp[user_demand_idx][priority_idx] = demand_p_itp
Expand Down Expand Up @@ -741,14 +740,14 @@ function UserDemand(db::DB, config::Config)::UserDemand
n_priority = length(priorities)
active = BitVector(ones(Bool, n_user))
realized_bmi = zeros(n_user)
demand = zeros(n_user * n_priority)
demand_reduced = zeros(n_user * n_priority)
demand = zeros(n_user, n_priority)
demand_reduced = zeros(n_user, n_priority)
trivial_timespan = [nextfloat(-Inf), prevfloat(Inf)]
demand_itp = [
[LinearInterpolation(zeros(2), trivial_timespan) for i in eachindex(priorities)] for j in eachindex(node_ids)
]
demand_from_timeseries = BitVector(zeros(Bool, n_user))
allocated = [fill(Inf, length(priorities)) for id in node_ids]
allocated = fill(Inf, n_user, n_priority)
return_factor = zeros(n_user)
min_level = zeros(n_user)

Expand Down
9 changes: 5 additions & 4 deletions core/src/solve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,13 @@ function formulate_flow!(
storage::AbstractVector,
t::Number,
)::Nothing
(; graph, basin) = p
(; graph, basin, allocation) = p
(;
node_id,
allocated,
active,
demand_itp,
demand,
return_factor,
min_level,
demand_from_timeseries,
Expand All @@ -291,12 +292,12 @@ function formulate_flow!(
# and the current demand.
# If allocation is not optimized then allocated = Inf, so the result is always
# effectively allocated = demand.
for priority_idx in eachindex(allocated[i])
alloc_prio = allocated[i][priority_idx]
for priority_idx in eachindex(allocation.priorities)
alloc_prio = allocated[i, priority_idx]
demand_prio = if demand_from_timeseries[i]
demand_itp[i][priority_idx](t)
else
get_user_demand(p, id, priority_idx; reduced = false)
demand[i, priority_idx]
end
alloc = min(alloc_prio, demand_prio)
q += alloc
Expand Down
44 changes: 0 additions & 44 deletions core/src/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -583,50 +583,6 @@ function is_main_network(allocation_network_id::Int32)::Bool
return allocation_network_id == 1
end

function get_user_demand(
p::Parameters,
node_id::NodeID,
priority_idx::Int;
reduced::Bool = true,
)::Float64
(; user_demand, allocation) = p
(; demand, demand_reduced) = user_demand
user_demand_idx = findsorted(user_demand.node_id, node_id)
n_priorities = length(allocation.priorities)
idx = (user_demand_idx - 1) * n_priorities + priority_idx

if reduced
@assert is_active(allocation) "reduced demand accessed in non-allocation run"
return demand_reduced[idx]
else
return demand[idx]
end
end

function set_user_demand!(
p::Parameters,
node_id::NodeID,
priority_idx::Int,
value::Float64;
reduced::Bool = true,
)::Nothing
(; user_demand, allocation) = p
(; demand, demand_reduced) = user_demand

user_demand_idx = findsorted(user_demand.node_id, node_id)
n_priorities = length(allocation.priorities)
idx = (user_demand_idx - 1) * n_priorities + priority_idx

if reduced
@assert is_active(allocation) "reduced demand accessed in non-allocation run"
demand_reduced[idx] = value
else
demand[idx] = value
end

return nothing
end

function get_all_priorities(db::DB, config::Config)::Vector{Int32}
priorities = Set{Int32}()

Expand Down
20 changes: 7 additions & 13 deletions core/test/allocation_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,10 @@
@test JuMP.value(F[(NodeID(:FlowBoundary, 1), NodeID(:Basin, 2))]) 0.5
@test JuMP.value(F[(NodeID(:Basin, 6), NodeID(:UserDemand, 11))]) 0.0

allocated = p.user_demand.allocated
@test allocated[1] [0.0, 0.5]
@test allocated[2] [4.0, 0.0]
@test allocated[3] [0.0, 2.0]

# Test getting and setting UserDemand demands
(; user_demand) = p
Ribasim.set_user_demand!(p, NodeID(:UserDemand, 11), 2, Float64(π); reduced = false)
@test user_demand.demand[4] π
@test Ribasim.get_user_demand(p, NodeID(:UserDemand, 11), 2; reduced = false) π
(; allocated) = p.user_demand
@test allocated[1, :] [0.0, 0.5]
@test allocated[2, :] [4.0, 0.0]
@test allocated[3, :] [0.0, 2.0]
end

@testitem "Allocation objective: linear absolute" begin
Expand Down Expand Up @@ -197,7 +191,7 @@ end
[(NodeID(:Basin, 10), NodeID(:Pump, 38))]
end

@testitem "allocation with main network optimization problem" begin
@testitem "Allocation with main network optimization problem" begin
using SQLite
using Ribasim: NodeID, OptimizationType
using ComponentArrays: ComponentVector
Expand Down Expand Up @@ -255,8 +249,8 @@ end
[0.00399999999, 0.0, 0.0]
@test subnetwork_allocateds[NodeID(:Basin, 10), NodeID(:Pump, 38)] [0.001, 0.0, 0.0]

@test user_demand.allocated[2] [4.0, 0.0, 0.0]
@test user_demand.allocated[7] [0.001, 0.0, 0.0]
@test user_demand.allocated[2, :] [4.0, 0.0, 0.0]
@test user_demand.allocated[7, :] [0.001, 0.0, 0.0]
end

@testitem "subnetworks with sources" begin
Expand Down

0 comments on commit 17d1fea

Please sign in to comment.