mirror of
https://github.com/ANL-CEEESA/UnitCommitment.jl.git
synced 2025-12-07 16:58:51 -06:00
Add reserve shortfall penalty
This commit is contained in:
@@ -4,15 +4,11 @@
|
||||
|
||||
function _add_bus!(model::JuMP.Model, b::Bus)::Nothing
|
||||
net_injection = _init(model, :expr_net_injection)
|
||||
reserve = _init(model, :expr_reserve)
|
||||
curtail = _init(model, :curtail)
|
||||
for t in 1:model[:instance].time
|
||||
# Fixed load
|
||||
net_injection[b.name, t] = AffExpr(-b.load[t])
|
||||
|
||||
# Reserves
|
||||
reserve[b.name, t] = AffExpr()
|
||||
|
||||
# Load curtailment
|
||||
curtail[b.name, t] =
|
||||
@variable(model, lower_bound = 0, upper_bound = b.load[t])
|
||||
|
||||
@@ -29,13 +29,28 @@ end
|
||||
|
||||
function _add_reserve_eqs!(model::JuMP.Model)::Nothing
|
||||
eq_min_reserve = _init(model, :eq_min_reserve)
|
||||
for t in 1:model[:instance].time
|
||||
instance = model[:instance]
|
||||
for t in 1:instance.time
|
||||
# Equation (68) in Kneuven et al. (2020)
|
||||
# As in Morales-España et al. (2013a)
|
||||
# Akin to the alternative formulation with max_power_avail
|
||||
# from Carrión and Arroyo (2006) and Ostrowski et al. (2012)
|
||||
shortfall_penalty = instance.shortfall_penalty[t]
|
||||
eq_min_reserve[t] = @constraint(
|
||||
model,
|
||||
sum(
|
||||
model[:expr_reserve][b.name, t] for b in model[:instance].buses
|
||||
) >= model[:instance].reserves.spinning[t]
|
||||
sum(model[:reserve][g.name, t] for g in instance.units) +
|
||||
(shortfall_penalty >= 0 ? model[:reserve_shortfall][t] : 0.0) >=
|
||||
instance.reserves.spinning[t]
|
||||
)
|
||||
|
||||
# Account for shortfall contribution to objective
|
||||
if shortfall_penalty >= 0
|
||||
add_to_expression!(
|
||||
model[:obj],
|
||||
shortfall_penalty,
|
||||
model[:reserve_shortfall][t],
|
||||
)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@@ -44,12 +44,16 @@ _is_initially_on(g::Unit)::Float64 = (g.initial_status > 0 ? 1.0 : 0.0)
|
||||
|
||||
function _add_reserve_vars!(model::JuMP.Model, g::Unit)::Nothing
|
||||
reserve = _init(model, :reserve)
|
||||
reserve_shortfall = _init(model, :reserve_shortfall)
|
||||
for t in 1:model[:instance].time
|
||||
if g.provides_spinning_reserves[t]
|
||||
reserve[g.name, t] = @variable(model, lower_bound = 0)
|
||||
else
|
||||
reserve[g.name, t] = 0.0
|
||||
end
|
||||
reserve_shortfall[t] =
|
||||
(model[:instance].shortfall_penalty[t] >= 0) ?
|
||||
@variable(model, lower_bound = 0) : 0.0
|
||||
end
|
||||
return
|
||||
end
|
||||
@@ -210,11 +214,5 @@ function _add_net_injection_eqs!(model::JuMP.Model, g::Unit)::Nothing
|
||||
model[:is_on][g.name, t],
|
||||
g.min_power[t],
|
||||
)
|
||||
# Add to reserves expression
|
||||
add_to_expression!(
|
||||
model[:expr_reserve][g.bus.name, t],
|
||||
model[:reserve][g.name, t],
|
||||
1.0,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user