time decomp bug fix

pull/31/head
Jun He 2 years ago
parent ec2d56602b
commit 7201acde78

@ -142,16 +142,28 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
return x
end
time_horizon = json["Parameters"]["Time horizon (min)"]
if time_horizon === nothing
time_horizon = json["Parameters"]["Time (h)"]
if time_horizon === nothing
time_horizon = json["Parameters"]["Time horizon (h)"]
end
time_horizon !== nothing || error("Missing parameter: Time horizon (h)")
if time_horizon !== nothing
time_horizon *= 60
end
end
time_horizon !== nothing || error("Missing parameter: Time horizon (min)")
isinteger(time_horizon) ||
error("Time horizon must be an integer in minutes")
time_horizon = Int(time_horizon)
time_step = scalar(json["Parameters"]["Time step (min)"], default = 60)
(60 % time_step == 0) ||
error("Time step $time_step is not a divisor of 60")
(time_horizon % time_step == 0) || error(
"Time step $time_step is not a divisor of time horizon $time_horizon",
)
time_multiplier = 60 ÷ time_step
T = time_horizon * time_multiplier
T = time_horizon ÷ time_step
probability = json["Parameters"]["Scenario weight"]
probability !== nothing || (probability = 1)
@ -408,6 +420,7 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
reserves = reserves,
reserves_by_name = name_to_reserve,
time = T,
time_step = time_step,
thermal_units_by_name = Dict(g.name => g for g in thermal_units),
thermal_units = thermal_units,
profiled_units_by_name = Dict(pu.name => pu for pu in profiled_units),

@ -104,6 +104,7 @@ Base.@kwdef mutable struct UnitCommitmentScenario
thermal_units_by_name::Dict{AbstractString,ThermalUnit}
thermal_units::Vector{ThermalUnit}
time::Int
time_step::Int
end
Base.@kwdef mutable struct UnitCommitmentInstance

@ -47,7 +47,6 @@ function optimize!(
# get instance total length
T = instance.time
solution = OrderedDict()
iter = 0
if length(instance.scenarios) > 1
for sc in instance.scenarios
solution[sc.name] = OrderedDict()
@ -55,10 +54,6 @@ function optimize!(
end
# for each iteration, time increment by method.time_increment
for t_start in 1:method.time_increment:T
# set the initial status
if iter > 0
_set_initial_status!(instance, solution, method.time_increment)
end
t_end = t_start + method.time_window - 1
# if t_end exceed total T
t_end = t_end > T ? T : t_end
@ -84,7 +79,8 @@ function optimize!(
)
end
end
iter += 1 # increment iteration counter
# set the initial status for the next sub-problem
_set_initial_status!(instance, solution, method.time_increment)
end
return solution
end
@ -96,7 +92,7 @@ end
time_increment::Int,
)
Set the thermal units' initial power levels and statuses based on the first bunch of time slots
Set the thermal units' initial power levels and statuses based on the last bunch of time slots
specified by time_increment in the solution dictionary.
"""
function _set_initial_status!(
@ -114,11 +110,10 @@ function _set_initial_status!(
solution[sc.name]["Thermal production (MW)"][thermal_unit.name]
is_on = solution[sc.name]["Is on"][thermal_unit.name]
end
thermal_unit.initial_power = prod[time_increment]
thermal_unit.initial_power = prod[end]
thermal_unit.initial_status = _determine_initial_status(
thermal_unit.initial_status,
is_on,
time_increment,
is_on[end-time_increment+1:end],
)
end
end
@ -128,16 +123,14 @@ end
_determine_initial_status(
prev_initial_status::Union{Float64,Int},
status_sequence::Vector{Float64},
time_increment::Int,
)::Union{Float64,Int}
Determines a thermal unit's initial status based on its previous initial status, and
the on/off statuses in first bunch of time slots.
the on/off statuses in the last operation.
"""
function _determine_initial_status(
prev_initial_status::Union{Float64,Int},
status_sequence::Vector{Float64},
time_increment::Int,
)::Union{Float64,Int}
# initialize the two flags
on_status = prev_initial_status
@ -147,8 +140,8 @@ function _determine_initial_status(
# if the on_status < 0, set it to 1.0
# at each time if the unit is off, reset on_status, decrement off_status
# if the off_status > 0, set it to -1.0
for t in 1:time_increment
if status_sequence[t] == 1.0
for status in status_sequence
if status == 1.0
on_status = on_status < 0.0 ? 1.0 : on_status + 1.0
off_status = 0.0
else

@ -20,6 +20,7 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
@test length(sc.contingencies) == 19
@test length(sc.price_sensitive_loads) == 1
@test instance.time == 4
@test sc.time_step == 60
@test sc.lines[5].name == "l5"
@test sc.lines[5].source.name == "b2"

@ -5,134 +5,66 @@
using UnitCommitment, DataStructures
@testset "determine_initial_status" begin
t_increment = 24
t_model = 36
hot_start = 100
cold_start = -100
# all on throughout
stat_seq = ones(t_model)
stat_seq = ones(36)
# hot start
new_stat = UnitCommitment._determine_initial_status(
hot_start,
stat_seq,
t_increment,
)
@test new_stat == 124
new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq)
@test new_stat == 136
# cold start
new_stat = UnitCommitment._determine_initial_status(
cold_start,
stat_seq,
t_increment,
)
@test new_stat == 24
new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq)
@test new_stat == 36
# off in the last 12 periods
stat_seq = ones(t_model)
stat_seq = ones(36)
stat_seq[25:end] .= 0
# hot start
new_stat = UnitCommitment._determine_initial_status(
hot_start,
stat_seq,
t_increment,
)
@test new_stat == 124
new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq)
@test new_stat == -12
# cold start
new_stat = UnitCommitment._determine_initial_status(
cold_start,
stat_seq,
t_increment,
)
@test new_stat == 24
new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq)
@test new_stat == -12
# off in one of the first 24 periods
stat_seq = ones(t_model)
# off in one period
stat_seq = ones(36)
stat_seq[10] = 0
# hot start
new_stat = UnitCommitment._determine_initial_status(
hot_start,
stat_seq,
t_increment,
)
@test new_stat == 14
new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq)
@test new_stat == 26
# cold start
new_stat = UnitCommitment._determine_initial_status(
cold_start,
stat_seq,
t_increment,
)
@test new_stat == 14
new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq)
@test new_stat == 26
# off in several of the first 24 periods
stat_seq = ones(t_model)
stat_seq = ones(36)
stat_seq[[10, 11, 20]] .= 0
# hot start
new_stat = UnitCommitment._determine_initial_status(
hot_start,
stat_seq,
t_increment,
)
@test new_stat == 4
new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq)
@test new_stat == 16
# cold start
new_stat = UnitCommitment._determine_initial_status(
cold_start,
stat_seq,
t_increment,
)
@test new_stat == 4
# off in several of the first 24 periods
stat_seq = ones(t_model)
stat_seq[20:24] .= 0
# hot start
new_stat = UnitCommitment._determine_initial_status(
hot_start,
stat_seq,
t_increment,
)
@test new_stat == -5
# cold start
new_stat = UnitCommitment._determine_initial_status(
cold_start,
stat_seq,
t_increment,
)
@test new_stat == -5
new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq)
@test new_stat == 16
# all off throughout
stat_seq = zeros(t_model)
stat_seq = zeros(36)
# hot start
new_stat = UnitCommitment._determine_initial_status(
hot_start,
stat_seq,
t_increment,
)
@test new_stat == -24
new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq)
@test new_stat == -36
# cold start
new_stat = UnitCommitment._determine_initial_status(
cold_start,
stat_seq,
t_increment,
)
@test new_stat == -124
new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq)
@test new_stat == -136
# on in the last 12 periods
stat_seq = zeros(t_model)
stat_seq = zeros(36)
stat_seq[25:end] .= 1
# hot start
new_stat = UnitCommitment._determine_initial_status(
hot_start,
stat_seq,
t_increment,
)
@test new_stat == -24
new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq)
@test new_stat == 12
# cold start
new_stat = UnitCommitment._determine_initial_status(
cold_start,
stat_seq,
t_increment,
)
@test new_stat == -124
new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq)
@test new_stat == 12
end
@testset "set_initial_status" begin
@ -140,28 +72,28 @@ end
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
psuedo_solution = OrderedDict(
"Thermal production (MW)" => OrderedDict(
"g1" => [110.0, 112.0, 114.0, 116.0],
"g2" => [100.0, 102.0, 0.0, 0.0],
"g1" => [0.0, 112.0, 114.0, 116.0],
"g2" => [0.0, 102.0, 0.0, 0.0],
"g3" => [0.0, 0.0, 0.0, 0.0],
"g4" => [33.0, 34.0, 66.0, 99.0],
"g5" => [33.0, 34.0, 66.0, 99.0],
"g6" => [100.0, 100.0, 100.0, 100.0],
"g4" => [0.0, 34.0, 66.0, 99.0],
"g5" => [0.0, 34.0, 66.0, 99.0],
"g6" => [0.0, 100.0, 100.0, 100.0],
),
"Is on" => OrderedDict(
"g1" => [1.0, 1.0, 1.0, 1.0],
"g2" => [1.0, 1.0, 0.0, 0.0],
"g1" => [0.0, 1.0, 1.0, 1.0],
"g2" => [0.0, 1.0, 0.0, 0.0],
"g3" => [0.0, 0.0, 0.0, 0.0],
"g4" => [1.0, 1.0, 1.0, 1.0],
"g5" => [1.0, 1.0, 1.0, 1.0],
"g6" => [1.0, 1.0, 1.0, 1.0],
"g4" => [0.0, 1.0, 1.0, 1.0],
"g5" => [0.0, 1.0, 1.0, 1.0],
"g6" => [0.0, 1.0, 1.0, 1.0],
),
)
UnitCommitment._set_initial_status!(instance, psuedo_solution, 3)
thermal_units = instance.scenarios[1].thermal_units
@test thermal_units[1].initial_power == 114.0
@test thermal_units[1].initial_power == 116.0
@test thermal_units[1].initial_status == 3.0
@test thermal_units[2].initial_power == 0.0
@test thermal_units[2].initial_status == -1.0
@test thermal_units[2].initial_status == -2.0
@test thermal_units[3].initial_power == 0.0
@test thermal_units[3].initial_status == -9.0
@ -173,47 +105,47 @@ end
psuedo_solution = OrderedDict(
"case14" => OrderedDict(
"Thermal production (MW)" => OrderedDict(
"g1" => [110.0, 112.0, 114.0, 116.0],
"g2" => [100.0, 102.0, 0.0, 0.0],
"g1" => [0.0, 112.0, 114.0, 116.0],
"g2" => [0.0, 102.0, 0.0, 0.0],
"g3" => [0.0, 0.0, 0.0, 0.0],
"g4" => [33.0, 34.0, 66.0, 99.0],
"g5" => [33.0, 34.0, 66.0, 99.0],
"g6" => [100.0, 100.0, 100.0, 100.0],
"g4" => [0.0, 34.0, 66.0, 99.0],
"g5" => [0.0, 34.0, 66.0, 99.0],
"g6" => [0.0, 100.0, 100.0, 100.0],
),
"Is on" => OrderedDict(
"g1" => [1.0, 1.0, 1.0, 1.0],
"g2" => [1.0, 1.0, 0.0, 0.0],
"g1" => [0.0, 1.0, 1.0, 1.0],
"g2" => [0.0, 1.0, 0.0, 0.0],
"g3" => [0.0, 0.0, 0.0, 0.0],
"g4" => [1.0, 1.0, 1.0, 1.0],
"g5" => [1.0, 1.0, 1.0, 1.0],
"g6" => [1.0, 1.0, 1.0, 1.0],
"g4" => [0.0, 1.0, 1.0, 1.0],
"g5" => [0.0, 1.0, 1.0, 1.0],
"g6" => [0.0, 1.0, 1.0, 1.0],
),
),
"case14-profiled" => OrderedDict(
"Thermal production (MW)" => OrderedDict(
"g1" => [112.0, 113.0, 116.0, 115.0],
"g1" => [0.0, 113.0, 116.0, 115.0],
"g2" => [0.0, 0.0, 0.0, 0.0],
"g3" => [0.0, 0.0, 0.0, 20.0],
"g4" => [33.0, 34.0, 66.0, 99.0],
"g5" => [33.0, 34.0, 66.0, 99.0],
"g6" => [100.0, 100.0, 100.0, 100.0],
"g4" => [0.0, 34.0, 66.0, 98.0],
"g5" => [0.0, 34.0, 66.0, 97.0],
"g6" => [0.0, 100.0, 100.0, 100.0],
),
"Is on" => OrderedDict(
"g1" => [1.0, 1.0, 1.0, 1.0],
"g1" => [0.0, 1.0, 1.0, 1.0],
"g2" => [0.0, 0.0, 0.0, 0.0],
"g3" => [0.0, 0.0, 0.0, 0.0],
"g4" => [1.0, 1.0, 1.0, 1.0],
"g5" => [1.0, 1.0, 1.0, 1.0],
"g6" => [1.0, 1.0, 1.0, 1.0],
"g3" => [0.0, 0.0, 0.0, 1.0],
"g4" => [0.0, 1.0, 1.0, 1.0],
"g5" => [0.0, 1.0, 1.0, 1.0],
"g6" => [0.0, 1.0, 1.0, 1.0],
),
),
)
UnitCommitment._set_initial_status!(instance, psuedo_solution, 3)
thermal_units_sc2 = instance.scenarios[2].thermal_units
@test thermal_units_sc2[1].initial_power == 116.0
@test thermal_units_sc2[1].initial_power == 115.0
@test thermal_units_sc2[1].initial_status == 3.0
@test thermal_units_sc2[2].initial_power == 0.0
@test thermal_units_sc2[2].initial_status == -11.0
@test thermal_units_sc2[3].initial_power == 0.0
@test thermal_units_sc2[3].initial_status == -9.0
@test thermal_units_sc2[3].initial_power == 20.0
@test thermal_units_sc2[3].initial_status == 1.0
end

Loading…
Cancel
Save