Skip to content

Commit 71539c0

Browse files
authored
Modify storage constraint to compute inflows using _profile_aggregate (#1371)
This ensures that all profile aggregation is done through that function, which is a requirement for rolling horizon. Closes #1370
1 parent 8851262 commit 71539c0

File tree

2 files changed

+64
-52
lines changed

2 files changed

+64
-52
lines changed

src/constraints/storage.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ function add_storage_constraints!(connection, model, variables, expressions, con
156156
storage_charging_efficiency = row.storage_charging_efficiency::Float64
157157
storage_discharging_efficiency = row.storage_discharging_efficiency::Float64
158158

159+
inflows_agg = _profile_aggregate(
160+
profiles.over_clustered_year,
161+
(row.inflows_profile_name, row.year),
162+
row.period_block_start:row.period_block_end,
163+
sum,
164+
0.0,
165+
)
166+
159167
if row.period_block_start == 1 && !ismissing(initial_storage_level)
160168
# Initial storage is a Float64
161169
@constraint(
@@ -199,12 +207,8 @@ function add_storage_constraints!(connection, model, variables, expressions, con
199207
base_name = "$table_name[$(row.asset),$(row.year),$(row.period_block_start):$(row.period_block_end)]"
200208
)
201209
end
202-
end for (row, incoming_flow, outgoing_flow, inflows_agg) in zip(
203-
indices,
204-
cons.expressions[:incoming],
205-
cons.expressions[:outgoing],
206-
cons.coefficients[:inflows_profile_aggregation],
207-
)
210+
end for (row, incoming_flow, outgoing_flow) in
211+
zip(indices, cons.expressions[:incoming], cons.expressions[:outgoing])
208212
],
209213
)
210214

src/model-preparation.jl

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ function add_expression_terms_over_clustered_year_constraints!(
276276
cases = [(expr_key = :outgoing, asset_match = :from_asset)]
277277
if is_storage_level
278278
push!(cases, (expr_key = :incoming, asset_match = :to_asset))
279-
attach_coefficient!(cons, :inflows_profile_aggregation, zeros(num_rows))
280279
end
281280

282281
for case in cases
@@ -424,51 +423,6 @@ function add_expression_terms_over_clustered_year_constraints!(
424423
end
425424
end
426425

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

@@ -662,5 +616,59 @@ function prepare_profiles_structure(connection)
662616
)
663617
)
664618

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+
values = Float64[
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+
if length(values) > 0
669+
over_clustered_year[(profile_name, year)] = values
670+
end
671+
end
672+
665673
return ProfileLookup(rep_period, over_clustered_year)
666674
end

0 commit comments

Comments
 (0)