Added comments on formulations, added start/stop constraints into MorLatRam and GenMorRam, added ability to add shortfall penalty.

add_formulations
Aleksandr Kazachkov 4 years ago
parent c7602d1fb4
commit 9ca3ae1e45

@ -45,7 +45,7 @@ function _add_ramp_eqs!(
for t in 1:model[:instance].time for t in 1:model[:instance].time
# Ramp up limit # Ramp up limit
if t == 1 if t == 1
if is_initially_on if _is_initially_on(g)
# min power is _not_ multiplied by is_on because if !is_on, then ramp up is irrelevant # min power is _not_ multiplied by is_on because if !is_on, then ramp up is irrelevant
eq_ramp_up[gn, t] = @constraint( eq_ramp_up[gn, t] = @constraint(
model, model,
@ -76,7 +76,7 @@ function _add_ramp_eqs!(
# Ramp down limit # Ramp down limit
if t == 1 if t == 1
if is_initially_on if _is_initially_on(g)
# TODO If RD < SD, or more specifically if # TODO If RD < SD, or more specifically if
# min_power + RD < initial_power < SD # min_power + RD < initial_power < SD
# then the generator should be able to shut down at time t = 1, # then the generator should be able to shut down at time t = 1,

@ -12,6 +12,7 @@ function _add_status_vars!(
model::JuMP.Model, model::JuMP.Model,
g::Unit, g::Unit,
formulation_status_vars::Gar1962.StatusVars, formulation_status_vars::Gar1962.StatusVars,
ALWAYS_CREATE_VARS = false
)::Nothing )::Nothing
is_on = _init(model, :is_on) is_on = _init(model, :is_on)
switch_on = _init(model, :switch_on) switch_on = _init(model, :switch_on)
@ -63,6 +64,44 @@ function _add_status_vars!(
end end
end end
end end
if ALWAYS_CREATE_VARS
# If variables are created, use initial conditions to fix some values
if t == 1
if _is_initially_on(g)
# Generator was on (for g.initial_status time periods),
# so cannot be more switched on until the period after the first time it can be turned off
fix(switch_on[g.name, 1], 0.0; force = true)
else
# Generator is initially off (for -g.initial_status time periods)
# Cannot be switched off more
fix(switch_off[g.name, 1], 0.0; force = true)
end
end
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_off[g.name, t], 0.0; force = true)
end
else
# If vars are not created, then replace them by a constant
if t == 1
if _is_initially_on(g)
switch_on[g.name, t] = 0.0
else
switch_off[g.name, t] = 0.0
end
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_off[g.name, t] = 0.0
end
end # check if ALWAYS_CREATE_VARS
end end
return return
end end

@ -2,10 +2,10 @@
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. # Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details. # Released under the modified BSD license. See COPYING.md for more details.
abstract type TransmissionFormulation end abstract type AbstractTransmissionFormulation end
abstract type RampingFormulation end abstract type AbstractRampingFormulation end
abstract type PiecewiseLinearCostsFormulation end abstract type PiecewiseLinearCostsFormulation end
abstract type StartupCostsFormulation end abstract type AbstractStartupCostsFormulation end
abstract type StatusVarsFormulation end abstract type StatusVarsFormulation end
abstract type ProductionVarsFormulation end abstract type ProductionVarsFormulation end
@ -21,18 +21,18 @@ Some of these components are allowed to be empty, as long as overall validity of
struct Formulation struct Formulation
prod_vars::ProductionVarsFormulation prod_vars::ProductionVarsFormulation
pwl_costs::PiecewiseLinearCostsFormulation pwl_costs::PiecewiseLinearCostsFormulation
ramping::RampingFormulation ramping::AbstractRampingFormulation
startup_costs::StartupCostsFormulation startup_costs::AbstractStartupCostsFormulation
status_vars::StatusVarsFormulation status_vars::StatusVarsFormulation
transmission::TransmissionFormulation transmission::AbstractTransmissionFormulation
function Formulation(; function Formulation(;
prod_vars::ProductionVarsFormulation = Gar1962.ProdVars(), prod_vars::ProductionVarsFormulation = Gar1962.ProdVars(),
pwl_costs::PiecewiseLinearCostsFormulation = KnuOstWat2018.PwlCosts(), pwl_costs::PiecewiseLinearCostsFormulation = KnuOstWat2018.PwlCosts(),
ramping::RampingFormulation = MorLatRam2013.Ramping(), ramping::AbstractRampingFormulation = MorLatRam2013.Ramping(),
startup_costs::StartupCostsFormulation = MorLatRam2013.StartupCosts(), startup_costs::AbstractStartupCostsFormulation = MorLatRam2013.StartupCosts(),
status_vars::StatusVarsFormulation = Gar1962.StatusVars(), status_vars::StatusVarsFormulation = Gar1962.StatusVars(),
transmission::TransmissionFormulation = ShiftFactorsFormulation(), transmission::AbstractTransmissionFormulation = ShiftFactorsFormulation(),
) )
return new( return new(
prod_vars, prod_vars,
@ -70,7 +70,7 @@ Arguments
the cutoff that should be applied to the LODF matrix. Entries with magnitude the cutoff that should be applied to the LODF matrix. Entries with magnitude
smaller than this value will be set to zero. smaller than this value will be set to zero.
""" """
struct ShiftFactorsFormulation <: TransmissionFormulation struct ShiftFactorsFormulation <: AbstractTransmissionFormulation
isf_cutoff::Float64 isf_cutoff::Float64
lodf_cutoff::Float64 lodf_cutoff::Float64
precomputed_isf::Union{Nothing,Matrix{Float64}} precomputed_isf::Union{Nothing,Matrix{Float64}}

@ -192,7 +192,7 @@ end
function _add_ramp_eqs!( function _add_ramp_eqs!(
model::JuMP.Model, model::JuMP.Model,
g::Unit, g::Unit,
formulation::RampingFormulation, formulation::AbstractRampingFormulation,
)::Nothing )::Nothing
prod_above = model[:prod_above] prod_above = model[:prod_above]
reserve = model[:reserve] reserve = model[:reserve]
@ -265,16 +265,16 @@ function _add_min_uptime_downtime_eqs!(model::JuMP.Model, g::Unit)::Nothing
# Equation (4) in Knueven et al. (2020) # Equation (4) in Knueven et al. (2020)
eq_min_uptime[g.name, t] = @constraint( eq_min_uptime[g.name, t] = @constraint(
model, 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 # Minimum down-time
# Equation (5) in Knueven et al. (2020) # Equation (5) in Knueven et al. (2020)
eq_min_downtime[g.name, t] = @constraint( eq_min_downtime[g.name, t] = @constraint(
model, model,
sum( sum(switch_off[g.name, i] for i in (t-g.min_downtime+1):t if i >= 1)
switch_off[g.name, i] for i in (t-g.min_downtime+1):t if i >= 1 <= 1 - is_on[g.name, t]
) <= 1 - is_on[g.name, t]
) )
# Minimum up/down-time for initial periods # Minimum up/down-time for initial periods

Loading…
Cancel
Save