Implement sub-hourly commitment

pull/10/head
Alinson S. Xavier 5 years ago
parent 5f0400fd93
commit 4947bff460

Binary file not shown.

@ -97,12 +97,14 @@ end
function Base.show(io::IO, instance::UnitCommitmentInstance) function Base.show(io::IO, instance::UnitCommitmentInstance)
print(io, "UnitCommitmentInstance with ") print(io, "UnitCommitmentInstance(")
print(io, "$(length(instance.units)) units, ") print(io, "$(length(instance.units)) units, ")
print(io, "$(length(instance.buses)) buses, ") print(io, "$(length(instance.buses)) buses, ")
print(io, "$(length(instance.lines)) lines, ") print(io, "$(length(instance.lines)) lines, ")
print(io, "$(length(instance.contingencies)) contingencies, ") print(io, "$(length(instance.contingencies)) contingencies, ")
print(io, "$(length(instance.price_sensitive_loads)) price sensitive loads") print(io, "$(length(instance.price_sensitive_loads)) price sensitive loads, ")
print(io, "$(instance.time) time steps")
print(io, ")")
end end
@ -131,7 +133,21 @@ function from_json(json; fix=true)
contingencies = Contingency[] contingencies = Contingency[]
lines = TransmissionLine[] lines = TransmissionLine[]
loads = PriceSensitiveLoad[] loads = PriceSensitiveLoad[]
T = json["Parameters"]["Time (h)"]
function scalar(x; default=nothing)
x !== nothing || return default
x
end
time_horizon = json["Parameters"]["Time (h)"]
if time_horizon === nothing
time_horizon = json["Parameters"]["Time horizon (h)"]
end
time_horizon !== nothing || error("Missing required parameter: Time horizon (h)")
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_multiplier = 60 ÷ time_step
T = time_horizon * time_multiplier
name_to_bus = Dict{String, Bus}() name_to_bus = Dict{String, Bus}()
name_to_line = Dict{String, TransmissionLine}() name_to_line = Dict{String, TransmissionLine}()
@ -143,11 +159,6 @@ function from_json(json; fix=true)
return x return x
end end
function scalar(x; default=nothing)
x !== nothing || return default
x
end
# Read parameters # Read parameters
power_balance_penalty = timeseries(json["Parameters"]["Power balance penalty (\$/MW)"], power_balance_penalty = timeseries(json["Parameters"]["Power balance penalty (\$/MW)"],
default=[1000.0 for t in 1:T]) default=[1000.0 for t in 1:T])
@ -187,8 +198,13 @@ function from_json(json; fix=true)
startup_costs = scalar(dict["Startup costs (\$)"], default=[0.]) startup_costs = scalar(dict["Startup costs (\$)"], default=[0.])
startup_categories = StartupCategory[] startup_categories = StartupCategory[]
for k in 1:length(startup_delays) for k in 1:length(startup_delays)
push!(startup_categories, StartupCategory(startup_delays[k], push!(
startup_costs[k])) startup_categories,
StartupCategory(
startup_delays[k] .* time_multiplier,
startup_costs[k],
),
)
end end
# Read and validate initial conditions # Read and validate initial conditions
@ -202,26 +218,31 @@ function from_json(json; fix=true)
if initial_status < 0 && initial_power > 1e-3 if initial_status < 0 && initial_power > 1e-3
error("unit $unit_name has invalid initial power") error("unit $unit_name has invalid initial power")
end end
initial_status *= time_multiplier
end end
unit = Unit(unit_name, unit = Unit(
unit_name,
bus, bus,
max_power, max_power,
min_power, min_power,
timeseries(dict["Must run?"], default=[false for t in 1:T]), timeseries(dict["Must run?"], default=[false for t in 1:T]),
min_power_cost, min_power_cost,
segments, segments,
scalar(dict["Minimum uptime (h)"], default=1), scalar(dict["Minimum uptime (h)"], default=1) * time_multiplier,
scalar(dict["Minimum downtime (h)"], default=1), scalar(dict["Minimum downtime (h)"], default=1) * time_multiplier,
scalar(dict["Ramp up limit (MW)"], default=1e6), scalar(dict["Ramp up limit (MW)"], default=1e6),
scalar(dict["Ramp down limit (MW)"], default=1e6), scalar(dict["Ramp down limit (MW)"], default=1e6),
scalar(dict["Startup limit (MW)"], default=1e6), scalar(dict["Startup limit (MW)"], default=1e6),
scalar(dict["Shutdown limit (MW)"], default=1e6), scalar(dict["Shutdown limit (MW)"], default=1e6),
initial_status, initial_status,
initial_power, initial_power,
timeseries(dict["Provides spinning reserves?"], timeseries(
default=[true for t in 1:T]), dict["Provides spinning reserves?"],
startup_categories) default=[true for t in 1:T],
),
startup_categories,
)
push!(bus.units, unit) push!(bus.units, unit)
name_to_unit[unit_name] = unit name_to_unit[unit_name] = unit
push!(units, unit) push!(units, unit)

@ -101,6 +101,20 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
@test load.demand == [50. for t in 1:4] @test load.demand == [50. for t in 1:4]
end end
@testset "read sub-hourly" begin
instance = UnitCommitment.read_benchmark("test/case14-sub-hourly")
@test instance.time == 4
unit = instance.units[1]
@test unit.name == "g1"
@test unit.min_uptime == 2
@test unit.min_downtime == 2
@test length(unit.startup_categories) == 3
@test unit.startup_categories[1].delay == 2
@test unit.startup_categories[2].delay == 4
@test unit.startup_categories[3].delay == 6
@test unit.initial_status == -200
end
@testset "slice" begin @testset "slice" begin
instance = UnitCommitment.read_benchmark("test/case14") instance = UnitCommitment.read_benchmark("test/case14")
modified = UnitCommitment.slice(instance, 1:2) modified = UnitCommitment.slice(instance, 1:2)

Loading…
Cancel
Save