Skip to content

Commit

Permalink
Remove graph from src/constraints/storage.jl (#981)
Browse files Browse the repository at this point in the history
  • Loading branch information
abelsiqueira authored Dec 19, 2024
1 parent 1694227 commit f421d02
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 106 deletions.
254 changes: 149 additions & 105 deletions src/constraints/storage.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ add_storage_constraints!(model, graph,...)
Adds the storage asset constraints to the model.
"""

function add_storage_constraints!(model, variables, constraints, graph)
function add_storage_constraints!(connection, model, variables, constraints, profiles)
var_storage_level_intra_rp = variables[:storage_level_intra_rp]
var_storage_level_inter_rp = variables[:storage_level_inter_rp]

Expand All @@ -16,30 +15,29 @@ function add_storage_constraints!(model, variables, constraints, graph)
# - Balance constraint (using the lowest temporal resolution)
let table_name = :balance_storage_rep_period, cons = constraints[table_name]
var_storage_level = variables[:storage_level_intra_rp].container
indices = _append_storage_data_to_indices(connection, table_name)
attach_constraint!(
model,
cons,
:balance_storage_rep_period,
[
begin
profile_agg = profile_aggregation(
sum,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("inflows", row.rep_period),
profile_agg = _profile_aggregate(
profiles.rep_period,
(row.inflows_profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
sum,
0.0,
)
initial_storage_level = graph[row.asset].initial_storage_level[row.year]
initial_storage_level = row.initial_storage_level

if row.time_block_start == 1 && !ismissing(initial_storage_level)
# Initial storage is a Float64
@constraint(
model,
var_storage_level[row.index] ==
initial_storage_level +
profile_agg * graph[row.asset].storage_inflows[row.year] +
profile_agg * row.storage_inflows +
incoming_flow - outgoing_flow,
base_name = "$table_name[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
)
Expand All @@ -66,69 +64,73 @@ function add_storage_constraints!(model, variables, constraints, graph)
@constraint(
model,
var_storage_level[row.index] ==
previous_level +
profile_agg * graph[row.asset].storage_inflows[row.year] +
incoming_flow - outgoing_flow,
previous_level + profile_agg * row.storage_inflows + incoming_flow -
outgoing_flow,
base_name = "$table_name[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
)
end
end for (row, incoming_flow, outgoing_flow) in
zip(eachrow(cons.indices), cons.expressions[:incoming], cons.expressions[:outgoing])
zip(indices, cons.expressions[:incoming], cons.expressions[:outgoing])
],
)
end

# - Maximum storage level
attach_constraint!(
model,
constraints[:balance_storage_rep_period],
:max_storage_level_intra_rp_limit,
[
@constraint(
model,
var_storage_level_intra_rp.container[row.index]
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("max-storage-level", row.rep_period),
row.time_block_start:row.time_block_end,
1.0,
) * accumulated_energy_capacity[row.year, row.asset],
base_name = "max_storage_level_intra_rp_limit[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(var_storage_level_intra_rp.indices)
],
)
# - Maximum storage level
attach_constraint!(
model,
cons,
:max_storage_level_intra_rp_limit,
[
begin
max_storage_level_agg = _profile_aggregate(
profiles.rep_period,
(row.max_storage_level_profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
)
@constraint(
model,
var_storage_level
max_storage_level_agg * accumulated_energy_capacity[row.year, row.asset],
base_name = "max_storage_level_intra_rp_limit[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
)
end for
(row, var_storage_level) in zip(indices, var_storage_level_intra_rp.container)
],
)

# - Minimum storage level
attach_constraint!(
model,
constraints[:balance_storage_rep_period],
:min_storage_level_intra_rp_limit,
[
@constraint(
model,
var_storage_level_intra_rp.container[row.index]
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("min_storage_level", row.rep_period),
row.time_block_start:row.time_block_end,
0.0,
) * accumulated_energy_capacity[row.year, row.asset],
base_name = "min_storage_level_intra_rp_limit[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(var_storage_level_intra_rp.indices)
],
)
# - Minimum storage level
attach_constraint!(
model,
cons,
:min_storage_level_intra_rp_limit,
[
begin
min_storage_level_agg = _profile_aggregate(
profiles.rep_period,
(row.min_storage_level_profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
0.0,
)
@constraint(
model,
var_storage_level
min_storage_level_agg * accumulated_energy_capacity[row.year, row.asset],
base_name = "min_storage_level_intra_rp_limit[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
)
end for
(row, var_storage_level) in zip(indices, var_storage_level_intra_rp.container)
],
)
end

## INTER-TEMPORAL CONSTRAINTS (between representative periods)

# - Balance constraint (using the lowest temporal resolution)
let table_name = :balance_storage_over_clustered_year, cons = constraints[table_name]
var_storage_level = variables[:storage_level_inter_rp].container
indices = _append_storage_data_to_indices(connection, table_name)

# This assumes an ordering of the time blocks, that is guaranteed inside
# construct_dataframes
Expand All @@ -139,7 +141,7 @@ function add_storage_constraints!(model, variables, constraints, graph)
:balance_storage_over_clustered_year,
[
begin
initial_storage_level = graph[row.asset].initial_storage_level[row.year]
initial_storage_level = row.initial_storage_level

if row.period_block_start == 1 && !ismissing(initial_storage_level)
# Initial storage is a Float64
Expand Down Expand Up @@ -174,58 +176,100 @@ function add_storage_constraints!(model, variables, constraints, graph)
)
end
end for (row, incoming_flow, outgoing_flow, inflows_agg) in zip(
eachrow(cons.indices),
indices,
cons.expressions[:incoming],
cons.expressions[:outgoing],
cons.expressions[:inflows_profile_aggregation],
)
],
)
end

# - Maximum storage level
attach_constraint!(
model,
constraints[:balance_storage_over_clustered_year],
:max_storage_level_inter_rp_limit,
[
@constraint(
model,
var_storage_level_inter_rp.container[row.index]
profile_aggregation(
Statistics.mean,
graph[row.asset].timeframe_profiles,
row.year,
row.year,
"max_storage_level",
row.period_block_start:row.period_block_end,
1.0,
) * accumulated_energy_capacity[row.year, row.asset],
base_name = "max_storage_level_inter_rp_limit[$(row.asset),$(row.year),$(row.period_block_start):$(row.period_block_end)]"
) for row in eachrow(var_storage_level_inter_rp.indices)
],
)
# - Maximum storage level
attach_constraint!(
model,
cons,
:max_storage_level_inter_rp_limit,
[
begin
max_storage_level_agg = _profile_aggregate(
profiles.over_clustered_year,
(row.max_storage_level_profile_name, row.year),
row.period_block_start:row.period_block_end,
Statistics.mean,
1.0,
)
@constraint(
model,
var_storage_level
max_storage_level_agg * accumulated_energy_capacity[row.year, row.asset],
base_name = "max_storage_level_inter_rp_limit[$(row.asset),$(row.year),$(row.period_block_start):$(row.period_block_end)]"
)
end for
(row, var_storage_level) in zip(indices, var_storage_level_inter_rp.container)
],
)

# - Minimum storage level
attach_constraint!(
model,
cons,
:min_storage_level_inter_rp_limit,
[
begin
min_storage_level_agg = _profile_aggregate(
profiles.over_clustered_year,
(row.min_storage_level_profile_name, row.year),
row.period_block_start:row.period_block_end,
Statistics.mean,
0.0,
)
@constraint(
model,
var_storage_level
min_storage_level_agg * accumulated_energy_capacity[row.year, row.asset],
base_name = "min_storage_level_inter_rp_limit[$(row.asset),$(row.year),$(row.period_block_start):$(row.period_block_end)]"
)
end for
(row, var_storage_level) in zip(indices, var_storage_level_inter_rp.container)
],
)
end
end

# - Minimum storage level
attach_constraint!(
model,
constraints[:balance_storage_over_clustered_year],
:min_storage_level_inter_rp_limit,
[
@constraint(
model,
var_storage_level_inter_rp.container[row.index]
profile_aggregation(
Statistics.mean,
graph[row.asset].timeframe_profiles,
row.year,
row.year,
"min_storage_level",
row.period_block_start:row.period_block_end,
0.0,
) * accumulated_energy_capacity[row.year, row.asset],
base_name = "min_storage_level_inter_rp_limit[$(row.asset),$(row.year),$(row.period_block_start):$(row.period_block_end)]"
) for row in eachrow(var_storage_level_inter_rp.indices)
],
function _append_storage_data_to_indices(connection, table_name)
return DuckDB.query(
connection,
"SELECT
cons.*,
asset.capacity,
asset_commission.investment_limit,
asset_milestone.initial_storage_level,
asset_milestone.storage_inflows,
inflows_profile.profile_name AS inflows_profile_name,
max_storage_level_profile.profile_name AS max_storage_level_profile_name,
min_storage_level_profile.profile_name AS min_storage_level_profile_name,
FROM cons_$table_name AS cons
LEFT JOIN asset
ON cons.asset = asset.asset
LEFT JOIN asset_commission
ON cons.asset = asset_commission.asset
AND cons.year = asset_commission.commission_year
LEFT JOIN asset_milestone
ON cons.asset = asset_milestone.asset
AND cons.year = asset_milestone.milestone_year
LEFT OUTER JOIN assets_profiles AS inflows_profile
ON cons.asset = inflows_profile.asset
AND cons.year = inflows_profile.commission_year
AND inflows_profile.profile_type = 'inflows'
LEFT OUTER JOIN assets_profiles AS max_storage_level_profile
ON cons.asset = max_storage_level_profile.asset
AND cons.year = max_storage_level_profile.commission_year
AND max_storage_level_profile.profile_type = 'max_storage_level'
LEFT OUTER JOIN assets_profiles AS min_storage_level_profile
ON cons.asset = min_storage_level_profile.asset
AND cons.year = min_storage_level_profile.commission_year
AND min_storage_level_profile.profile_type = 'min_storage_level'
ORDER BY cons.index
",
)
end
3 changes: 2 additions & 1 deletion src/create-model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,11 @@ function create_model(
)

@timeit to "add_storage_constraints!" add_storage_constraints!(
connection,
model,
variables,
constraints,
graph,
profiles,
)

@timeit to "add_hub_constraints!" add_hub_constraints!(model, constraints)
Expand Down

0 comments on commit f421d02

Please sign in to comment.