From b53902d559b087e4e03ca4996881b95593d66271 Mon Sep 17 00:00:00 2001 From: Aleksandr Kazachkov Date: Thu, 22 Jul 2021 09:33:15 -0400 Subject: [PATCH] Ran JuliaFormatter --- src/instance/read.jl | 2 +- .../formulations/DamKucRajAta2016/ramp.jl | 2 +- src/model/formulations/Gar1962/status.jl | 13 +++- .../formulations/GenMorRam2017/startstop.jl | 58 +++++++++------ .../formulations/KnuOstWat2018/scosts.jl | 73 ++++++++++--------- .../formulations/MorLatRam2013/scosts.jl | 6 +- .../formulations/MorLatRam2013/startstop.jl | 41 ++++++----- src/model/formulations/NowRom2000/scosts.jl | 2 +- src/model/formulations/OstAnjVan2012/ramp.jl | 28 +++---- src/model/formulations/base/system.jl | 18 +++-- src/model/formulations/base/unit.jl | 38 ++++++---- 11 files changed, 158 insertions(+), 123 deletions(-) diff --git a/src/instance/read.jl b/src/instance/read.jl index 2a28be0..84e76c2 100644 --- a/src/instance/read.jl +++ b/src/instance/read.jl @@ -100,7 +100,7 @@ function _from_json(json; repair = true) ) shortfall_penalty = timeseries( json["Parameters"]["Reserve shortfall penalty (\$/MW)"], - default=[0. for t in 1:T] + default = [0.0 for t in 1:T], ) # Read buses diff --git a/src/model/formulations/DamKucRajAta2016/ramp.jl b/src/model/formulations/DamKucRajAta2016/ramp.jl index ab7e4af..5fc221e 100644 --- a/src/model/formulations/DamKucRajAta2016/ramp.jl +++ b/src/model/formulations/DamKucRajAta2016/ramp.jl @@ -35,7 +35,7 @@ function _add_ramp_eqs!( RESERVES_WHEN_RAMP_DOWN = true RESERVES_WHEN_SHUT_DOWN = true is_initially_on = _is_initially_on(g) - + # The following are the same for generator g across all time periods SU = g.startup_limit # startup rate SD = g.shutdown_limit # shutdown rate diff --git a/src/model/formulations/Gar1962/status.jl b/src/model/formulations/Gar1962/status.jl index 9ba9da1..2224f3f 100644 --- a/src/model/formulations/Gar1962/status.jl +++ b/src/model/formulations/Gar1962/status.jl @@ -12,7 +12,7 @@ function _add_status_vars!( model::JuMP.Model, g::Unit, formulation_status_vars::Gar1962.StatusVars, - ALWAYS_CREATE_VARS = false + ALWAYS_CREATE_VARS = false, )::Nothing is_on = _init(model, :is_on) switch_on = _init(model, :switch_on) @@ -38,12 +38,16 @@ function _add_status_vars!( end end - if g.must_run[t] + if g.must_run[t] # If the generator _must_ run, then it is obviously on and cannot be switched off # In the first time period, force unit to switch on if was off before # Otherwise, unit is on, and will never turn off, so will never need to turn on fix(is_on[g.name, t], 1.0; force = true) - fix(switch_on[g.name, t], (t == 1 ? 1.0 - _is_initially_on(g) : 0.0); force = true) + fix( + switch_on[g.name, t], + (t == 1 ? 1.0 - _is_initially_on(g) : 0.0); + force = true, + ) fix(switch_off[g.name, t], 0.0; force = true) end else @@ -57,7 +61,8 @@ function _add_status_vars!( end if g.must_run[t] is_on[g.name, t] = 1.0 - switch_on[g.name, t] = (t == 1 ? 1.0 - _is_initially_on(g) : 0.0) + switch_on[g.name, t] = + (t == 1 ? 1.0 - _is_initially_on(g) : 0.0) switch_off[g.name, t] = 0.0 end end # check if ALWAYS_CREATE_VARS diff --git a/src/model/formulations/GenMorRam2017/startstop.jl b/src/model/formulations/GenMorRam2017/startstop.jl index 2c39be5..7a7ac31 100644 --- a/src/model/formulations/GenMorRam2017/startstop.jl +++ b/src/model/formulations/GenMorRam2017/startstop.jl @@ -2,7 +2,6 @@ # Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. # Released under the modified BSD license. See COPYING.md for more details. - """ _add_startup_shutdown_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing @@ -45,41 +44,52 @@ function _add_startup_shutdown_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing if g.initial_power > g.shutdown_limit #eqs.shutdown_limit[gi, 0] = @constraint(mip, vars.switch_off[gi, 1] <= 0) - fix(switch_off[gi, 1], 0.; force = true) + fix(switch_off[gi, 1], 0.0; force = true) end - for t = 1:T + for t in 1:T ## 2020-10-09 amk: added eqn (20) and check of g.min_uptime # Not present in (23) in Kneueven et al. if g.min_uptime > 1 # Equation (20) in Kneuven et al. (2020) - eqs.startstop_limit[gi,t] = - @constraint(model, - prod_above[gi, t] + reserve[gi, t] - <= (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - - max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t] - - (t < T ? max(0, g.max_power[t] - g.shutdown_limit) * switch_off[gi, t+1] : 0.) - ) + eqs.startstop_limit[gi, t] = @constraint( + model, + prod_above[gi, t] + reserve[gi, t] <= + (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - + max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t] - ( + t < T ? + max(0, g.max_power[t] - g.shutdown_limit) * + switch_off[gi, t+1] : 0.0 + ) + ) else ## Startup limits # Equation (23a) in Kneuven et al. (2020) - eqs.startup_limit[gi, t] = - @constraint(model, - prod_above[gi, t] + reserve[gi, t] - <= (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - - max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t] - - (t < T ? max(0, g.startup_limit - g.shutdown_limit) * switch_off[gi, t+1] : 0.) - ) - + eqs.startup_limit[gi, t] = @constraint( + model, + prod_above[gi, t] + reserve[gi, t] <= + (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - + max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t] - ( + t < T ? + max(0, g.startup_limit - g.shutdown_limit) * + switch_off[gi, t+1] : 0.0 + ) + ) + ## Shutdown limits if t < T # Equation (23b) in Kneuven et al. (2020) - eqs.shutdown_limit[gi, t] = - @constraint(model, - prod_above[gi, t] + reserve[gi, t] - <= (g.max_power[t] - g.min_power[t]) * xis_on[gi, t] - - (t < T ? max(0, g.max_power[t] - g.shutdown_limit) * switch_off[gi, t+1] : 0.) - - max(0, g.shutdown_limit - g.startup_limit) * switch_on[gi, t]) + eqs.shutdown_limit[gi, t] = @constraint( + model, + prod_above[gi, t] + reserve[gi, t] <= + (g.max_power[t] - g.min_power[t]) * xis_on[gi, t] - ( + t < T ? + max(0, g.max_power[t] - g.shutdown_limit) * + switch_off[gi, t+1] : 0.0 + ) - + max(0, g.shutdown_limit - g.startup_limit) * + switch_on[gi, t] + ) end end # check if g.min_uptime > 1 end # loop over time diff --git a/src/model/formulations/KnuOstWat2018/scosts.jl b/src/model/formulations/KnuOstWat2018/scosts.jl index c875105..570e7ea 100644 --- a/src/model/formulations/KnuOstWat2018/scosts.jl +++ b/src/model/formulations/KnuOstWat2018/scosts.jl @@ -61,56 +61,63 @@ function _add_startup_cost_eqs!( # Equation (59) in Kneuven et al. (2020) # Relate downtime_arc with switch_on # "switch_on[g,t] >= x_g(t',t) for all t' \in [t-TC+1, t-DT]" - eq_startup_at_t[gn, t] = - @constraint(model, - switch_on[gn, t] - >= sum(downtime_arc[gn,tmp_t,t] - for tmp_t in t-TC+1:t-DT if tmp_t >= 1) - ) + eq_startup_at_t[gn, t] = @constraint( + model, + switch_on[gn, t] >= sum( + downtime_arc[gn, tmp_t, t] for + tmp_t in t-TC+1:t-DT if tmp_t >= 1 + ) + ) # Equation (60) in Kneuven et al. (2020) # "switch_off[g,t] >= x_g(t,t') for all t' \in [t+DT, t+TC-1]" - eqs.shutdown_at_t[gn, t] = - @constraint(model, - switch_off[gn, t] - >= sum(downtime_arc[gn,t,tmp_t] - for tmp_t in t+DT:t+TC-1 if tmp_t <= T) - ) + eqs.shutdown_at_t[gn, t] = @constraint( + model, + switch_off[gn, t] >= sum( + downtime_arc[gn, t, tmp_t] for + tmp_t in t+DT:t+TC-1 if tmp_t <= T + ) + ) # Objective function terms for start-up costs # Equation (61) in Kneuven et al. (2020) default_category = S if initial_time_shutdown > 0 && t + initial_time_shutdown - 1 < TC for s in 1:S-1 - # If off for x periods before, then belongs to category s - # if -x+1 in [t-delay[s+1]+1,t-delay[s]] - # or, equivalently, if total time off in [delay[s], delay[s+1]-1] - # where total time off = t - 1 + initial_time_shutdown - # (the -1 because not off for current time period) - if t + initial_time_shutdown - 1 < g.startup_categories[s+1].delay - default_category = s - break # does not go into next category - end + # If off for x periods before, then belongs to category s + # if -x+1 in [t-delay[s+1]+1,t-delay[s]] + # or, equivalently, if total time off in [delay[s], delay[s+1]-1] + # where total time off = t - 1 + initial_time_shutdown + # (the -1 because not off for current time period) + if t + initial_time_shutdown - 1 < + g.startup_categories[s+1].delay + default_category = s + break # does not go into next category + end end end - add_to_expression!(model[:obj], - switch_on[gn, t], - g.startup_categories[default_category].cost) + add_to_expression!( + model[:obj], + switch_on[gn, t], + g.startup_categories[default_category].cost, + ) for s in 1:S-1 # Objective function terms for start-up costs # Equation (61) in Kneuven et al. (2020) # Says to replace the cost of last category with cost of category s - start_range = max((t - g.startup_categories[s + 1].delay + 1),1) - end_range = min((t - g.startup_categories[s].delay),T-1) + start_range = max((t - g.startup_categories[s+1].delay + 1), 1) + end_range = min((t - g.startup_categories[s].delay), T - 1) for tmp_t in start_range:end_range - if (t < tmp_t + DT) || (t >= tmp_t + TC) # the second clause should never be true for s < S - continue - end - add_to_expression!(model[:obj], - downtime_arc[gn,tmp_t,t], - g.startup_categories[s].cost - g.startup_categories[S].cost) + if (t < tmp_t + DT) || (t >= tmp_t + TC) # the second clause should never be true for s < S + continue + end + add_to_expression!( + model[:obj], + downtime_arc[gn, tmp_t, t], + g.startup_categories[s].cost - g.startup_categories[S].cost, + ) end end # iterate over startup categories end # iterate over time -end # add_startup_costs_KneOstWat20 \ No newline at end of file +end # add_startup_costs_KneOstWat20 diff --git a/src/model/formulations/MorLatRam2013/scosts.jl b/src/model/formulations/MorLatRam2013/scosts.jl index 8fdb961..17b7584 100644 --- a/src/model/formulations/MorLatRam2013/scosts.jl +++ b/src/model/formulations/MorLatRam2013/scosts.jl @@ -51,8 +51,7 @@ function _add_startup_cost_eqs!( # Equation (55) in Kneuven et al. (2020) eq_startup_choose[gn, t] = @constraint( model, - switch_on[gn, t] == - sum(startup[gn, t, s] for s in 1:S) + switch_on[gn, t] == sum(startup[gn, t, s] for s in 1:S) ) for s in 1:S @@ -71,7 +70,8 @@ function _add_startup_cost_eqs!( eq_startup_restrict[gn, t, s] = @constraint( model, startup[gn, t, s] <= - initial_sum + sum(switch_off[gn, i] for i in range if i >= 1) + initial_sum + + sum(switch_off[gn, i] for i in range if i >= 1) ) end # if s < S (not the last category) diff --git a/src/model/formulations/MorLatRam2013/startstop.jl b/src/model/formulations/MorLatRam2013/startstop.jl index b3d3329..941a9d0 100644 --- a/src/model/formulations/MorLatRam2013/startstop.jl +++ b/src/model/formulations/MorLatRam2013/startstop.jl @@ -2,7 +2,6 @@ # Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. # Released under the modified BSD license. See COPYING.md for more details. - """ _add_startup_shutdown_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing @@ -42,26 +41,28 @@ function _add_startup_shutdown_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing T = model[:instance].time gi = g.name - for t = 1:T + for t in 1:T ## 2020-10-09 amk: added eqn (20) and check of g.min_uptime if g.min_uptime > 1 && t < T # Equation (20) in Kneuven et al. (2020) # UT > 1 required, to guarantee that vars.switch_on[gi, t] and vars.switch_off[gi, t+1] are not both = 1 at the same time - eq_startstop_limit[gi,t] = - @constraint(model, - prod_above[gi, t] + reserve[gi, t] - <= (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - - max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t] - - max(0, g.max_power[t] - g.shutdown_limit) * switch_off[gi, t+1]) + eq_startstop_limit[gi, t] = @constraint( + model, + prod_above[gi, t] + reserve[gi, t] <= + (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - + max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t] - + max(0, g.max_power[t] - g.shutdown_limit) * switch_off[gi, t+1] + ) else ## Startup limits # Equation (21a) in Kneuven et al. (2020) # Proposed by Morales-España et al. (2013a) - eqs_startup_limit[gi, t] = - @constraint(model, - prod_above[gi, t] + reserve[gi, t] - <= (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - - max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t]) + eqs_startup_limit[gi, t] = @constraint( + model, + prod_above[gi, t] + reserve[gi, t] <= + (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - + max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t] + ) ## Shutdown limits if t < T @@ -74,12 +75,14 @@ function _add_startup_shutdown_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing # amk: if shutdown_limit is the max prod of generator in time period before shutting down, # then it makes sense to count reserves, because otherwise, if reserves ≠ 0, # then the generator will actually produce more than the limit - eqs.shutdown_limit[gi, t] = - @constraint(model, - prod_above[gi, t] - + (RESERVES_WHEN_SHUT_DOWN ? reserve[gi, t] : 0.) # amk added - <= (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - - max(0, g.max_power[t] - g.shutdown_limit) * switch_off[gi, t+1]) + eqs.shutdown_limit[gi, t] = @constraint( + model, + prod_above[gi, t] + + (RESERVES_WHEN_SHUT_DOWN ? reserve[gi, t] : 0.0) <= + (g.max_power[t] - g.min_power[t]) * is_on[gi, t] - + max(0, g.max_power[t] - g.shutdown_limit) * + switch_off[gi, t+1] + ) end end # check if g.min_uptime > 1 end # loop over time diff --git a/src/model/formulations/NowRom2000/scosts.jl b/src/model/formulations/NowRom2000/scosts.jl index 07e0317..f0693f6 100644 --- a/src/model/formulations/NowRom2000/scosts.jl +++ b/src/model/formulations/NowRom2000/scosts.jl @@ -16,5 +16,5 @@ function _add_startup_cost_eqs!( g::Unit, formulation::MorLatRam2013.StartupCosts, )::Nothing - error("Not implemented.") + return error("Not implemented.") end diff --git a/src/model/formulations/OstAnjVan2012/ramp.jl b/src/model/formulations/OstAnjVan2012/ramp.jl index 7e3eb44..706b544 100644 --- a/src/model/formulations/OstAnjVan2012/ramp.jl +++ b/src/model/formulations/OstAnjVan2012/ramp.jl @@ -53,31 +53,33 @@ function _add_ramp_eqs!( SD = g.shutdown_limit # shutdown rate RU = g.ramp_up_limit # ramp up rate RD = g.ramp_down_limit # ramp down rate - + # TODO check initial conditions, but maybe okay as long as (35) and (36) are also used for t in 1:model[:instance].time Pbar = g.max_power[t] - + #TRD = floor((Pbar - SU)/RD) # TODO check amk changed TRD wrt Kneuven et al. TRD = ceil((Pbar - SD) / RD) # ramp down time if Pbar < 1e-7 - # Skip this time period if max power = 0 - continue + # Skip this time period if max power = 0 + continue end if UT >= 1 # Equation (37) in Kneuven et al. (2020) - KSD = min( TRD, UT-1, T-t-1 ) - eq_str_prod_limit[gn, t] = - @constraint(model, - prod_above[gn, t] + g.min_power[t] * is_on[gn, t] - + (RESERVES_WHEN_RAMP_DOWN ? reserve[gn, t] : 0.) # amk added; TODO: should this be RESERVES_WHEN_RAMP_DOWN or RESERVES_WHEN_SHUT_DOWN? - <= Pbar * is_on[gi, t] - - sum((Pbar - (SD + i * RD)) * switch_off[gi, t+1+i] - for i in 0:KSD) - ) + KSD = min(TRD, UT - 1, T - t - 1) + eq_str_prod_limit[gn, t] = @constraint( + model, + prod_above[gn, t] + + g.min_power[t] * is_on[gn, t] + + (RESERVES_WHEN_RAMP_DOWN ? reserve[gn, t] : 0.0) <= + Pbar * is_on[gi, t] - sum( + (Pbar - (SD + i * RD)) * switch_off[gi, t+1+i] for + i in 0:KSD + ) + ) end # check UT >= 1 end # loop over time end diff --git a/src/model/formulations/base/system.jl b/src/model/formulations/base/system.jl index 846bfd4..621c735 100644 --- a/src/model/formulations/base/system.jl +++ b/src/model/formulations/base/system.jl @@ -76,19 +76,21 @@ function _add_reserve_eqs!(model::JuMP.Model)::Nothing shortfall_penalty = instance.shortfall_penalty[t] eq_min_reserve[t] = @constraint( model, - sum(model[:reserve][g.name, t] for g in instance.units) - + (shortfall_penalty > 1e-7 ? model[:reserve_shortfall][t] : 0.) - >= instance.reserves.spinning[t] + sum(model[:reserve][g.name, t] for g in instance.units) + ( + shortfall_penalty > 1e-7 ? model[:reserve_shortfall][t] : 0.0 + ) >= instance.reserves.spinning[t] ) # Account for shortfall contribution to objective if shortfall_penalty > 1e-7 - add_to_expression!(model.obj, - shortfall_penalty, - model[:reserve_shortfall][t]) + add_to_expression!( + model.obj, + shortfall_penalty, + model[:reserve_shortfall][t], + ) else - # Not added to the model at all - #fix(model.vars.reserve_shortfall[t], 0.; force=true) + # Not added to the model at all + #fix(model.vars.reserve_shortfall[t], 0.; force=true) end end # loop over time return diff --git a/src/model/formulations/base/unit.jl b/src/model/formulations/base/unit.jl index fc14ded..f0661c9 100644 --- a/src/model/formulations/base/unit.jl +++ b/src/model/formulations/base/unit.jl @@ -57,7 +57,11 @@ _is_initially_on(g::Unit)::Float64 = (g.initial_status > 0 ? 1.0 : 0.0) Add `:reserve` variable to `model`, fixed to zero if no spinning reserves specified. """ -function _add_reserve_vars!(model::JuMP.Model, g::Unit, ALWAYS_CREATE_VARS = false)::Nothing +function _add_reserve_vars!( + model::JuMP.Model, + g::Unit, + ALWAYS_CREATE_VARS = false, +)::Nothing reserve = _init(model, :reserve) reserve_shortfall = _init(model, :reserve_shortfall) # for accounting for shortfall penalty in the objective for t in 1:model[:instance].time @@ -137,9 +141,9 @@ function _add_startup_shutdown_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing # Generator producing too much to be turned off in the first time period # (can a binary variable have bounds x = 0?) #eqs.shutdown_limit[gi, 0] = @constraint(mip, vars.switch_off[gi, 1] <= 0) - fix(model.vars.switch_off[gi, 1], 0.; force = true) + fix(model.vars.switch_off[gi, 1], 0.0; force = true) #eq_shutdown_limit[g.name, 0] = - #@constraint(model, switch_off[g.name, 1] <= 0) + #@constraint(model, switch_off[g.name, 1] <= 0) end if t < T eq_shutdown_limit[g.name, t] = @constraint( @@ -164,14 +168,16 @@ Variables function _add_shutdown_cost_eqs!(model::JuMP.Modle, g::Unit)::Nothing T = model[:instance].time gi = g.name - for t = 1:T - shutdown_cost = 0. - if shutdown_cost > 1e-7 - # Equation (62) in Kneuven et al. (2020) - add_to_expression!(model[:obj], - model[:switch_off][gi, t], - shutdown_cost) - end + for t in 1:T + shutdown_cost = 0.0 + if shutdown_cost > 1e-7 + # Equation (62) in Kneuven et al. (2020) + add_to_expression!( + model[:obj], + model[:switch_off][gi, t], + shutdown_cost, + ) + end end # loop over time end # _add_shutdown_cost_eqs! @@ -256,18 +262,18 @@ function _add_min_uptime_downtime_eqs!(model::JuMP.Model, g::Unit)::Nothing # Equation (4) in Kneuven et al. (2020) eq_min_uptime[g.name, t] = @constraint( model, - sum(switch_on[g.name, i] for i in (t-g.min_uptime+1):t if i >= 1) - <= is_on[g.name, t] + sum(switch_on[g.name, i] for i in (t-g.min_uptime+1):t if i >= 1) <= is_on[g.name, t] ) # Minimum down-time # Equation (5) in Kneuven et al. (2020) eq_min_downtime[g.name, t] = @constraint( model, - sum(switch_off[g.name, i] for i in (t-g.min_downtime+1):t if i >= 1) - <= 1 - is_on[g.name, t] + sum( + switch_off[g.name, i] for i in (t-g.min_downtime+1):t if i >= 1 + ) <= 1 - is_on[g.name, t] ) - + # Minimum up/down-time for initial periods # Equations (3a) and (3b) in Kneuven et al. (2020) # (using :switch_on and :switch_off instead of :is_on)