You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
UnitCommitment.jl/src/model/formulations/OstAnjVan2012/ramp.jl

86 lines
2.4 KiB

# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
"""
_add_ramp_eqs!
Ensure constraints on ramping are met.
Based on Ostrowski, Anjos, Vannelli (2012).
Eqn (37) in Knueven et al. (2020).
Variables
---
* :is_on
* :prod_above
* :reserve
Constraints
---
* :eq_str_prod_limit
"""
function _add_ramp_eqs!(
model::JuMP.Model,
g::Unit,
formulation_prod_vars::Gar1962.ProdVars,
formulation_ramping::MorLatRam2013.Ramping,
formulation_status_vars::Gar1962.StatusVars,
)::Nothing
# TODO: Move upper case constants to model[:instance]
RESERVES_WHEN_START_UP = true
RESERVES_WHEN_RAMP_UP = true
RESERVES_WHEN_RAMP_DOWN = true
RESERVES_WHEN_SHUT_DOWN = true
is_initially_on = _is_initially_on(g)
gn = g.name
eq_str_prod_limit = _init(model, :eq_str_prod_limit)
# Variables that we need
reserve = model[:reserve]
# Gar1962.ProdVars
prod_above = model[:prod_above]
# Gar1962.StatusVars
is_on = model[:is_on]
switch_off = model[:switch_off]
# The following are the same for generator g across all time periods
UT = g.min_uptime
SU = g.startup_limit # startup rate
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 Knueven et al.
TRD = ceil((Pbar - SD) / RD) # ramp down time
if Pbar < 1e-7
# Skip this time period if max power = 0
continue
end
if UT >= 1
# Equation (37) in Knueven 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.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