Skip to content

Commit a20119b

Browse files
committed
[WIP] Rolling horizon
1 parent 404ebbb commit a20119b

File tree

5 files changed

+92
-83
lines changed

5 files changed

+92
-83
lines changed

src/constraints/storage.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ function add_storage_constraints!(
180180
storage_charging_efficiency = row.storage_charging_efficiency::Float64
181181
storage_discharging_efficiency = row.storage_discharging_efficiency::Float64
182182

183+
inflows_agg = _profile_aggregate(
184+
profiles.over_clustered_year,
185+
(row.inflows_profile_name, row.year),
186+
row.period_block_start:row.period_block_end,
187+
sum,
188+
0.0,
189+
)
190+
183191
if row.period_block_start == 1 && !ismissing(initial_storage_level)
184192
# Initial storage is a Float64
185193
@constraint(
@@ -223,12 +231,8 @@ function add_storage_constraints!(
223231
base_name = "$table_name[$(row.asset),$(row.year),$(row.period_block_start):$(row.period_block_end)]"
224232
)
225233
end
226-
end for (row, incoming_flow, outgoing_flow, inflows_agg) in zip(
227-
indices,
228-
cons.expressions[:incoming],
229-
cons.expressions[:outgoing],
230-
cons.coefficients[:inflows_profile_aggregation],
231-
)
234+
end for (row, incoming_flow, outgoing_flow) in
235+
zip(indices, cons.expressions[:incoming], cons.expressions[:outgoing])
232236
],
233237
)
234238

src/create-model.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ function create_model(
7878

7979
## Optimizer
8080
optimizer_with_attributes = if rolling_horizon
81-
# TODO: Fix this
82-
() -> POI.Optimizer(HiGHS.Optimizer())
81+
JuMP.optimizer_with_attributes(() -> POI.Optimizer(optimizer()), optimizer_parameters...)
8382
else
8483
JuMP.optimizer_with_attributes(optimizer, optimizer_parameters...)
8584
end

src/model-preparation.jl

Lines changed: 75 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -424,52 +424,6 @@ function add_expression_terms_over_clustered_year_constraints!(
424424
end
425425
end
426426

427-
# Completely separate calculation for inflows_profile_aggregation
428-
if is_storage_level
429-
# TODO: Fix this for rolling horizon
430-
cons.coefficients[:inflows_profile_aggregation] .= [
431-
row.inflows_agg for row in DuckDB.query(
432-
connection,
433-
"
434-
SELECT
435-
cons.id,
436-
ANY_VALUE(cons.asset) AS asset,
437-
ANY_VALUE(cons.year) AS year,
438-
SUM(COALESCE(other.inflows_agg, 0.0)) AS inflows_agg,
439-
FROM cons_balance_storage_over_clustered_year AS cons
440-
LEFT JOIN (
441-
SELECT
442-
assets_profiles.asset AS asset,
443-
assets_profiles.commission_year AS year,
444-
rpmap.period AS period,
445-
SUM(COALESCE(profiles.value, 0.0) * rpmap.weight * asset_milestone.storage_inflows) AS inflows_agg,
446-
FROM assets_profiles
447-
LEFT OUTER JOIN profiles_rep_periods AS profiles
448-
ON assets_profiles.profile_name=profiles.profile_name
449-
AND assets_profiles.profile_type='inflows'
450-
LEFT JOIN rep_periods_mapping AS rpmap
451-
ON rpmap.year = assets_profiles.commission_year
452-
AND rpmap.year = profiles.year -- because milestone_year = commission_year
453-
AND rpmap.rep_period = profiles.rep_period
454-
LEFT JOIN asset_milestone
455-
ON asset_milestone.asset = assets_profiles.asset
456-
AND asset_milestone.milestone_year = assets_profiles.commission_year
457-
GROUP BY
458-
assets_profiles.asset,
459-
assets_profiles.commission_year,
460-
rpmap.period
461-
) AS other
462-
ON cons.asset = other.asset
463-
AND cons.year = other.year
464-
AND cons.period_block_start <= other.period
465-
AND cons.period_block_end >= other.period
466-
GROUP BY cons.id
467-
ORDER BY cons.id
468-
",
469-
)
470-
]
471-
end
472-
473427
return
474428
end
475429

@@ -618,21 +572,18 @@ end
618572
function prepare_profiles_structure(connection)
619573
# Independent of being rolling horizon or not, these are complete
620574
rep_period = Dict(
621-
(row.profile_name, row.year, row.rep_period) => ProfileWithRollingHorizon(
622-
[
623-
row.value for row in DuckDB.query(
624-
connection,
625-
"SELECT profile.value
626-
FROM profiles_rep_periods AS profile
627-
WHERE
628-
profile.profile_name = '$(row.profile_name)'
629-
AND profile.year = $(row.year)
630-
AND profile.rep_period = $(row.rep_period)
631-
",
632-
)
633-
],
634-
JuMP.VariableRef[],
635-
) for row in DuckDB.query(
575+
(row.profile_name, row.year, row.rep_period) => ProfileWithRollingHorizon([
576+
row.value for row in DuckDB.query(
577+
connection,
578+
"SELECT profile.value
579+
FROM profiles_rep_periods AS profile
580+
WHERE
581+
profile.profile_name = '$(row.profile_name)'
582+
AND profile.year = $(row.year)
583+
AND profile.rep_period = $(row.rep_period)
584+
",
585+
)
586+
]) for row in DuckDB.query(
636587
connection,
637588
"SELECT DISTINCT
638589
profiles.profile_name,
@@ -644,20 +595,17 @@ function prepare_profiles_structure(connection)
644595
)
645596

646597
over_clustered_year = Dict(
647-
(row.profile_name, row.year) => ProfileWithRollingHorizon(
648-
[
649-
row.value for row in DuckDB.query(
650-
connection,
651-
"SELECT profile.value
652-
FROM profiles_timeframe AS profile
653-
WHERE
654-
profile.profile_name = '$(row.profile_name)'
655-
AND profile.year = $(row.year)
656-
",
657-
)
658-
],
659-
JuMP.VariableRef[],
660-
) for row in DuckDB.query(
598+
(row.profile_name, row.year) => ProfileWithRollingHorizon([
599+
row.value for row in DuckDB.query(
600+
connection,
601+
"SELECT profile.value
602+
FROM profiles_timeframe AS profile
603+
WHERE
604+
profile.profile_name = '$(row.profile_name)'
605+
AND profile.year = $(row.year)
606+
",
607+
)
608+
]) for row in DuckDB.query(
661609
connection,
662610
"SELECT DISTINCT
663611
profiles.profile_name,
@@ -667,5 +615,57 @@ function prepare_profiles_structure(connection)
667615
)
668616
)
669617

618+
# TODO: Decide where to put this (leave here?)
619+
# Creating over_clustered_year profiles of inflows using the inflows
620+
# profiles of rep_periods and asset_milestone.storage_inflows
621+
for row in DuckDB.query(
622+
connection,
623+
"""
624+
SELECT
625+
assets_profiles.asset,
626+
assets_profiles.profile_name,
627+
assets_profiles.commission_year,
628+
asset_milestone.storage_inflows
629+
FROM assets_profiles
630+
LEFT JOIN asset
631+
ON assets_profiles.asset = asset.asset
632+
LEFT JOIN asset_milestone
633+
ON assets_profiles.asset = asset_milestone.asset
634+
AND assets_profiles.commission_year = asset_milestone.milestone_year -- commission_year = milestone_year
635+
WHERE assets_profiles.profile_type = 'inflows' AND asset.type = 'storage' AND asset.is_seasonal
636+
""",
637+
)
638+
asset = row.asset
639+
profile_name = row.profile_name
640+
year = row.commission_year
641+
storage_inflows = row.storage_inflows
642+
over_clustered_year[(profile_name, year)] = ProfileWithRollingHorizon([
643+
row.value for row in DuckDB.query(
644+
connection,
645+
"""
646+
WITH cte_profile_rp AS (
647+
SELECT
648+
'$asset' AS asset,
649+
$year AS year,
650+
profiles_rep_periods.rep_period,
651+
profiles_rep_periods.timestep,
652+
profiles_rep_periods.value,
653+
FROM profiles_rep_periods
654+
WHERE profile_name = '$profile_name' AND year = $year
655+
)
656+
SELECT
657+
rp_map.period,
658+
SUM(cte_profile_rp.value * rp_map.weight * $storage_inflows) AS value,
659+
FROM cte_profile_rp
660+
LEFT JOIN rep_periods_mapping AS rp_map
661+
ON cte_profile_rp.year = rp_map.year
662+
AND cte_profile_rp.rep_period = rp_map.rep_period
663+
GROUP BY rp_map.period
664+
ORDER BY rp_map.period
665+
""",
666+
)
667+
])
668+
end
669+
670670
return ProfileLookup(rep_period, over_clustered_year)
671671
end

src/structures.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ end
233233
mutable struct ProfileWithRollingHorizon
234234
values::Vector{Float64}
235235
rolling_horizon_variables::Vector{JuMP.VariableRef}
236+
237+
ProfileWithRollingHorizon(values::Vector{Float64}) = new(values, JuMP.VariableRef[])
236238
end
237239

238240
"""

test/test-case-studies.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ end
153153
TulipaEnergyModel.populate_with_defaults!(connection)
154154
energy_problem = TulipaEnergyModel.run_scenario(connection; show_log = false)
155155
@test energy_problem.objective_value 10000.0 atol = 1e-5
156+
# Rolling horizon
157+
energy_problem =
158+
TulipaEnergyModel.run_rolling_horizon(connection, 24 * 7, 48 * 7; show_log = false)
159+
# @test energy_problem.objective_value ≈ 10000.0 atol = 1e-5
156160
end
157161

158162
@testitem "Infeasible Case Study" setup = [CommonSetup] tags = [:case_study, :integration, :slow] begin

0 commit comments

Comments
 (0)