mirror of
https://github.com/ANL-CEEESA/UnitCommitment.jl.git
synced 2025-12-06 16:28:51 -06:00
Add Gar1962.ProdVars
This commit is contained in:
@@ -31,6 +31,7 @@ include("model/formulations/CarArr2006/pwlcosts.jl")
|
|||||||
include("model/formulations/DamKucRajAta2016/ramp.jl")
|
include("model/formulations/DamKucRajAta2016/ramp.jl")
|
||||||
include("model/formulations/Gar1962/pwlcosts.jl")
|
include("model/formulations/Gar1962/pwlcosts.jl")
|
||||||
include("model/formulations/Gar1962/status.jl")
|
include("model/formulations/Gar1962/status.jl")
|
||||||
|
include("model/formulations/Gar1962/prod.jl")
|
||||||
include("model/formulations/KnuOstWat2018/pwlcosts.jl")
|
include("model/formulations/KnuOstWat2018/pwlcosts.jl")
|
||||||
include("model/formulations/MorLatRam2013/ramp.jl")
|
include("model/formulations/MorLatRam2013/ramp.jl")
|
||||||
include("model/formulations/MorLatRam2013/scosts.jl")
|
include("model/formulations/MorLatRam2013/scosts.jl")
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::Unit,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::ArrCon2000.Ramping,
|
formulation_ramping::ArrCon2000.Ramping,
|
||||||
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
# TODO: Move upper case constants to model[:instance]
|
# TODO: Move upper case constants to model[:instance]
|
||||||
RESERVES_WHEN_START_UP = true
|
RESERVES_WHEN_START_UP = true
|
||||||
@@ -18,12 +19,14 @@ function _add_ramp_eqs!(
|
|||||||
RD = g.ramp_down_limit
|
RD = g.ramp_down_limit
|
||||||
SU = g.startup_limit
|
SU = g.startup_limit
|
||||||
SD = g.shutdown_limit
|
SD = g.shutdown_limit
|
||||||
prod_above = model[:prod_above]
|
|
||||||
reserve = model[:reserve]
|
reserve = model[:reserve]
|
||||||
eq_ramp_down = _init(model, :eq_ramp_down)
|
eq_ramp_down = _init(model, :eq_ramp_down)
|
||||||
eq_ramp_up = _init(model, :eq_ramp_up)
|
eq_ramp_up = _init(model, :eq_ramp_up)
|
||||||
is_initially_on = (g.initial_status > 0)
|
is_initially_on = (g.initial_status > 0)
|
||||||
|
|
||||||
|
# Gar1962.ProdVars
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
|
||||||
# Gar1962.StatusVars
|
# Gar1962.StatusVars
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
switch_off = model[:switch_off]
|
switch_off = model[:switch_off]
|
||||||
|
|||||||
@@ -5,14 +5,18 @@
|
|||||||
function _add_production_piecewise_linear_eqs!(
|
function _add_production_piecewise_linear_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::Unit,
|
||||||
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
|
formulation_pwl_costs::CarArr2006.PwlCosts,
|
||||||
formulation_status_vars::StatusVarsFormulation,
|
formulation_status_vars::StatusVarsFormulation,
|
||||||
formulation::CarArr2006.PwlCosts,
|
|
||||||
)::Nothing
|
)::Nothing
|
||||||
eq_prod_above_def = _init(model, :eq_prod_above_def)
|
eq_prod_above_def = _init(model, :eq_prod_above_def)
|
||||||
eq_segprod_limit = _init(model, :eq_segprod_limit)
|
eq_segprod_limit = _init(model, :eq_segprod_limit)
|
||||||
prod_above = model[:prod_above]
|
|
||||||
segprod = model[:segprod]
|
segprod = model[:segprod]
|
||||||
gn = g.name
|
gn = g.name
|
||||||
|
|
||||||
|
# Gar1962.ProdVars
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
|
||||||
K = length(g.cost_segments)
|
K = length(g.cost_segments)
|
||||||
for t in 1:model[:instance].time
|
for t in 1:model[:instance].time
|
||||||
gn = g.name
|
gn = g.name
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::Unit,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::DamKucRajAta2016.Ramping,
|
formulation_ramping::DamKucRajAta2016.Ramping,
|
||||||
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
# TODO: Move upper case constants to model[:instance]
|
# TODO: Move upper case constants to model[:instance]
|
||||||
RESERVES_WHEN_START_UP = true
|
RESERVES_WHEN_START_UP = true
|
||||||
@@ -22,9 +23,11 @@ function _add_ramp_eqs!(
|
|||||||
gn = g.name
|
gn = g.name
|
||||||
eq_str_ramp_down = _init(model, :eq_str_ramp_down)
|
eq_str_ramp_down = _init(model, :eq_str_ramp_down)
|
||||||
eq_str_ramp_up = _init(model, :eq_str_ramp_up)
|
eq_str_ramp_up = _init(model, :eq_str_ramp_up)
|
||||||
prod_above = model[:prod_above]
|
|
||||||
reserve = model[:reserve]
|
reserve = model[:reserve]
|
||||||
|
|
||||||
|
# Gar1962.ProdVars
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
|
||||||
# Gar1962.StatusVars
|
# Gar1962.StatusVars
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
switch_off = model[:switch_off]
|
switch_off = model[:switch_off]
|
||||||
|
|||||||
50
src/model/formulations/Gar1962/prod.jl
Normal file
50
src/model/formulations/Gar1962/prod.jl
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# 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_production_vars!(
|
||||||
|
model::JuMP.Model,
|
||||||
|
g::Unit,
|
||||||
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
|
)::Nothing
|
||||||
|
prod_above = _init(model, :prod_above)
|
||||||
|
segprod = _init(model, :segprod)
|
||||||
|
for t in 1:model[:instance].time
|
||||||
|
for k in 1:length(g.cost_segments)
|
||||||
|
segprod[g.name, t, k] = @variable(model, lower_bound = 0)
|
||||||
|
end
|
||||||
|
prod_above[g.name, t] = @variable(model, lower_bound = 0)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
function _add_production_limit_eqs!(
|
||||||
|
model::JuMP.Model,
|
||||||
|
g::Unit,
|
||||||
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
|
)::Nothing
|
||||||
|
eq_prod_limit = _init(model, :eq_prod_limit)
|
||||||
|
is_on = model[:is_on]
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
reserve = model[:reserve]
|
||||||
|
gn = g.name
|
||||||
|
for t in 1:model[:instance].time
|
||||||
|
# Objective function terms for production costs
|
||||||
|
# Part of (69) of Kneuven et al. (2020) as C^R_g * u_g(t) term
|
||||||
|
add_to_expression!(model[:obj], is_on[gn, t], g.min_power_cost[t])
|
||||||
|
|
||||||
|
# Production limit
|
||||||
|
# Equation (18) in Kneuven et al. (2020)
|
||||||
|
# as \bar{p}_g(t) \le \bar{P}_g u_g(t)
|
||||||
|
# amk: this is a weaker version of (20) and (21) in Kneuven et al. (2020)
|
||||||
|
# but keeping it here in case those are not present
|
||||||
|
power_diff = max(g.max_power[t], 0.0) - max(g.min_power[t], 0.0)
|
||||||
|
if power_diff < 1e-7
|
||||||
|
power_diff = 0.0
|
||||||
|
end
|
||||||
|
eq_prod_limit[gn, t] = @constraint(
|
||||||
|
model,
|
||||||
|
prod_above[gn, t] + reserve[gn, t] <= power_diff * is_on[gn, t]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -5,15 +5,21 @@
|
|||||||
function _add_production_piecewise_linear_eqs!(
|
function _add_production_piecewise_linear_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::Unit,
|
||||||
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
|
formulation_pwl_costs::Gar1962.PwlCosts,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
formulation_pwd::Gar1962.PwlCosts,
|
|
||||||
)::Nothing
|
)::Nothing
|
||||||
eq_prod_above_def = _init(model, :eq_prod_above_def)
|
eq_prod_above_def = _init(model, :eq_prod_above_def)
|
||||||
eq_segprod_limit = _init(model, :eq_segprod_limit)
|
eq_segprod_limit = _init(model, :eq_segprod_limit)
|
||||||
prod_above = model[:prod_above]
|
|
||||||
segprod = model[:segprod]
|
segprod = model[:segprod]
|
||||||
gn = g.name
|
gn = g.name
|
||||||
|
|
||||||
|
# Gar1962.ProdVars
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
|
||||||
|
# Gar1962.StatusVars
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
|
|
||||||
K = length(g.cost_segments)
|
K = length(g.cost_segments)
|
||||||
for t in 1:model[:instance].time
|
for t in 1:model[:instance].time
|
||||||
# Definition of production
|
# Definition of production
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ Formulation described in:
|
|||||||
module Gar1962
|
module Gar1962
|
||||||
|
|
||||||
import ..PiecewiseLinearCostsFormulation
|
import ..PiecewiseLinearCostsFormulation
|
||||||
|
import ..ProductionVarsFormulation
|
||||||
import ..StatusVarsFormulation
|
import ..StatusVarsFormulation
|
||||||
|
|
||||||
|
struct ProdVars <: ProductionVarsFormulation end
|
||||||
struct PwlCosts <: PiecewiseLinearCostsFormulation end
|
struct PwlCosts <: PiecewiseLinearCostsFormulation end
|
||||||
struct StatusVars <: StatusVarsFormulation end
|
struct StatusVars <: StatusVarsFormulation end
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,22 @@
|
|||||||
function _add_production_piecewise_linear_eqs!(
|
function _add_production_piecewise_linear_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::Unit,
|
||||||
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
|
formulation_pwl_costs::KnuOstWat2018.PwlCosts,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
formulation_pwl::KnuOstWat2018.PwlCosts,
|
|
||||||
)::Nothing
|
)::Nothing
|
||||||
eq_prod_above_def = _init(model, :eq_prod_above_def)
|
eq_prod_above_def = _init(model, :eq_prod_above_def)
|
||||||
eq_segprod_limit_a = _init(model, :eq_segprod_limit_a)
|
eq_segprod_limit_a = _init(model, :eq_segprod_limit_a)
|
||||||
eq_segprod_limit_b = _init(model, :eq_segprod_limit_b)
|
eq_segprod_limit_b = _init(model, :eq_segprod_limit_b)
|
||||||
eq_segprod_limit_c = _init(model, :eq_segprod_limit_c)
|
eq_segprod_limit_c = _init(model, :eq_segprod_limit_c)
|
||||||
prod_above = model[:prod_above]
|
|
||||||
segprod = model[:segprod]
|
segprod = model[:segprod]
|
||||||
gn = g.name
|
gn = g.name
|
||||||
K = length(g.cost_segments)
|
K = length(g.cost_segments)
|
||||||
T = model[:instance].time
|
T = model[:instance].time
|
||||||
|
|
||||||
|
# Gar1962.ProdVars
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
|
||||||
# Gar1962.StatusVars
|
# Gar1962.StatusVars
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
switch_on = model[:switch_on]
|
switch_on = model[:switch_on]
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::Unit,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::MorLatRam2013.Ramping,
|
formulation_ramping::MorLatRam2013.Ramping,
|
||||||
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
# TODO: Move upper case constants to model[:instance]
|
# TODO: Move upper case constants to model[:instance]
|
||||||
RESERVES_WHEN_START_UP = true
|
RESERVES_WHEN_START_UP = true
|
||||||
@@ -21,9 +22,11 @@ function _add_ramp_eqs!(
|
|||||||
gn = g.name
|
gn = g.name
|
||||||
eq_ramp_down = _init(model, :eq_ramp_down)
|
eq_ramp_down = _init(model, :eq_ramp_down)
|
||||||
eq_ramp_up = _init(model, :eq_str_ramp_up)
|
eq_ramp_up = _init(model, :eq_str_ramp_up)
|
||||||
prod_above = model[:prod_above]
|
|
||||||
reserve = model[:reserve]
|
reserve = model[:reserve]
|
||||||
|
|
||||||
|
# Gar1962.ProdVars
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
|
||||||
# Gar1962.StatusVars
|
# Gar1962.StatusVars
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
switch_off = model[:switch_off]
|
switch_off = model[:switch_off]
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::Unit,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::PanGua2016.Ramping,
|
formulation_ramping::PanGua2016.Ramping,
|
||||||
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
# TODO: Move upper case constants to model[:instance]
|
# TODO: Move upper case constants to model[:instance]
|
||||||
RESERVES_WHEN_SHUT_DOWN = true
|
RESERVES_WHEN_SHUT_DOWN = true
|
||||||
gn = g.name
|
gn = g.name
|
||||||
prod_above = model[:prod_above]
|
|
||||||
reserve = model[:reserve]
|
reserve = model[:reserve]
|
||||||
eq_str_prod_limit = _init(model, :eq_str_prod_limit)
|
eq_str_prod_limit = _init(model, :eq_str_prod_limit)
|
||||||
eq_prod_limit_ramp_up_extra_period =
|
eq_prod_limit_ramp_up_extra_period =
|
||||||
@@ -25,6 +25,9 @@ function _add_ramp_eqs!(
|
|||||||
RD = g.ramp_down_limit # ramp down rate
|
RD = g.ramp_down_limit # ramp down rate
|
||||||
T = model[:instance].time
|
T = model[:instance].time
|
||||||
|
|
||||||
|
# Gar1962.ProdVars
|
||||||
|
prod_above = model[:prod_above]
|
||||||
|
|
||||||
# Gar1962.StatusVars
|
# Gar1962.StatusVars
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
switch_off = model[:switch_off]
|
switch_off = model[:switch_off]
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ abstract type RampingFormulation end
|
|||||||
abstract type PiecewiseLinearCostsFormulation end
|
abstract type PiecewiseLinearCostsFormulation end
|
||||||
abstract type StartupCostsFormulation end
|
abstract type StartupCostsFormulation end
|
||||||
abstract type StatusVarsFormulation end
|
abstract type StatusVarsFormulation end
|
||||||
|
abstract type ProductionVarsFormulation end
|
||||||
|
|
||||||
struct Formulation
|
struct Formulation
|
||||||
|
prod_vars::ProductionVarsFormulation
|
||||||
pwl_costs::PiecewiseLinearCostsFormulation
|
pwl_costs::PiecewiseLinearCostsFormulation
|
||||||
ramping::RampingFormulation
|
ramping::RampingFormulation
|
||||||
startup_costs::StartupCostsFormulation
|
startup_costs::StartupCostsFormulation
|
||||||
@@ -16,13 +18,21 @@ struct Formulation
|
|||||||
transmission::TransmissionFormulation
|
transmission::TransmissionFormulation
|
||||||
|
|
||||||
function Formulation(;
|
function Formulation(;
|
||||||
|
prod_vars::ProductionVarsFormulation = Gar1962.ProdVars(),
|
||||||
pwl_costs::PiecewiseLinearCostsFormulation = KnuOstWat2018.PwlCosts(),
|
pwl_costs::PiecewiseLinearCostsFormulation = KnuOstWat2018.PwlCosts(),
|
||||||
ramping::RampingFormulation = MorLatRam2013.Ramping(),
|
ramping::RampingFormulation = MorLatRam2013.Ramping(),
|
||||||
startup_costs::StartupCostsFormulation = MorLatRam2013.StartupCosts(),
|
startup_costs::StartupCostsFormulation = MorLatRam2013.StartupCosts(),
|
||||||
status_vars::StatusVarsFormulation = Gar1962.StatusVars(),
|
status_vars::StatusVarsFormulation = Gar1962.StatusVars(),
|
||||||
transmission::TransmissionFormulation = ShiftFactorsFormulation(),
|
transmission::TransmissionFormulation = ShiftFactorsFormulation(),
|
||||||
)
|
)
|
||||||
return new(pwl_costs, ramping, startup_costs, status_vars, transmission)
|
return new(
|
||||||
|
prod_vars,
|
||||||
|
pwl_costs,
|
||||||
|
ramping,
|
||||||
|
startup_costs,
|
||||||
|
status_vars,
|
||||||
|
transmission,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ function _add_unit!(model::JuMP.Model, g::Unit, formulation::Formulation)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
_add_production_vars!(model, g)
|
_add_production_vars!(model, g, formulation.prod_vars)
|
||||||
_add_reserve_vars!(model, g)
|
_add_reserve_vars!(model, g)
|
||||||
_add_startup_shutdown_vars!(model, g)
|
_add_startup_shutdown_vars!(model, g)
|
||||||
_add_status_vars!(model, g, formulation.status_vars)
|
_add_status_vars!(model, g, formulation.status_vars)
|
||||||
@@ -19,14 +19,21 @@ function _add_unit!(model::JuMP.Model, g::Unit, formulation::Formulation)
|
|||||||
# Constraints and objective function
|
# Constraints and objective function
|
||||||
_add_min_uptime_downtime_eqs!(model, g)
|
_add_min_uptime_downtime_eqs!(model, g)
|
||||||
_add_net_injection_eqs!(model, g)
|
_add_net_injection_eqs!(model, g)
|
||||||
_add_production_limit_eqs!(model, g)
|
_add_production_limit_eqs!(model, g, formulation.prod_vars)
|
||||||
_add_production_piecewise_linear_eqs!(
|
_add_production_piecewise_linear_eqs!(
|
||||||
model,
|
model,
|
||||||
g,
|
g,
|
||||||
formulation.status_vars,
|
formulation.prod_vars,
|
||||||
formulation.pwl_costs,
|
formulation.pwl_costs,
|
||||||
|
formulation.status_vars,
|
||||||
|
)
|
||||||
|
_add_ramp_eqs!(
|
||||||
|
model,
|
||||||
|
g,
|
||||||
|
formulation.prod_vars,
|
||||||
|
formulation.ramping,
|
||||||
|
formulation.status_vars,
|
||||||
)
|
)
|
||||||
_add_ramp_eqs!(model, g, formulation.status_vars, formulation.ramping)
|
|
||||||
_add_startup_cost_eqs!(model, g, formulation.startup_costs)
|
_add_startup_cost_eqs!(model, g, formulation.startup_costs)
|
||||||
_add_startup_shutdown_limit_eqs!(model, g)
|
_add_startup_shutdown_limit_eqs!(model, g)
|
||||||
_add_status_eqs!(model, g, formulation.status_vars)
|
_add_status_eqs!(model, g, formulation.status_vars)
|
||||||
@@ -35,45 +42,6 @@ end
|
|||||||
|
|
||||||
_is_initially_on(g::Unit)::Float64 = (g.initial_status > 0 ? 1.0 : 0.0)
|
_is_initially_on(g::Unit)::Float64 = (g.initial_status > 0 ? 1.0 : 0.0)
|
||||||
|
|
||||||
function _add_production_vars!(model::JuMP.Model, g::Unit)::Nothing
|
|
||||||
prod_above = _init(model, :prod_above)
|
|
||||||
segprod = _init(model, :segprod)
|
|
||||||
for t in 1:model[:instance].time
|
|
||||||
for k in 1:length(g.cost_segments)
|
|
||||||
segprod[g.name, t, k] = @variable(model, lower_bound = 0)
|
|
||||||
end
|
|
||||||
prod_above[g.name, t] = @variable(model, lower_bound = 0)
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
function _add_production_limit_eqs!(model::JuMP.Model, g::Unit)::Nothing
|
|
||||||
eq_prod_limit = _init(model, :eq_prod_limit)
|
|
||||||
is_on = model[:is_on]
|
|
||||||
prod_above = model[:prod_above]
|
|
||||||
reserve = model[:reserve]
|
|
||||||
gn = g.name
|
|
||||||
for t in 1:model[:instance].time
|
|
||||||
# Objective function terms for production costs
|
|
||||||
# Part of (69) of Kneuven et al. (2020) as C^R_g * u_g(t) term
|
|
||||||
add_to_expression!(model[:obj], is_on[gn, t], g.min_power_cost[t])
|
|
||||||
|
|
||||||
# Production limit
|
|
||||||
# Equation (18) in Kneuven et al. (2020)
|
|
||||||
# as \bar{p}_g(t) \le \bar{P}_g u_g(t)
|
|
||||||
# amk: this is a weaker version of (20) and (21) in Kneuven et al. (2020)
|
|
||||||
# but keeping it here in case those are not present
|
|
||||||
power_diff = max(g.max_power[t], 0.0) - max(g.min_power[t], 0.0)
|
|
||||||
if power_diff < 1e-7
|
|
||||||
power_diff = 0.0
|
|
||||||
end
|
|
||||||
eq_prod_limit[gn, t] = @constraint(
|
|
||||||
model,
|
|
||||||
prod_above[gn, t] + reserve[gn, t] <= power_diff * is_on[gn, t]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function _add_reserve_vars!(model::JuMP.Model, g::Unit)::Nothing
|
function _add_reserve_vars!(model::JuMP.Model, g::Unit)::Nothing
|
||||||
reserve = _init(model, :reserve)
|
reserve = _init(model, :reserve)
|
||||||
for t in 1:model[:instance].time
|
for t in 1:model[:instance].time
|
||||||
|
|||||||
Reference in New Issue
Block a user