Create file for status vars; add Gar1962.StatusVars

bugfix/formulations
Alinson S. Xavier 4 years ago
parent 2f90c48d60
commit 063b602d1a

@ -30,6 +30,7 @@ include("model/formulations/base/unit.jl")
include("model/formulations/CarArr2006/pwlcosts.jl")
include("model/formulations/DamKucRajAta2016/ramp.jl")
include("model/formulations/Gar1962/pwlcosts.jl")
include("model/formulations/Gar1962/status.jl")
include("model/formulations/KnuOstWat2018/pwlcosts.jl")
include("model/formulations/MorLatRam2013/ramp.jl")
include("model/formulations/MorLatRam2013/scosts.jl")

@ -5,7 +5,8 @@
function _add_ramp_eqs!(
model::JuMP.Model,
g::Unit,
formulation::ArrCon2000.Ramping,
formulation_status_vars::Gar1962.StatusVars,
formulation_ramping::ArrCon2000.Ramping,
)::Nothing
# TODO: Move upper case constants to model[:instance]
RESERVES_WHEN_START_UP = true
@ -17,15 +18,17 @@ function _add_ramp_eqs!(
RD = g.ramp_down_limit
SU = g.startup_limit
SD = g.shutdown_limit
is_on = model[:is_on]
prod_above = model[:prod_above]
reserve = model[:reserve]
switch_off = model[:switch_off]
switch_on = model[:switch_on]
eq_ramp_down = _init(model, :eq_ramp_down)
eq_ramp_up = _init(model, :eq_ramp_up)
is_initially_on = (g.initial_status > 0)
# Gar1962.StatusVars
is_on = model[:is_on]
switch_off = model[:switch_off]
switch_on = model[:switch_on]
for t in 1:model[:instance].time
# Ramp up limit
if t == 1

@ -5,6 +5,7 @@
function _add_production_piecewise_linear_eqs!(
model::JuMP.Model,
g::Unit,
formulation_status_vars::StatusVarsFormulation,
formulation::CarArr2006.PwlCosts,
)::Nothing
eq_prod_above_def = _init(model, :eq_prod_above_def)

@ -5,7 +5,8 @@
function _add_ramp_eqs!(
model::JuMP.Model,
g::Unit,
formulation::DamKucRajAta2016.Ramping,
formulation_status_vars::Gar1962.StatusVars,
formulation_ramping::DamKucRajAta2016.Ramping,
)::Nothing
# TODO: Move upper case constants to model[:instance]
RESERVES_WHEN_START_UP = true
@ -21,9 +22,11 @@ function _add_ramp_eqs!(
gn = g.name
eq_str_ramp_down = _init(model, :eq_str_ramp_down)
eq_str_ramp_up = _init(model, :eq_str_ramp_up)
is_on = model[:is_on]
prod_above = model[:prod_above]
reserve = model[:reserve]
# Gar1962.StatusVars
is_on = model[:is_on]
switch_off = model[:switch_off]
switch_on = model[:switch_on]

@ -5,14 +5,15 @@
function _add_production_piecewise_linear_eqs!(
model::JuMP.Model,
g::Unit,
formulation::Gar1962.PwlCosts,
formulation_status_vars::Gar1962.StatusVars,
formulation_pwd::Gar1962.PwlCosts,
)::Nothing
eq_prod_above_def = _init(model, :eq_prod_above_def)
eq_segprod_limit = _init(model, :eq_segprod_limit)
is_on = model[:is_on]
prod_above = model[:prod_above]
segprod = model[:segprod]
gn = g.name
is_on = model[:is_on]
K = length(g.cost_segments)
for t in 1:model[:instance].time
# Definition of production

@ -0,0 +1,61 @@
# 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.
function _add_status_vars!(
model::JuMP.Model,
g::Unit,
formulation_status_vars::Gar1962.StatusVars,
)::Nothing
is_on = _init(model, :is_on)
switch_on = _init(model, :switch_on)
switch_off = _init(model, :switch_off)
for t in 1:model[:instance].time
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
else
is_on[g.name, t] = @variable(model, binary = true)
switch_on[g.name, t] = @variable(model, binary = true)
switch_off[g.name, t] = @variable(model, binary = true)
end
end
return
end
function _add_status_eqs!(
model::JuMP.Model,
g::Unit,
formulation_status_vars::Gar1962.StatusVars,
)::Nothing
eq_binary_link = _init(model, :eq_binary_link)
eq_switch_on_off = _init(model, :eq_switch_on_off)
is_on = model[:is_on]
switch_off = model[:switch_off]
switch_on = model[:switch_on]
for t in 1:model[:instance].time
if !g.must_run[t]
# Link binary variables
if t == 1
eq_binary_link[g.name, t] = @constraint(
model,
is_on[g.name, t] - _is_initially_on(g) ==
switch_on[g.name, t] - switch_off[g.name, t]
)
else
eq_binary_link[g.name, t] = @constraint(
model,
is_on[g.name, t] - is_on[g.name, t-1] ==
switch_on[g.name, t] - switch_off[g.name, t]
)
end
# Cannot switch on and off at the same time
eq_switch_on_off[g.name, t] = @constraint(
model,
switch_on[g.name, t] + switch_off[g.name, t] <= 1
)
end
end
return
end

@ -14,7 +14,9 @@ Formulation described in:
module Gar1962
import ..PiecewiseLinearCostsFormulation
import ..StatusVarsFormulation
struct PwlCosts <: PiecewiseLinearCostsFormulation end
struct StatusVars <: StatusVarsFormulation end
end

@ -5,7 +5,8 @@
function _add_production_piecewise_linear_eqs!(
model::JuMP.Model,
g::Unit,
formulation::KnuOstWat2018.PwlCosts,
formulation_status_vars::Gar1962.StatusVars,
formulation_pwl::KnuOstWat2018.PwlCosts,
)::Nothing
eq_prod_above_def = _init(model, :eq_prod_above_def)
eq_segprod_limit_a = _init(model, :eq_segprod_limit_a)
@ -13,13 +14,15 @@ function _add_production_piecewise_linear_eqs!(
eq_segprod_limit_c = _init(model, :eq_segprod_limit_c)
prod_above = model[:prod_above]
segprod = model[:segprod]
is_on = model[:is_on]
switch_on = model[:switch_on]
switch_off = model[:switch_off]
gn = g.name
K = length(g.cost_segments)
T = model[:instance].time
# Gar1962.StatusVars
is_on = model[:is_on]
switch_on = model[:switch_on]
switch_off = model[:switch_off]
for t in 1:T
for k in 1:K
# Pbar^{k-1)

@ -5,7 +5,8 @@
function _add_ramp_eqs!(
model::JuMP.Model,
g::Unit,
formulation::MorLatRam2013.Ramping,
formulation_status_vars::Gar1962.StatusVars,
formulation_ramping::MorLatRam2013.Ramping,
)::Nothing
# TODO: Move upper case constants to model[:instance]
RESERVES_WHEN_START_UP = true
@ -20,9 +21,11 @@ function _add_ramp_eqs!(
gn = g.name
eq_ramp_down = _init(model, :eq_ramp_down)
eq_ramp_up = _init(model, :eq_str_ramp_up)
is_on = model[:is_on]
prod_above = model[:prod_above]
reserve = model[:reserve]
# Gar1962.StatusVars
is_on = model[:is_on]
switch_off = model[:switch_off]
switch_on = model[:switch_on]

@ -1,16 +1,18 @@
# 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.
function _add_ramp_eqs!(
model::JuMP.Model,
g::Unit,
formulation::PanGua2016.Ramping,
formulation_status_vars::Gar1962.StatusVars,
formulation_ramping::PanGua2016.Ramping,
)::Nothing
# TODO: Move upper case constants to model[:instance]
RESERVES_WHEN_SHUT_DOWN = true
gn = g.name
is_on = model[:is_on]
prod_above = model[:prod_above]
reserve = model[:reserve]
switch_off = model[:switch_off]
switch_on = model[:switch_on]
eq_str_prod_limit = _init(model, :eq_str_prod_limit)
eq_prod_limit_ramp_up_extra_period =
_init(model, :eq_prod_limit_ramp_up_extra_period)
@ -23,6 +25,11 @@ function _add_ramp_eqs!(
RD = g.ramp_down_limit # ramp down rate
T = model[:instance].time
# Gar1962.StatusVars
is_on = model[:is_on]
switch_off = model[:switch_off]
switch_on = model[:switch_on]
for t in 1:T
Pbar = g.max_power[t]
if Pbar < 1e-7

@ -6,20 +6,23 @@ abstract type TransmissionFormulation end
abstract type RampingFormulation end
abstract type PiecewiseLinearCostsFormulation end
abstract type StartupCostsFormulation end
abstract type StatusVarsFormulation end
struct Formulation
pwl_costs::PiecewiseLinearCostsFormulation
ramping::RampingFormulation
startup_costs::StartupCostsFormulation
status_vars::StatusVarsFormulation
transmission::TransmissionFormulation
function Formulation(;
pwl_costs::PiecewiseLinearCostsFormulation = KnuOstWat2018.PwlCosts(),
ramping::RampingFormulation = MorLatRam2013.Ramping(),
startup_costs::StartupCostsFormulation = MorLatRam2013.StartupCosts(),
status_vars::StatusVarsFormulation = Gar1962.StatusVars(),
transmission::TransmissionFormulation = ShiftFactorsFormulation(),
)
return new(pwl_costs, ramping, startup_costs, transmission)
return new(pwl_costs, ramping, startup_costs, status_vars, transmission)
end
end

@ -2,7 +2,7 @@
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
function _add_unit!(model::JuMP.Model, g::Unit, f::Formulation)
function _add_unit!(model::JuMP.Model, g::Unit, formulation::Formulation)
if !all(g.must_run) && any(g.must_run)
error("Partially must-run units are not currently supported")
end
@ -14,17 +14,22 @@ function _add_unit!(model::JuMP.Model, g::Unit, f::Formulation)
_add_production_vars!(model, g)
_add_reserve_vars!(model, g)
_add_startup_shutdown_vars!(model, g)
_add_status_vars!(model, g)
_add_status_vars!(model, g, formulation.status_vars)
# Constraints and objective function
_add_min_uptime_downtime_eqs!(model, g)
_add_net_injection_eqs!(model, g)
_add_production_limit_eqs!(model, g)
_add_production_piecewise_linear_eqs!(model, g, f.pwl_costs)
_add_ramp_eqs!(model, g, f.ramping)
_add_startup_cost_eqs!(model, g, f.startup_costs)
_add_production_piecewise_linear_eqs!(
model,
g,
formulation.status_vars,
formulation.pwl_costs,
)
_add_ramp_eqs!(model, g, formulation.status_vars, formulation.ramping)
_add_startup_cost_eqs!(model, g, formulation.startup_costs)
_add_startup_shutdown_limit_eqs!(model, g)
_add_status_eqs!(model, g)
_add_status_eqs!(model, g, formulation.status_vars)
return
end
@ -134,56 +139,6 @@ function _add_startup_shutdown_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing
return
end
function _add_status_vars!(model::JuMP.Model, g::Unit)::Nothing
is_on = _init(model, :is_on)
switch_on = _init(model, :switch_on)
switch_off = _init(model, :switch_off)
for t in 1:model[:instance].time
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
else
is_on[g.name, t] = @variable(model, binary = true)
switch_on[g.name, t] = @variable(model, binary = true)
switch_off[g.name, t] = @variable(model, binary = true)
end
end
return
end
function _add_status_eqs!(model::JuMP.Model, g::Unit)::Nothing
eq_binary_link = _init(model, :eq_binary_link)
eq_switch_on_off = _init(model, :eq_switch_on_off)
is_on = model[:is_on]
switch_off = model[:switch_off]
switch_on = model[:switch_on]
for t in 1:model[:instance].time
if !g.must_run[t]
# Link binary variables
if t == 1
eq_binary_link[g.name, t] = @constraint(
model,
is_on[g.name, t] - _is_initially_on(g) ==
switch_on[g.name, t] - switch_off[g.name, t]
)
else
eq_binary_link[g.name, t] = @constraint(
model,
is_on[g.name, t] - is_on[g.name, t-1] ==
switch_on[g.name, t] - switch_off[g.name, t]
)
end
# Cannot switch on and off at the same time
eq_switch_on_off[g.name, t] = @constraint(
model,
switch_on[g.name, t] + switch_off[g.name, t] <= 1
)
end
end
return
end
function _add_ramp_eqs!(
model::JuMP.Model,
g::Unit,

Loading…
Cancel
Save