Skip to content

Commit

Permalink
Merge pull request #56 from daschw/delay
Browse files Browse the repository at this point in the history
Support "non-integer" delay for Connections
  • Loading branch information
daschw authored Feb 3, 2025
2 parents ed101b5 + 86b8f05 commit f356329
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 23 deletions.
44 changes: 44 additions & 0 deletions assets/examples/50_delayed_connections.iesopt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
config:
general:
version:
core: 2.4.0
optimization:
problem_type: LP
solver:
name: highs
snapshots:
count: 4
weights: 0.25
results:
enabled: true
memory_only: true

carriers:
water: {}

components:
upper:
type: Node
carrier: water
lower:
type: Node
carrier: water
river:
type: Connection
node_from: upper
node_to: lower
delay: 1 // 3
inflow:
type: Profile
carrier: water
node_to: upper
mode: create
outflow:
type: Profile
carrier: water
node_from: lower
value:
- 1.0
- 2.0
- 1.5
- 0.5
9 changes: 0 additions & 9 deletions src/core/connection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,6 @@ function _isvalid(connection::Connection)
@critical "Setting <delay> for Connection currently requires equal Snapshot weights" connection =
connection.name
end

for t in get_T(connection.model)
delay = access(connection.delay, t, Float64)
if !isinteger(delay / sw[1])
# TODO: This is a temporary solution, implement and remove this.
@critical "Setting <delay> for Connection currently requires integer delays (thought in Snapshots)" connection =
connection.name
end
end
end

return true
Expand Down
41 changes: 27 additions & 14 deletions src/core/connection/var_flow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,35 @@ function _connection_var_flow!(connection::Connection)
has_delay = !_isempty(connection.delay)

@inbounds @simd for t in get_T(model)
t0 = t
if !has_delay
t1 = t
delayed_snapshots, delayed_weights = if !has_delay
(t,), (1.0,)
else
t1 = (Int64(t + access(connection.delay, t)::Float64 / Δ) - 1) % get_T(model)[end] + 1
Δi, r = divrem(access(connection.delay, t), Δ)
mod1.(t .+ Int(Δi) .+ (0, 1), last(get_T(model))), (1 - r / Δ, r / Δ)
end

if connection.loss_mode == :to
JuMP.add_to_expression!(connection.exp.in[t0], cvf[t0], 1.0)
JuMP.add_to_expression!(connection.exp.out[t1], cvf[t0], (1.0 - access(loss, t0)::Float64))
elseif connection.loss_mode == :from
JuMP.add_to_expression!(connection.exp.in[t0], cvf[t0], 1.0 / (1.0 - access(loss, t0)::Float64))
JuMP.add_to_expression!(connection.exp.out[t1], cvf[t0], 1.0)
elseif connection.loss_mode == :split
JuMP.add_to_expression!(connection.exp.in[t0], cvf[t0], 1.0 / sqrt(1.0 - access(loss, t0)::Float64))
JuMP.add_to_expression!(connection.exp.out[t1], cvf[t0], sqrt(1.0 - access(loss, t0)::Float64))
if connection.loss_mode === :to
JuMP.add_to_expression!(connection.exp.in[t], cvf[t], 1.0)
for (i, td) in enumerate(delayed_snapshots)
JuMP.add_to_expression!(
connection.exp.out[td],
cvf[t],
delayed_weights[i] * (1.0 - access(loss, t)::Float64),
)
end
elseif connection.loss_mode === :from
JuMP.add_to_expression!(connection.exp.in[t], cvf[t], 1.0 / (1.0 - access(loss, t)::Float64))
for (i, td) in enumerate(delayed_snapshots)
JuMP.add_to_expression!(connection.exp.out[td], cvf[t], delayed_weights[i])
end
elseif connection.loss_mode === :split
JuMP.add_to_expression!(connection.exp.in[t], cvf[t], 1.0 / sqrt(1.0 - access(loss, t)::Float64))
for (i, td) in enumerate(delayed_snapshots)
JuMP.add_to_expression!(
connection.exp.out[td],
cvf[t],
delayed_weights[i] * sqrt(1.0 - access(loss, t)::Float64),
)
end
end
end

Expand Down
14 changes: 14 additions & 0 deletions test/src/examples.jl
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,17 @@ end
).input.files["data"],
) == (8760, 8)
end

@testitem "50_delayed_connections" tags = [:examples] setup = [TestExampleModule] begin
model = TestExampleModule.check(; obj=0.0)

river = internal(model).results.components["river"]
weight = 0.25
delay = 1 // 3
d, r = divrem(delay, weight)
for i in get_T(model)
first_inflow = r / weight * river.exp.in[mod1(i - Int(d) - 1, end)]
second_inflow = (1 - r / weight) * river.exp.in[mod1(i - Int(d), end)]
@test river.exp.out[i] == first_inflow + second_inflow
end
end

0 comments on commit f356329

Please sign in to comment.