Skip to content

Commit

Permalink
Remove most of graph from src/constraints/capacity.jl (#978)
Browse files Browse the repository at this point in the history
  • Loading branch information
abelsiqueira authored Dec 19, 2024
1 parent 40a7436 commit e6be0a9
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 108 deletions.
249 changes: 142 additions & 107 deletions src/constraints/capacity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ add_capacity_constraints!(model, graph,...)
Adds the capacity constraints for all asset types to the model
"""

function add_capacity_constraints!(model, variables, constraints, graph, sets)
function add_capacity_constraints!(connection, model, variables, constraints, profiles, graph, sets)
## unpack from sets
Acv = sets[:Acv]
Ap = sets[:Ap]
Expand All @@ -32,14 +32,15 @@ function add_capacity_constraints!(model, variables, constraints, graph, sets)
## Expressions used by capacity constraints
# - Create capacity limit for outgoing flows
let table_name = :capacity_outgoing, cons = constraints[table_name]
indices = _append_capacity_data_to_indices(connection, table_name)
attach_expression!(
cons,
:profile_times_capacity,
[
if row.asset decommissionable_assets_using_compact_method
@expression(
model,
graph[row.asset].capacity * sum(
row.capacity * sum(
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
Expand All @@ -58,21 +59,20 @@ function add_capacity_constraints!(model, variables, constraints, graph, sets)
)
)
else
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
)
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
row.time_block_start:row.time_block_end,
1.0,
) *
graph[row.asset].capacity *
availability_agg *
row.capacity *
accumulated_units[accumulated_units_lookup[(row.asset, row.year)]]
)
end for row in eachrow(cons.indices)
end for row in indices
],
)
end
Expand All @@ -81,103 +81,110 @@ function add_capacity_constraints!(model, variables, constraints, graph, sets)
let table_name = :capacity_outgoing_non_investable_storage_with_binary,
cons = constraints[table_name]

indices = _append_capacity_data_to_indices(connection, table_name)

attach_expression!(
cons,
:profile_times_capacity,
[
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
begin
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
) *
(graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year]) *
(1 - is_charging)
) for
(row, is_charging) in zip(eachrow(cons.indices), cons.expressions[:is_charging])
)
@expression(
model,
availability_agg *
row.capacity *
accumulated_initial_units[row.asset, row.year] *
(1 - is_charging)
)
end for (row, is_charging) in zip(indices, cons.expressions[:is_charging])
],
)
end

let table_name = :capacity_outgoing_investable_storage_with_binary,
cons = constraints[table_name]

indices = _append_capacity_data_to_indices(connection, table_name)

attach_expression!(
cons,
:profile_times_capacity_with_investment_variable,
[
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
begin
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
) * (
graph[row.asset].capacity * (
)
@expression(
model,
availability_agg *
row.capacity *
(
accumulated_initial_units[row.asset, row.year] * (1 - is_charging) +
accumulated_investment_units_using_simple_method[row.asset, row.year]
)
)
) for
(row, is_charging) in zip(eachrow(cons.indices), cons.expressions[:is_charging])
end for (row, is_charging) in zip(indices, cons.expressions[:is_charging])
],
)

attach_expression!(
cons,
:profile_times_capacity_with_investment_limit,
[
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
begin
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
) *
(
graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year] +
graph[row.asset].investment_limit[row.year]
) *
(1 - is_charging)
) for
(row, is_charging) in zip(eachrow(cons.indices), cons.expressions[:is_charging])
)
@expression(
model,
availability_agg *
(
row.capacity * accumulated_initial_units[row.asset, row.year] +
row.investment_limit
) *
(1 - is_charging)
)
end for (row, is_charging) in zip(indices, cons.expressions[:is_charging])
],
)
end

# - Create capacity limit for incoming flows
let table_name = :capacity_incoming, cons = constraints[table_name]
indices = _append_capacity_data_to_indices(connection, table_name)
attach_expression!(
cons,
:profile_times_capacity,
[
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
begin
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
) *
graph[row.asset].capacity *
accumulated_units[accumulated_units_lookup[(row.asset, row.year)]]
) for row in eachrow(cons.indices)
)
@expression(
model,
availability_agg *
row.capacity *
accumulated_units[accumulated_units_lookup[(row.asset, row.year)]]
)
end for row in indices
],
)
end
Expand All @@ -186,79 +193,84 @@ function add_capacity_constraints!(model, variables, constraints, graph, sets)
let table_name = :capacity_incoming_non_investable_storage_with_binary,
cons = constraints[table_name]

indices = _append_capacity_data_to_indices(connection, table_name)

attach_expression!(
cons,
:profile_times_capacity,
[
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
begin
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
) *
(graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year]) *
is_charging
) for
(row, is_charging) in zip(eachrow(cons.indices), cons.expressions[:is_charging])
)
@expression(
model,
availability_agg *
row.capacity *
accumulated_initial_units[row.asset, row.year] *
is_charging
)
end for (row, is_charging) in zip(indices, cons.expressions[:is_charging])
],
)
end

let table_name = :capacity_incoming_investable_storage_with_binary,
cons = constraints[table_name]

indices = _append_capacity_data_to_indices(connection, table_name)

attach_expression!(
cons,
:profile_times_capacity_with_investment_variable,
[
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
begin
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
) * (
graph[row.asset].capacity * (
)
@expression(
model,
availability_agg *
row.capacity *
(
accumulated_initial_units[row.asset, row.year] * is_charging +
accumulated_investment_units_using_simple_method[row.asset, row.year]
)
)
) for
(row, is_charging) in zip(eachrow(cons.indices), cons.expressions[:is_charging])
end for (row, is_charging) in zip(indices, cons.expressions[:is_charging])
],
)

attach_expression!(
cons,
:profile_times_capacity_with_investment_limit,
[
@expression(
model,
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("availability", row.rep_period),
begin
availability_agg = _profile_aggregate(
profiles.rep_period,
(row.profile_name, row.year, row.rep_period),
row.time_block_start:row.time_block_end,
Statistics.mean,
1.0,
) *
(
graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year] +
graph[row.asset].investment_limit[row.year]
) *
is_charging
) for
(row, is_charging) in zip(eachrow(cons.indices), cons.expressions[:is_charging])
)
@expression(
model,
availability_agg *
(
row.capacity * accumulated_initial_units[row.asset, row.year] +
row.investment_limit
) *
is_charging
)
end for (row, is_charging) in zip(indices, cons.expressions[:is_charging])
],
)
end
Expand Down Expand Up @@ -359,3 +371,26 @@ function add_capacity_constraints!(model, variables, constraints, graph, sets)
)
end
end

function _append_capacity_data_to_indices(connection, table_name)
return DuckDB.query(
connection,
"SELECT
cons.*,
asset.capacity,
asset_commission.investment_limit,
assets_profiles.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 OUTER JOIN assets_profiles
ON cons.asset = assets_profiles.asset
AND cons.year = assets_profiles.commission_year
AND assets_profiles.profile_type = 'availability'
ORDER BY cons.index
",
)
end
2 changes: 2 additions & 0 deletions src/create-model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,11 @@ function create_model(
# TODO: Pass sets instead of the explicit values
## Constraints
@timeit to "add_capacity_constraints!" add_capacity_constraints!(
connection,
model,
variables,
constraints,
profiles,
graph,
sets,
)
Expand Down
2 changes: 1 addition & 1 deletion src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function profile_aggregation(agg, profiles, year, commission_year, key, block, d
end

function _profile_aggregate(profiles, tuple_key, time_block, agg_function, default_value)
if !haskey(profiles, tuple_key)
if any(ismissing, tuple_key) || !haskey(profiles, tuple_key)
return agg_function(Iterators.repeated(default_value, length(time_block)))
end
profile_value = profiles[tuple_key]
Expand Down

0 comments on commit e6be0a9

Please sign in to comment.