Add reserve shortfall penalty

pull/16/head
Aleksandr Kazachkov 4 years ago committed by Alinson S Xavier
parent 7a1b6f0f55
commit 7a03f4bbb0

@ -98,6 +98,10 @@ function _from_json(json; repair = true)
json["Parameters"]["Power balance penalty (\$/MW)"],
default = [1000.0 for t in 1:T],
)
shortfall_penalty = timeseries(
json["Parameters"]["Reserve shortfall penalty (\$/MW)"],
default = [0.0 for t in 1:T],
)
# Read buses
for (bus_name, dict) in json["Buses"]
@ -264,6 +268,7 @@ function _from_json(json; repair = true)
instance = UnitCommitmentInstance(
T,
power_balance_penalty,
shortfall_penalty,
units,
buses,
lines,

@ -72,6 +72,8 @@ end
mutable struct UnitCommitmentInstance
time::Int
power_balance_penalty::Vector{Float64}
"Penalty for failing to meet reserve requirement."
shortfall_penalty::Vector{Float64}
units::Vector{Unit}
buses::Vector{Bus}
lines::Vector{TransmissionLine}

@ -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,31 @@ 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 > 1e-7 ? model[:reserve_shortfall][t] : 0.0
) >= instance.reserves.spinning[t]
)
end
# Account for shortfall contribution to objective
if shortfall_penalty > 1e-7
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)
end
end # loop over time
return
end

@ -44,6 +44,7 @@ _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)
@ -210,11 +211,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

Loading…
Cancel
Save