From ef156336d8b5ffd5db5f44e21bb1befee933f98c Mon Sep 17 00:00:00 2001 From: Diego Alejandro Tejada Arango <12887482+datejada@users.noreply.github.com> Date: Wed, 25 Sep 2024 13:22:42 +0200 Subject: [PATCH] Update storage binary constraints with multi-year investment (#824) --- src/constraints/capacity.jl | 13 +++---- src/create-model.jl | 72 ++++++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/constraints/capacity.jl b/src/constraints/capacity.jl index edbe305e..aad14c62 100644 --- a/src/constraints/capacity.jl +++ b/src/constraints/capacity.jl @@ -20,6 +20,7 @@ function add_capacity_constraints!( accumulated_set_using_compact_method_lookup, Asb, accumulated_initial_units, + accumulated_investment_units_using_simple_method, accumulated_units, accumulated_units_compact_method, accumulated_set_using_compact_method, @@ -124,8 +125,8 @@ function add_capacity_constraints!( 1.0, ) * ( graph[row.asset].capacity * ( - accumulated_units[accumulated_units_lookup[(row.asset, row.year)]] - - accumulated_initial_units[row.asset, row.year] * row.is_charging + accumulated_initial_units[row.asset, row.year] * (1 - row.is_charging) + + accumulated_investment_units_using_simple_method[row.asset, row.year] ) ) ) @@ -205,8 +206,8 @@ function add_capacity_constraints!( 1.0, ) * ( graph[row.asset].capacity * ( - accumulated_units[accumulated_units_lookup[(row.asset, row.year)]] - - accumulated_initial_units[row.asset, row.year] * (1 - row.is_charging) + accumulated_initial_units[row.asset, row.year] * row.is_charging + + accumulated_investment_units_using_simple_method[row.asset, row.year] ) ) ) @@ -222,7 +223,7 @@ function add_capacity_constraints!( assets_profile_times_capacity_out[row.index], base_name = "max_output_flows_limit[$(row.asset),$(row.year),$(row.rep_period),$(row.timesteps_block)]" ) for row in eachrow(dataframes[:highest_out]) if - row.asset ∉ Asb[row.year] && outgoing_flow_highest_out_resolution[row.index] != 0 + outgoing_flow_highest_out_resolution[row.index] != 0 ] # - Maximum input flows limit @@ -233,7 +234,7 @@ function add_capacity_constraints!( assets_profile_times_capacity_in[row.index], base_name = "max_input_flows_limit[$(row.asset),$(row.rep_period),$(row.timesteps_block)]" ) for row in eachrow(dataframes[:highest_in]) if - row.asset ∉ Asb[row.year] && incoming_flow_highest_in_resolution[row.index] != 0 + incoming_flow_highest_in_resolution[row.index] != 0 ] ## Capacity limit constraints (using the highest resolution) for storage assets using binary to avoid charging and discharging at the same time diff --git a/src/create-model.jl b/src/create-model.jl index f2ff0d51..bdd3fcf8 100644 --- a/src/create-model.jl +++ b/src/create-model.jl @@ -1018,18 +1018,52 @@ function create_model( accumulated_initial_units[a in A, y in Y], sum(values(graph[a].initial_units[y])) ) - @expression( + + ### Expressions for multi-year investment simple method + accumulated_investment_units_using_simple_method = @expression( model, - accumulated_units_simple_method[y ∈ Y, a ∈ decommissionable_assets_using_simple_method], - accumulated_initial_units[a, y] + sum( + accumulated_investment_units_using_simple_method[ + a ∈ decommissionable_assets_using_simple_method, + y in Y, + ], + sum( assets_investment[yy, a] for yy in Y if a ∈ investable_assets_using_simple_method[yy] && starting_year_using_simple_method[(y, a)] ≤ yy ≤ y - ) - sum( + ) + ) + @expression( + model, + accumulated_decommission_units_using_simple_method[ + a ∈ decommissionable_assets_using_simple_method, + y in Y, + ], + sum( assets_decommission_simple_method[yy, a] for yy in Y if starting_year_using_simple_method[(y, a)] ≤ yy ≤ y ) ) + @expression( + model, + accumulated_units_simple_method[a ∈ decommissionable_assets_using_simple_method, y ∈ Y], + accumulated_initial_units[a, y] + + accumulated_investment_units_using_simple_method[a, y] - + accumulated_decommission_units_using_simple_method[a, y] + ) + + ### Expressions for multi-year investment compact method + @expression( + model, + accumulated_decommission_units_using_compact_method[( + a, + y, + v, + ) in accumulated_set_using_compact_method], + sum( + assets_decommission_compact_method[(a, yy, v)] for + yy in Y if v ≤ yy ≤ y && (a, yy, v) in decommission_set_using_compact_method + ) + ) cond1(a, y, v) = a in existing_assets_by_year_using_compact_method[v] cond2(a, y, v) = v in Y && a in investable_assets_using_compact_method[v] accumulated_units_compact_method = @@ -1037,40 +1071,34 @@ function create_model( if cond1(a, y, v) && cond2(a, y, v) @expression( model, - graph[a].initial_units[y][v] + assets_investment[v, a] - sum( - assets_decommission_compact_method[(a, yy, v)] for yy in Y if - v ≤ yy ≤ y && (a, yy, v) in decommission_set_using_compact_method - ) + graph[a].initial_units[y][v] + assets_investment[v, a] - + accumulated_decommission_units_using_compact_method[(a, y, v)] ) elseif cond1(a, y, v) && !cond2(a, y, v) @expression( model, - graph[a].initial_units[y][v] - sum( - assets_decommission_compact_method[(a, yy, v)] for yy in Y if - v ≤ yy ≤ y && (a, yy, v) in decommission_set_using_compact_method - ) + graph[a].initial_units[y][v] - + accumulated_decommission_units_using_compact_method[(a, y, v)] ) elseif !cond1(a, y, v) && cond2(a, y, v) @expression( model, - assets_investment[v, a] - sum( - assets_decommission_compact_method[(a, yy, v)] for yy in Y if - v ≤ yy ≤ y && (a, yy, v) in decommission_set_using_compact_method - ) + assets_investment[v, a] - + accumulated_decommission_units_using_compact_method[(a, y, v)] ) else @expression(model, 0.0) end for (a, y, v) in accumulated_set_using_compact_method ] - # Create a lookup set for accumulated units + ### Expressions for multi-year investment for accumulated units no matter the method accumulated_units_lookup = Dict((a, y) => idx for (idx, (a, y)) in enumerate((aa, yy) for aa in A for yy in Y)) accumulated_units = model[:accumulated_units] = JuMP.AffExpr[ if a in decommissionable_assets_using_simple_method - @expression(model, accumulated_units_simple_method[y, a]) + @expression(model, accumulated_units_simple_method[a, y]) elseif a in decommissionable_assets_using_compact_method @expression( model, @@ -1119,7 +1147,10 @@ function create_model( if a ∈ Ai[y] ∩ decommissionable_assets_using_simple_method graph[a].energy_to_power_ratio[y] * graph[a].capacity * - (accumulated_units_simple_method[y, a] - accumulated_initial_units[a, y]) + ( + accumulated_investment_units_using_simple_method[a, y] - + accumulated_decommission_units_using_simple_method[a, y] + ) else 0.0 end @@ -1178,7 +1209,7 @@ function create_model( assets_fixed_cost = @expression( model, sum( - graph[a].fixed_cost[y] * graph[a].capacity * accumulated_units_simple_method[y, a] for y in Y for + graph[a].fixed_cost[y] * graph[a].capacity * accumulated_units_simple_method[a, y] for y in Y for a in decommissionable_assets_using_simple_method ) + sum( graph[a].fixed_cost[v] * graph[a].capacity * accm for (accm, (a, y, v)) in @@ -1279,6 +1310,7 @@ function create_model( accumulated_set_using_compact_method_lookup, Asb, accumulated_initial_units, + accumulated_investment_units_using_simple_method, accumulated_units, accumulated_units_compact_method, accumulated_set_using_compact_method,