mirror of
https://github.com/ANL-CEEESA/UnitCommitment.jl.git
synced 2025-12-06 08:18:51 -06:00
Rename Unit to ThermalUnit
This commit is contained in:
@@ -129,7 +129,7 @@ end
|
|||||||
|
|
||||||
function _from_json(json; repair = true)::UnitCommitmentScenario
|
function _from_json(json; repair = true)::UnitCommitmentScenario
|
||||||
_migrate(json)
|
_migrate(json)
|
||||||
units = Unit[]
|
thermal_units = ThermalUnit[]
|
||||||
buses = Bus[]
|
buses = Bus[]
|
||||||
contingencies = Contingency[]
|
contingencies = Contingency[]
|
||||||
lines = TransmissionLine[]
|
lines = TransmissionLine[]
|
||||||
@@ -160,7 +160,7 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
|
|
||||||
name_to_bus = Dict{String,Bus}()
|
name_to_bus = Dict{String,Bus}()
|
||||||
name_to_line = Dict{String,TransmissionLine}()
|
name_to_line = Dict{String,TransmissionLine}()
|
||||||
name_to_unit = Dict{String,Unit}()
|
name_to_unit = Dict{String,ThermalUnit}()
|
||||||
name_to_reserve = Dict{String,Reserve}()
|
name_to_reserve = Dict{String,Reserve}()
|
||||||
|
|
||||||
function timeseries(x; default = nothing)
|
function timeseries(x; default = nothing)
|
||||||
@@ -181,7 +181,7 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
bus_name,
|
bus_name,
|
||||||
length(buses),
|
length(buses),
|
||||||
timeseries(dict["Load (MW)"]),
|
timeseries(dict["Load (MW)"]),
|
||||||
Unit[],
|
ThermalUnit[],
|
||||||
PriceSensitiveLoad[],
|
PriceSensitiveLoad[],
|
||||||
ProfiledUnit[],
|
ProfiledUnit[],
|
||||||
)
|
)
|
||||||
@@ -196,7 +196,7 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
name = reserve_name,
|
name = reserve_name,
|
||||||
type = lowercase(dict["Type"]),
|
type = lowercase(dict["Type"]),
|
||||||
amount = timeseries(dict["Amount (MW)"]),
|
amount = timeseries(dict["Amount (MW)"]),
|
||||||
units = [],
|
thermal_units = [],
|
||||||
shortfall_penalty = scalar(
|
shortfall_penalty = scalar(
|
||||||
dict["Shortfall penalty (\$/MW)"],
|
dict["Shortfall penalty (\$/MW)"],
|
||||||
default = -1,
|
default = -1,
|
||||||
@@ -282,7 +282,7 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
initial_status *= time_multiplier
|
initial_status *= time_multiplier
|
||||||
end
|
end
|
||||||
|
|
||||||
unit = Unit(
|
unit = ThermalUnit(
|
||||||
unit_name,
|
unit_name,
|
||||||
bus,
|
bus,
|
||||||
max_power,
|
max_power,
|
||||||
@@ -303,12 +303,12 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
startup_categories,
|
startup_categories,
|
||||||
unit_reserves,
|
unit_reserves,
|
||||||
)
|
)
|
||||||
push!(bus.units, unit)
|
push!(bus.thermal_units, unit)
|
||||||
for r in unit_reserves
|
for r in unit_reserves
|
||||||
push!(r.units, unit)
|
push!(r.thermal_units, unit)
|
||||||
end
|
end
|
||||||
name_to_unit[unit_name] = unit
|
name_to_unit[unit_name] = unit
|
||||||
push!(units, unit)
|
push!(thermal_units, unit)
|
||||||
elseif lowercase(unit_type) === "profiled"
|
elseif lowercase(unit_type) === "profiled"
|
||||||
bus = name_to_bus[dict["Bus"]]
|
bus = name_to_bus[dict["Bus"]]
|
||||||
pu = ProfiledUnit(
|
pu = ProfiledUnit(
|
||||||
@@ -355,7 +355,7 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
# Read contingencies
|
# Read contingencies
|
||||||
if "Contingencies" in keys(json)
|
if "Contingencies" in keys(json)
|
||||||
for (cont_name, dict) in json["Contingencies"]
|
for (cont_name, dict) in json["Contingencies"]
|
||||||
affected_units = Unit[]
|
affected_units = ThermalUnit[]
|
||||||
affected_lines = TransmissionLine[]
|
affected_lines = TransmissionLine[]
|
||||||
if "Affected lines" in keys(dict)
|
if "Affected lines" in keys(dict)
|
||||||
affected_lines =
|
affected_lines =
|
||||||
@@ -400,8 +400,8 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
reserves = reserves,
|
reserves = reserves,
|
||||||
reserves_by_name = name_to_reserve,
|
reserves_by_name = name_to_reserve,
|
||||||
time = T,
|
time = T,
|
||||||
units_by_name = Dict(g.name => g for g in units),
|
thermal_units_by_name = Dict(g.name => g for g in thermal_units),
|
||||||
units = units,
|
thermal_units = thermal_units,
|
||||||
profiled_units_by_name = Dict(pu.name => pu for pu in profiled_units),
|
profiled_units_by_name = Dict(pu.name => pu for pu in profiled_units),
|
||||||
profiled_units = profiled_units,
|
profiled_units = profiled_units,
|
||||||
isf = spzeros(Float64, length(lines), length(buses) - 1),
|
isf = spzeros(Float64, length(lines), length(buses) - 1),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ mutable struct Bus
|
|||||||
name::String
|
name::String
|
||||||
offset::Int
|
offset::Int
|
||||||
load::Vector{Float64}
|
load::Vector{Float64}
|
||||||
units::Vector
|
thermal_units::Vector
|
||||||
price_sensitive_loads::Vector
|
price_sensitive_loads::Vector
|
||||||
profiled_units::Vector
|
profiled_units::Vector
|
||||||
end
|
end
|
||||||
@@ -25,11 +25,11 @@ Base.@kwdef mutable struct Reserve
|
|||||||
name::String
|
name::String
|
||||||
type::String
|
type::String
|
||||||
amount::Vector{Float64}
|
amount::Vector{Float64}
|
||||||
units::Vector
|
thermal_units::Vector
|
||||||
shortfall_penalty::Float64
|
shortfall_penalty::Float64
|
||||||
end
|
end
|
||||||
|
|
||||||
mutable struct Unit
|
mutable struct ThermalUnit
|
||||||
name::String
|
name::String
|
||||||
bus::Bus
|
bus::Bus
|
||||||
max_power::Vector{Float64}
|
max_power::Vector{Float64}
|
||||||
@@ -64,7 +64,7 @@ end
|
|||||||
mutable struct Contingency
|
mutable struct Contingency
|
||||||
name::String
|
name::String
|
||||||
lines::Vector{TransmissionLine}
|
lines::Vector{TransmissionLine}
|
||||||
units::Vector{Unit}
|
thermal_units::Vector{ThermalUnit}
|
||||||
end
|
end
|
||||||
|
|
||||||
mutable struct PriceSensitiveLoad
|
mutable struct PriceSensitiveLoad
|
||||||
@@ -95,13 +95,13 @@ Base.@kwdef mutable struct UnitCommitmentScenario
|
|||||||
price_sensitive_loads_by_name::Dict{AbstractString,PriceSensitiveLoad}
|
price_sensitive_loads_by_name::Dict{AbstractString,PriceSensitiveLoad}
|
||||||
price_sensitive_loads::Vector{PriceSensitiveLoad}
|
price_sensitive_loads::Vector{PriceSensitiveLoad}
|
||||||
probability::Float64
|
probability::Float64
|
||||||
reserves_by_name::Dict{AbstractString,Reserve}
|
|
||||||
reserves::Vector{Reserve}
|
|
||||||
time::Int
|
|
||||||
units_by_name::Dict{AbstractString,Unit}
|
|
||||||
units::Vector{Unit}
|
|
||||||
profiled_units_by_name::Dict{AbstractString,ProfiledUnit}
|
profiled_units_by_name::Dict{AbstractString,ProfiledUnit}
|
||||||
profiled_units::Vector{ProfiledUnit}
|
profiled_units::Vector{ProfiledUnit}
|
||||||
|
reserves_by_name::Dict{AbstractString,Reserve}
|
||||||
|
reserves::Vector{Reserve}
|
||||||
|
thermal_units_by_name::Dict{AbstractString,ThermalUnit}
|
||||||
|
thermal_units::Vector{ThermalUnit}
|
||||||
|
time::Int
|
||||||
end
|
end
|
||||||
|
|
||||||
Base.@kwdef mutable struct UnitCommitmentInstance
|
Base.@kwdef mutable struct UnitCommitmentInstance
|
||||||
@@ -113,12 +113,12 @@ function Base.show(io::IO, instance::UnitCommitmentInstance)
|
|||||||
sc = instance.scenarios[1]
|
sc = instance.scenarios[1]
|
||||||
print(io, "UnitCommitmentInstance(")
|
print(io, "UnitCommitmentInstance(")
|
||||||
print(io, "$(length(instance.scenarios)) scenarios, ")
|
print(io, "$(length(instance.scenarios)) scenarios, ")
|
||||||
print(io, "$(length(sc.units)) units, ")
|
print(io, "$(length(sc.thermal_units)) thermal units, ")
|
||||||
|
print(io, "$(length(sc.profiled_units)) profiled units, ")
|
||||||
print(io, "$(length(sc.buses)) buses, ")
|
print(io, "$(length(sc.buses)) buses, ")
|
||||||
print(io, "$(length(sc.lines)) lines, ")
|
print(io, "$(length(sc.lines)) lines, ")
|
||||||
print(io, "$(length(sc.contingencies)) contingencies, ")
|
print(io, "$(length(sc.contingencies)) contingencies, ")
|
||||||
print(io, "$(length(sc.price_sensitive_loads)) price sensitive loads, ")
|
print(io, "$(length(sc.price_sensitive_loads)) price sensitive loads, ")
|
||||||
print(io, "$(length(sc.profiled_units)) profiled units, ")
|
|
||||||
print(io, "$(instance.time) time steps")
|
print(io, "$(instance.time) time steps")
|
||||||
print(io, ")")
|
print(io, ")")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ function _aelmp_check_parameters(
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
all_units = sc.units
|
all_units = sc.thermal_units
|
||||||
# CHECK: model cannot handle non-fast-starts (MISO Phase I: can ONLY solve fast-starts)
|
# CHECK: model cannot handle non-fast-starts (MISO Phase I: can ONLY solve fast-starts)
|
||||||
if any(u -> u.min_uptime > 1 || u.min_downtime > 1, all_units)
|
if any(u -> u.min_uptime > 1 || u.min_downtime > 1, all_units)
|
||||||
error(
|
error(
|
||||||
@@ -159,25 +159,25 @@ function _modify_scenario!(
|
|||||||
if !method.allow_offline_participation
|
if !method.allow_offline_participation
|
||||||
# 1. remove (if NOT allowing) the offline generators
|
# 1. remove (if NOT allowing) the offline generators
|
||||||
units_to_remove = []
|
units_to_remove = []
|
||||||
for unit in sc.units
|
for unit in sc.thermal_units
|
||||||
# remove based on the solved UC model result
|
# remove based on the solved UC model result
|
||||||
# remove the unit if it is never on
|
# remove the unit if it is never on
|
||||||
if all(t -> value(model[:is_on][unit.name, t]) == 0, sc.time)
|
if all(t -> value(model[:is_on][unit.name, t]) == 0, sc.time)
|
||||||
# unregister from the bus
|
# unregister from the bus
|
||||||
filter!(x -> x.name != unit.name, unit.bus.units)
|
filter!(x -> x.name != unit.name, unit.bus.thermal_units)
|
||||||
# unregister from the reserve
|
# unregister from the reserve
|
||||||
for r in unit.reserves
|
for r in unit.reserves
|
||||||
filter!(x -> x.name != unit.name, r.units)
|
filter!(x -> x.name != unit.name, r.thermal_units)
|
||||||
end
|
end
|
||||||
# append the name to the remove list
|
# append the name to the remove list
|
||||||
push!(units_to_remove, unit.name)
|
push!(units_to_remove, unit.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# unregister the units from the remove list
|
# unregister the units from the remove list
|
||||||
filter!(x -> !(x.name in units_to_remove), sc.units)
|
filter!(x -> !(x.name in units_to_remove), sc.thermal_units)
|
||||||
end
|
end
|
||||||
|
|
||||||
for unit in sc.units
|
for unit in sc.thermal_units
|
||||||
# 2. set min generation requirement to 0 by adding 0 to production curve and cost
|
# 2. set min generation requirement to 0 by adding 0 to production curve and cost
|
||||||
# min_power & min_costs are vectors with dimension T
|
# min_power & min_costs are vectors with dimension T
|
||||||
if unit.min_power[1] != 0
|
if unit.min_power[1] != 0
|
||||||
@@ -207,5 +207,6 @@ function _modify_scenario!(
|
|||||||
unit.startup_categories =
|
unit.startup_categories =
|
||||||
StartupCategory[StartupCategory(0, first_startup_cost)]
|
StartupCategory[StartupCategory(0, first_startup_cost)]
|
||||||
end
|
end
|
||||||
return sc.units_by_name = Dict(g.name => g for g in sc.units)
|
return sc.thermal_units_by_name =
|
||||||
|
Dict(g.name => g for g in sc.thermal_units)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ function build_model(;
|
|||||||
end
|
end
|
||||||
model[:obj] = AffExpr()
|
model[:obj] = AffExpr()
|
||||||
model[:instance] = instance
|
model[:instance] = instance
|
||||||
for g in instance.scenarios[1].units
|
for g in instance.scenarios[1].thermal_units
|
||||||
_add_unit_commitment!(model, g, formulation)
|
_add_unit_commitment!(model, g, formulation)
|
||||||
end
|
end
|
||||||
for sc in instance.scenarios
|
for sc in instance.scenarios
|
||||||
@@ -93,7 +93,7 @@ function build_model(;
|
|||||||
for ps in sc.price_sensitive_loads
|
for ps in sc.price_sensitive_loads
|
||||||
_add_price_sensitive_load!(model, ps, sc)
|
_add_price_sensitive_load!(model, ps, sc)
|
||||||
end
|
end
|
||||||
for g in sc.units
|
for g in sc.thermal_units
|
||||||
_add_unit_dispatch!(model, g, formulation, sc)
|
_add_unit_dispatch!(model, g, formulation, sc)
|
||||||
end
|
end
|
||||||
for pu in sc.profiled_units
|
for pu in sc.profiled_units
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::ArrCon2000.Ramping,
|
formulation_ramping::ArrCon2000.Ramping,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_production_piecewise_linear_eqs!(
|
function _add_production_piecewise_linear_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_pwl_costs::CarArr2006.PwlCosts,
|
formulation_pwl_costs::CarArr2006.PwlCosts,
|
||||||
formulation_status_vars::StatusVarsFormulation,
|
formulation_status_vars::StatusVarsFormulation,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::DamKucRajAta2016.Ramping,
|
formulation_ramping::DamKucRajAta2016.Ramping,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_production_vars!(
|
function _add_production_vars!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
@@ -21,7 +21,7 @@ end
|
|||||||
|
|
||||||
function _add_production_limit_eqs!(
|
function _add_production_limit_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_production_piecewise_linear_eqs!(
|
function _add_production_piecewise_linear_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_pwl_costs::Gar1962.PwlCosts,
|
formulation_pwl_costs::Gar1962.PwlCosts,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_status_vars!(
|
function _add_status_vars!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
is_on = _init(model, :is_on)
|
is_on = _init(model, :is_on)
|
||||||
@@ -27,7 +27,7 @@ end
|
|||||||
|
|
||||||
function _add_status_eqs!(
|
function _add_status_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
eq_binary_link = _init(model, :eq_binary_link)
|
eq_binary_link = _init(model, :eq_binary_link)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_production_piecewise_linear_eqs!(
|
function _add_production_piecewise_linear_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_pwl_costs::KnuOstWat2018.PwlCosts,
|
formulation_pwl_costs::KnuOstWat2018.PwlCosts,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::MorLatRam2013.Ramping,
|
formulation_ramping::MorLatRam2013.Ramping,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_startup_cost_eqs!(
|
function _add_startup_cost_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation::MorLatRam2013.StartupCosts,
|
formulation::MorLatRam2013.StartupCosts,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
eq_startup_choose = _init(model, :eq_startup_choose)
|
eq_startup_choose = _init(model, :eq_startup_choose)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation_prod_vars::Gar1962.ProdVars,
|
formulation_prod_vars::Gar1962.ProdVars,
|
||||||
formulation_ramping::PanGua2016.Ramping,
|
formulation_ramping::PanGua2016.Ramping,
|
||||||
formulation_status_vars::Gar1962.StatusVars,
|
formulation_status_vars::Gar1962.StatusVars,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
::Gar1962.ProdVars,
|
::Gar1962.ProdVars,
|
||||||
::WanHob2016.Ramping,
|
::WanHob2016.Ramping,
|
||||||
::Gar1962.StatusVars,
|
::Gar1962.StatusVars,
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ function _add_spinning_reserve_eqs!(
|
|||||||
model,
|
model,
|
||||||
sum(
|
sum(
|
||||||
model[:reserve][sc.name, r.name, g.name, t] for
|
model[:reserve][sc.name, r.name, g.name, t] for
|
||||||
g in r.units
|
g in r.thermal_units
|
||||||
) + model[:reserve_shortfall][sc.name, r.name, t] >=
|
) + model[:reserve_shortfall][sc.name, r.name, t] >=
|
||||||
r.amount[t]
|
r.amount[t]
|
||||||
)
|
)
|
||||||
@@ -91,7 +91,7 @@ function _add_flexiramp_reserve_eqs!(
|
|||||||
model,
|
model,
|
||||||
sum(
|
sum(
|
||||||
model[:upflexiramp][sc.name, r.name, g.name, t] for
|
model[:upflexiramp][sc.name, r.name, g.name, t] for
|
||||||
g in r.units
|
g in r.thermal_units
|
||||||
) + model[:upflexiramp_shortfall][sc.name, r.name, t] >=
|
) + model[:upflexiramp_shortfall][sc.name, r.name, t] >=
|
||||||
r.amount[t]
|
r.amount[t]
|
||||||
)
|
)
|
||||||
@@ -100,7 +100,7 @@ function _add_flexiramp_reserve_eqs!(
|
|||||||
model,
|
model,
|
||||||
sum(
|
sum(
|
||||||
model[:dwflexiramp][sc.name, r.name, g.name, t] for
|
model[:dwflexiramp][sc.name, r.name, g.name, t] for
|
||||||
g in r.units
|
g in r.thermal_units
|
||||||
) + model[:dwflexiramp_shortfall][sc.name, r.name, t] >=
|
) + model[:dwflexiramp_shortfall][sc.name, r.name, t] >=
|
||||||
r.amount[t]
|
r.amount[t]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# related to the binary commitment, startup and shutdown decisions of units
|
# related to the binary commitment, startup and shutdown decisions of units
|
||||||
function _add_unit_commitment!(
|
function _add_unit_commitment!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation::Formulation,
|
formulation::Formulation,
|
||||||
)
|
)
|
||||||
if !all(g.must_run) && any(g.must_run)
|
if !all(g.must_run) && any(g.must_run)
|
||||||
@@ -31,7 +31,7 @@ end
|
|||||||
# related to the continuous dispatch decisions of units
|
# related to the continuous dispatch decisions of units
|
||||||
function _add_unit_dispatch!(
|
function _add_unit_dispatch!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation::Formulation,
|
formulation::Formulation,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)
|
)
|
||||||
@@ -64,11 +64,11 @@ function _add_unit_dispatch!(
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
_is_initially_on(g::Unit)::Float64 = (g.initial_status > 0 ? 1.0 : 0.0)
|
_is_initially_on(g::ThermalUnit)::Float64 = (g.initial_status > 0 ? 1.0 : 0.0)
|
||||||
|
|
||||||
function _add_spinning_reserve_vars!(
|
function _add_spinning_reserve_vars!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
reserve = _init(model, :reserve)
|
reserve = _init(model, :reserve)
|
||||||
@@ -92,7 +92,7 @@ end
|
|||||||
|
|
||||||
function _add_flexiramp_reserve_vars!(
|
function _add_flexiramp_reserve_vars!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
upflexiramp = _init(model, :upflexiramp)
|
upflexiramp = _init(model, :upflexiramp)
|
||||||
@@ -128,7 +128,7 @@ function _add_flexiramp_reserve_vars!(
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
function _add_startup_shutdown_vars!(model::JuMP.Model, g::Unit)::Nothing
|
function _add_startup_shutdown_vars!(model::JuMP.Model, g::ThermalUnit)::Nothing
|
||||||
startup = _init(model, :startup)
|
startup = _init(model, :startup)
|
||||||
for t in 1:model[:instance].time
|
for t in 1:model[:instance].time
|
||||||
for s in 1:length(g.startup_categories)
|
for s in 1:length(g.startup_categories)
|
||||||
@@ -140,7 +140,7 @@ end
|
|||||||
|
|
||||||
function _add_startup_shutdown_limit_eqs!(
|
function _add_startup_shutdown_limit_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
eq_shutdown_limit = _init(model, :eq_shutdown_limit)
|
eq_shutdown_limit = _init(model, :eq_shutdown_limit)
|
||||||
@@ -179,7 +179,7 @@ end
|
|||||||
|
|
||||||
function _add_ramp_eqs!(
|
function _add_ramp_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
formulation::RampingFormulation,
|
formulation::RampingFormulation,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
@@ -224,7 +224,10 @@ function _add_ramp_eqs!(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function _add_min_uptime_downtime_eqs!(model::JuMP.Model, g::Unit)::Nothing
|
function _add_min_uptime_downtime_eqs!(
|
||||||
|
model::JuMP.Model,
|
||||||
|
g::ThermalUnit,
|
||||||
|
)::Nothing
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
switch_off = model[:switch_off]
|
switch_off = model[:switch_off]
|
||||||
switch_on = model[:switch_on]
|
switch_on = model[:switch_on]
|
||||||
@@ -269,7 +272,7 @@ end
|
|||||||
|
|
||||||
function _add_net_injection_eqs!(
|
function _add_net_injection_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::Unit,
|
g::ThermalUnit,
|
||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
expr_net_injection = model[:expr_net_injection]
|
expr_net_injection = model[:expr_net_injection]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ function fix!(model::JuMP.Model, solution::AbstractDict)::Nothing
|
|||||||
prod_above = model[:prod_above]
|
prod_above = model[:prod_above]
|
||||||
reserve = model[:reserve]
|
reserve = model[:reserve]
|
||||||
for sc in instance.scenarios
|
for sc in instance.scenarios
|
||||||
for g in sc.units
|
for g in sc.thermal_units
|
||||||
for t in 1:T
|
for t in 1:T
|
||||||
is_on_value = round(solution[sc.name]["Is on"][g.name][t])
|
is_on_value = round(solution[sc.name]["Is on"][g.name][t])
|
||||||
prod_value = round(
|
prod_value = round(
|
||||||
@@ -33,7 +33,7 @@ function fix!(model::JuMP.Model, solution::AbstractDict)::Nothing
|
|||||||
end
|
end
|
||||||
for r in sc.reserves
|
for r in sc.reserves
|
||||||
r.type == "spinning" || continue
|
r.type == "spinning" || continue
|
||||||
for g in r.units
|
for g in r.thermal_units
|
||||||
for t in 1:T
|
for t in 1:T
|
||||||
reserve_value = round(
|
reserve_value = round(
|
||||||
solution[sc.name]["Spinning reserve (MW)"][r.name][g.name][t],
|
solution[sc.name]["Spinning reserve (MW)"][r.name][g.name][t],
|
||||||
|
|||||||
@@ -65,17 +65,21 @@ function solution(model::JuMP.Model)::OrderedDict
|
|||||||
sol = OrderedDict()
|
sol = OrderedDict()
|
||||||
for sc in instance.scenarios
|
for sc in instance.scenarios
|
||||||
sol[sc.name] = OrderedDict()
|
sol[sc.name] = OrderedDict()
|
||||||
if !isempty(sc.units)
|
if !isempty(sc.thermal_units)
|
||||||
sol[sc.name]["Production (MW)"] =
|
sol[sc.name]["Production (MW)"] = OrderedDict(
|
||||||
OrderedDict(g.name => production(g, sc) for g in sc.units)
|
g.name => production(g, sc) for g in sc.thermal_units
|
||||||
sol[sc.name]["Production cost (\$)"] =
|
)
|
||||||
OrderedDict(g.name => production_cost(g, sc) for g in sc.units)
|
sol[sc.name]["Production cost (\$)"] = OrderedDict(
|
||||||
sol[sc.name]["Startup cost (\$)"] =
|
g.name => production_cost(g, sc) for g in sc.thermal_units
|
||||||
OrderedDict(g.name => startup_cost(g, sc) for g in sc.units)
|
)
|
||||||
sol[sc.name]["Is on"] = timeseries(model[:is_on], sc.units)
|
sol[sc.name]["Startup cost (\$)"] = OrderedDict(
|
||||||
sol[sc.name]["Switch on"] = timeseries(model[:switch_on], sc.units)
|
g.name => startup_cost(g, sc) for g in sc.thermal_units
|
||||||
|
)
|
||||||
|
sol[sc.name]["Is on"] = timeseries(model[:is_on], sc.thermal_units)
|
||||||
|
sol[sc.name]["Switch on"] =
|
||||||
|
timeseries(model[:switch_on], sc.thermal_units)
|
||||||
sol[sc.name]["Switch off"] =
|
sol[sc.name]["Switch off"] =
|
||||||
timeseries(model[:switch_off], sc.units)
|
timeseries(model[:switch_off], sc.thermal_units)
|
||||||
sol[sc.name]["Net injection (MW)"] =
|
sol[sc.name]["Net injection (MW)"] =
|
||||||
timeseries(model[:net_injection], sc.buses, sc = sc)
|
timeseries(model[:net_injection], sc.buses, sc = sc)
|
||||||
sol[sc.name]["Load curtail (MW)"] =
|
sol[sc.name]["Load curtail (MW)"] =
|
||||||
@@ -103,7 +107,7 @@ function solution(model::JuMP.Model)::OrderedDict
|
|||||||
r.name => OrderedDict(
|
r.name => OrderedDict(
|
||||||
g.name => [
|
g.name => [
|
||||||
value(model[:reserve][sc.name, r.name, g.name, t]) for t in 1:instance.time
|
value(model[:reserve][sc.name, r.name, g.name, t]) for t in 1:instance.time
|
||||||
] for g in r.units
|
] for g in r.thermal_units
|
||||||
) for r in sc.reserves if r.type == "spinning"
|
) for r in sc.reserves if r.type == "spinning"
|
||||||
)
|
)
|
||||||
sol[sc.name]["Spinning reserve shortfall (MW)"] = OrderedDict(
|
sol[sc.name]["Spinning reserve shortfall (MW)"] = OrderedDict(
|
||||||
@@ -116,7 +120,7 @@ function solution(model::JuMP.Model)::OrderedDict
|
|||||||
r.name => OrderedDict(
|
r.name => OrderedDict(
|
||||||
g.name => [
|
g.name => [
|
||||||
value(model[:upflexiramp][sc.name, r.name, g.name, t]) for t in 1:instance.time
|
value(model[:upflexiramp][sc.name, r.name, g.name, t]) for t in 1:instance.time
|
||||||
] for g in r.units
|
] for g in r.thermal_units
|
||||||
) for r in sc.reserves if r.type == "flexiramp"
|
) for r in sc.reserves if r.type == "flexiramp"
|
||||||
)
|
)
|
||||||
sol[sc.name]["Up-flexiramp shortfall (MW)"] = OrderedDict(
|
sol[sc.name]["Up-flexiramp shortfall (MW)"] = OrderedDict(
|
||||||
@@ -128,7 +132,7 @@ function solution(model::JuMP.Model)::OrderedDict
|
|||||||
r.name => OrderedDict(
|
r.name => OrderedDict(
|
||||||
g.name => [
|
g.name => [
|
||||||
value(model[:dwflexiramp][sc.name, r.name, g.name, t]) for t in 1:instance.time
|
value(model[:dwflexiramp][sc.name, r.name, g.name, t]) for t in 1:instance.time
|
||||||
] for g in r.units
|
] for g in r.thermal_units
|
||||||
) for r in sc.reserves if r.type == "flexiramp"
|
) for r in sc.reserves if r.type == "flexiramp"
|
||||||
)
|
)
|
||||||
sol[sc.name]["Down-flexiramp shortfall (MW)"] = OrderedDict(
|
sol[sc.name]["Down-flexiramp shortfall (MW)"] = OrderedDict(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
function set_warm_start!(model::JuMP.Model, solution::AbstractDict)::Nothing
|
function set_warm_start!(model::JuMP.Model, solution::AbstractDict)::Nothing
|
||||||
instance, T = model[:instance], model[:instance].time
|
instance, T = model[:instance], model[:instance].time
|
||||||
is_on = model[:is_on]
|
is_on = model[:is_on]
|
||||||
for g in instance.units
|
for g in instance.thermal_units
|
||||||
for t in 1:T
|
for t in 1:T
|
||||||
JuMP.set_start_value(is_on[g.name, t], solution["Is on"][g.name][t])
|
JuMP.set_start_value(is_on[g.name, t], solution["Is on"][g.name][t])
|
||||||
JuMP.set_start_value(
|
JuMP.set_start_value(
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ function generate_initial_conditions!(
|
|||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
optimizer,
|
optimizer,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
G = sc.units
|
G = sc.thermal_units
|
||||||
B = sc.buses
|
B = sc.buses
|
||||||
t = 1
|
t = 1
|
||||||
mip = JuMP.Model(optimizer)
|
mip = JuMP.Model(optimizer)
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ function _randomize_costs(
|
|||||||
sc::UnitCommitmentScenario,
|
sc::UnitCommitmentScenario,
|
||||||
distribution,
|
distribution,
|
||||||
)::Nothing
|
)::Nothing
|
||||||
for unit in sc.units
|
for unit in sc.thermal_units
|
||||||
α = rand(rng, distribution)
|
α = rand(rng, distribution)
|
||||||
unit.min_power_cost *= α
|
unit.min_power_cost *= α
|
||||||
for k in unit.cost_segments
|
for k in unit.cost_segments
|
||||||
@@ -168,7 +168,7 @@ function _randomize_load_profile(
|
|||||||
)
|
)
|
||||||
push!(system_load, system_load[t-1] * gamma)
|
push!(system_load, system_load[t-1] * gamma)
|
||||||
end
|
end
|
||||||
capacity = sum(maximum(u.max_power) for u in sc.units)
|
capacity = sum(maximum(u.max_power) for u in sc.thermal_units)
|
||||||
peak_load = rand(rng, params.peak_load) * capacity
|
peak_load = rand(rng, params.peak_load) * capacity
|
||||||
system_load = system_load ./ maximum(system_load) .* peak_load
|
system_load = system_load ./ maximum(system_load) .* peak_load
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function slice(
|
|||||||
for r in sc.reserves
|
for r in sc.reserves
|
||||||
r.amount = r.amount[range]
|
r.amount = r.amount[range]
|
||||||
end
|
end
|
||||||
for u in sc.units
|
for u in sc.thermal_units
|
||||||
u.max_power = u.max_power[range]
|
u.max_power = u.max_power[range]
|
||||||
u.min_power = u.min_power[range]
|
u.min_power = u.min_power[range]
|
||||||
u.must_run = u.must_run[range]
|
u.must_run = u.must_run[range]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Returns the number of validation errors found.
|
|||||||
function repair!(sc::UnitCommitmentScenario)::Int
|
function repair!(sc::UnitCommitmentScenario)::Int
|
||||||
n_errors = 0
|
n_errors = 0
|
||||||
|
|
||||||
for g in sc.units
|
for g in sc.thermal_units
|
||||||
|
|
||||||
# Startup costs and delays must be increasing
|
# Startup costs and delays must be increasing
|
||||||
for s in 2:length(g.startup_categories)
|
for s in 2:length(g.startup_categories)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ end
|
|||||||
function _validate_units(instance::UnitCommitmentInstance, solution; tol = 0.01)
|
function _validate_units(instance::UnitCommitmentInstance, solution; tol = 0.01)
|
||||||
err_count = 0
|
err_count = 0
|
||||||
for sc in instance.scenarios
|
for sc in instance.scenarios
|
||||||
for unit in sc.units
|
for unit in sc.thermal_units
|
||||||
production = solution[sc.name]["Production (MW)"][unit.name]
|
production = solution[sc.name]["Production (MW)"][unit.name]
|
||||||
reserve = [0.0 for _ in 1:instance.time]
|
reserve = [0.0 for _ in 1:instance.time]
|
||||||
spinning_reserves =
|
spinning_reserves =
|
||||||
@@ -114,7 +114,7 @@ function _validate_units(instance::UnitCommitmentInstance, solution; tol = 0.01)
|
|||||||
# Verify reserve eligibility
|
# Verify reserve eligibility
|
||||||
for r in sc.reserves
|
for r in sc.reserves
|
||||||
if r.type == "spinning"
|
if r.type == "spinning"
|
||||||
if unit ∉ r.units && (
|
if unit ∉ r.thermal_units && (
|
||||||
unit in keys(
|
unit in keys(
|
||||||
solution[sc.name]["Spinning reserve (MW)"][r.name],
|
solution[sc.name]["Spinning reserve (MW)"][r.name],
|
||||||
)
|
)
|
||||||
@@ -324,7 +324,7 @@ function _validate_reserve_and_demand(instance, solution, tol = 0.01)
|
|||||||
end
|
end
|
||||||
production = sum(
|
production = sum(
|
||||||
solution[sc.name]["Production (MW)"][g.name][t] for
|
solution[sc.name]["Production (MW)"][g.name][t] for
|
||||||
g in sc.units
|
g in sc.thermal_units
|
||||||
)
|
)
|
||||||
if "Load curtail (MW)" in keys(solution)
|
if "Load curtail (MW)" in keys(solution)
|
||||||
load_curtail = sum(
|
load_curtail = sum(
|
||||||
@@ -352,7 +352,7 @@ function _validate_reserve_and_demand(instance, solution, tol = 0.01)
|
|||||||
if r.type == "spinning"
|
if r.type == "spinning"
|
||||||
provided = sum(
|
provided = sum(
|
||||||
solution[sc.name]["Spinning reserve (MW)"][r.name][g.name][t]
|
solution[sc.name]["Spinning reserve (MW)"][r.name][g.name][t]
|
||||||
for g in r.units
|
for g in r.thermal_units
|
||||||
)
|
)
|
||||||
shortfall =
|
shortfall =
|
||||||
solution[sc.name]["Spinning reserve shortfall (MW)"][r.name][t]
|
solution[sc.name]["Spinning reserve shortfall (MW)"][r.name][t]
|
||||||
@@ -371,7 +371,7 @@ function _validate_reserve_and_demand(instance, solution, tol = 0.01)
|
|||||||
elseif r.type == "flexiramp"
|
elseif r.type == "flexiramp"
|
||||||
upflexiramp = sum(
|
upflexiramp = sum(
|
||||||
solution[sc.name]["Up-flexiramp (MW)"][r.name][g.name][t]
|
solution[sc.name]["Up-flexiramp (MW)"][r.name][g.name][t]
|
||||||
for g in r.units
|
for g in r.thermal_units
|
||||||
)
|
)
|
||||||
upflexiramp_shortfall =
|
upflexiramp_shortfall =
|
||||||
solution[sc.name]["Up-flexiramp shortfall (MW)"][r.name][t]
|
solution[sc.name]["Up-flexiramp shortfall (MW)"][r.name][t]
|
||||||
@@ -389,7 +389,7 @@ function _validate_reserve_and_demand(instance, solution, tol = 0.01)
|
|||||||
|
|
||||||
dwflexiramp = sum(
|
dwflexiramp = sum(
|
||||||
solution[sc.name]["Down-flexiramp (MW)"][r.name][g.name][t]
|
solution[sc.name]["Down-flexiramp (MW)"][r.name][g.name][t]
|
||||||
for g in r.units
|
for g in r.thermal_units
|
||||||
)
|
)
|
||||||
dwflexiramp_shortfall =
|
dwflexiramp_shortfall =
|
||||||
solution[sc.name]["Down-flexiramp shortfall (MW)"][r.name][t]
|
solution[sc.name]["Down-flexiramp shortfall (MW)"][r.name][t]
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
|
|||||||
@test length(instance.scenarios) == 1
|
@test length(instance.scenarios) == 1
|
||||||
sc = instance.scenarios[1]
|
sc = instance.scenarios[1]
|
||||||
@test length(sc.reserves_by_name["r1"].amount) == 4
|
@test length(sc.reserves_by_name["r1"].amount) == 4
|
||||||
@test sc.units_by_name["g2"].reserves[1].name == "r1"
|
@test sc.thermal_units_by_name["g2"].reserves[1].name == "r1"
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "read v0.3" begin
|
@testset "read v0.3" begin
|
||||||
instance = UnitCommitment.read("$FIXTURES/ucjl-0.3.json.gz")
|
instance = UnitCommitment.read("$FIXTURES/ucjl-0.3.json.gz")
|
||||||
@test length(instance.scenarios) == 1
|
@test length(instance.scenarios) == 1
|
||||||
sc = instance.scenarios[1]
|
sc = instance.scenarios[1]
|
||||||
@test length(sc.units) == 6
|
@test length(sc.thermal_units) == 6
|
||||||
@test length(sc.buses) == 14
|
@test length(sc.buses) == 14
|
||||||
@test length(sc.lines) == 20
|
@test length(sc.lines) == 20
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
|
|||||||
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
|
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
|
||||||
|
|
||||||
@test repr(instance) == (
|
@test repr(instance) == (
|
||||||
"UnitCommitmentInstance(1 scenarios, 6 units, 14 buses, " *
|
"UnitCommitmentInstance(1 scenarios, 6 thermal units, 0 profiled units, 14 buses, " *
|
||||||
"20 lines, 19 contingencies, 1 price sensitive loads, 0 profiled units, 4 time steps)"
|
"20 lines, 19 contingencies, 1 price sensitive loads, 4 time steps)"
|
||||||
)
|
)
|
||||||
|
|
||||||
@test length(instance.scenarios) == 1
|
@test length(instance.scenarios) == 1
|
||||||
sc = instance.scenarios[1]
|
sc = instance.scenarios[1]
|
||||||
@test length(sc.lines) == 20
|
@test length(sc.lines) == 20
|
||||||
@test length(sc.buses) == 14
|
@test length(sc.buses) == 14
|
||||||
@test length(sc.units) == 6
|
@test length(sc.thermal_units) == 6
|
||||||
@test length(sc.contingencies) == 19
|
@test length(sc.contingencies) == 19
|
||||||
@test length(sc.price_sensitive_loads) == 1
|
@test length(sc.price_sensitive_loads) == 1
|
||||||
@test instance.time == 4
|
@test instance.time == 4
|
||||||
@@ -49,7 +49,7 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
|
|||||||
@test sc.reserves[1].amount == [100.0, 100.0, 100.0, 100.0]
|
@test sc.reserves[1].amount == [100.0, 100.0, 100.0, 100.0]
|
||||||
@test sc.reserves_by_name["r1"].name == "r1"
|
@test sc.reserves_by_name["r1"].name == "r1"
|
||||||
|
|
||||||
unit = sc.units[1]
|
unit = sc.thermal_units[1]
|
||||||
@test unit.name == "g1"
|
@test unit.name == "g1"
|
||||||
@test unit.bus.name == "b1"
|
@test unit.bus.name == "b1"
|
||||||
@test unit.ramp_up_limit == 1e6
|
@test unit.ramp_up_limit == 1e6
|
||||||
@@ -76,14 +76,14 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
|
|||||||
@test unit.startup_categories[2].cost == 1500.0
|
@test unit.startup_categories[2].cost == 1500.0
|
||||||
@test unit.startup_categories[3].cost == 2000.0
|
@test unit.startup_categories[3].cost == 2000.0
|
||||||
@test length(unit.reserves) == 0
|
@test length(unit.reserves) == 0
|
||||||
@test sc.units_by_name["g1"].name == "g1"
|
@test sc.thermal_units_by_name["g1"].name == "g1"
|
||||||
|
|
||||||
unit = sc.units[2]
|
unit = sc.thermal_units[2]
|
||||||
@test unit.name == "g2"
|
@test unit.name == "g2"
|
||||||
@test unit.must_run == [false for t in 1:4]
|
@test unit.must_run == [false for t in 1:4]
|
||||||
@test length(unit.reserves) == 1
|
@test length(unit.reserves) == 1
|
||||||
|
|
||||||
unit = sc.units[3]
|
unit = sc.thermal_units[3]
|
||||||
@test unit.name == "g3"
|
@test unit.name == "g3"
|
||||||
@test unit.bus.name == "b3"
|
@test unit.bus.name == "b3"
|
||||||
@test unit.ramp_up_limit == 70.0
|
@test unit.ramp_up_limit == 70.0
|
||||||
@@ -106,7 +106,7 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
|
|||||||
@test unit.reserves[1].name == "r1"
|
@test unit.reserves[1].name == "r1"
|
||||||
|
|
||||||
@test sc.contingencies[1].lines == [sc.lines[1]]
|
@test sc.contingencies[1].lines == [sc.lines[1]]
|
||||||
@test sc.contingencies[1].units == []
|
@test sc.contingencies[1].thermal_units == []
|
||||||
@test sc.contingencies[1].name == "c1"
|
@test sc.contingencies[1].name == "c1"
|
||||||
@test sc.contingencies_by_name["c1"].name == "c1"
|
@test sc.contingencies_by_name["c1"].name == "c1"
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ end
|
|||||||
@testset "read_benchmark sub-hourly" begin
|
@testset "read_benchmark sub-hourly" begin
|
||||||
instance = UnitCommitment.read("$FIXTURES/case14-sub-hourly.json.gz")
|
instance = UnitCommitment.read("$FIXTURES/case14-sub-hourly.json.gz")
|
||||||
@test instance.time == 4
|
@test instance.time == 4
|
||||||
unit = instance.scenarios[1].units[1]
|
unit = instance.scenarios[1].thermal_units[1]
|
||||||
@test unit.name == "g1"
|
@test unit.name == "g1"
|
||||||
@test unit.min_uptime == 2
|
@test unit.min_uptime == 2
|
||||||
@test unit.min_downtime == 2
|
@test unit.min_downtime == 2
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using UnitCommitment, Cbc, JuMP
|
|||||||
optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0)
|
optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0)
|
||||||
sc = instance.scenarios[1]
|
sc = instance.scenarios[1]
|
||||||
# All units should have unknown initial conditions
|
# All units should have unknown initial conditions
|
||||||
for g in sc.units
|
for g in sc.thermal_units
|
||||||
@test g.initial_power === nothing
|
@test g.initial_power === nothing
|
||||||
@test g.initial_status === nothing
|
@test g.initial_status === nothing
|
||||||
end
|
end
|
||||||
@@ -19,7 +19,7 @@ using UnitCommitment, Cbc, JuMP
|
|||||||
UnitCommitment.generate_initial_conditions!(sc, optimizer)
|
UnitCommitment.generate_initial_conditions!(sc, optimizer)
|
||||||
|
|
||||||
# All units should now have known initial conditions
|
# All units should now have known initial conditions
|
||||||
for g in sc.units
|
for g in sc.thermal_units
|
||||||
@test g.initial_power !== nothing
|
@test g.initial_power !== nothing
|
||||||
@test g.initial_status !== nothing
|
@test g.initial_status !== nothing
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ test_approx(x, y) = @test isapprox(x, y, atol = 1e-3)
|
|||||||
@testset "cost and load share" begin
|
@testset "cost and load share" begin
|
||||||
sc = get_scenario()
|
sc = get_scenario()
|
||||||
# Check original costs
|
# Check original costs
|
||||||
unit = sc.units[10]
|
unit = sc.thermal_units[10]
|
||||||
test_approx(unit.min_power_cost[1], 825.023)
|
test_approx(unit.min_power_cost[1], 825.023)
|
||||||
test_approx(unit.cost_segments[1].cost[1], 36.659)
|
test_approx(unit.cost_segments[1].cost[1], 36.659)
|
||||||
test_approx(unit.startup_categories[1].cost[1], 7570.42)
|
test_approx(unit.startup_categories[1].cost[1], 7570.42)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
|
|||||||
@test modified.time == 2
|
@test modified.time == 2
|
||||||
@test length(sc.power_balance_penalty) == 2
|
@test length(sc.power_balance_penalty) == 2
|
||||||
@test length(sc.reserves_by_name["r1"].amount) == 2
|
@test length(sc.reserves_by_name["r1"].amount) == 2
|
||||||
for u in sc.units
|
for u in sc.thermal_units
|
||||||
@test length(u.max_power) == 2
|
@test length(u.max_power) == 2
|
||||||
@test length(u.min_power) == 2
|
@test length(u.min_power) == 2
|
||||||
@test length(u.must_run) == 2
|
@test length(u.must_run) == 2
|
||||||
|
|||||||
Reference in New Issue
Block a user