mirror of
https://github.com/ANL-CEEESA/UnitCommitment.jl.git
synced 2025-12-06 08:18:51 -06:00
added commitment status to thermal
This commit is contained in:
@@ -90,6 +90,7 @@ This section describes all generators in the system, including thermal units, re
|
|||||||
| `Initial power (MW)` | Amount of power the generator at time step `-1`, immediately before the planning horizon starts. | Required | N
|
| `Initial power (MW)` | Amount of power the generator at time step `-1`, immediately before the planning horizon starts. | Required | N
|
||||||
| `Must run?` | If `true`, the generator should be committed, even if that is not economical (Boolean). | `false` | Y
|
| `Must run?` | If `true`, the generator should be committed, even if that is not economical (Boolean). | `false` | Y
|
||||||
| `Reserve eligibility` | List of reserve products this generator is eligibe to provide. By default, the generator is not eligible to provide any reserves. | `[]` | N
|
| `Reserve eligibility` | List of reserve products this generator is eligibe to provide. By default, the generator is not eligible to provide any reserves. | `[]` | N
|
||||||
|
| `Commitment status` | List of commitment status over the time horizon. At time `t`, if `true`, the generator must be commited at that time period; if `false`, the generator must not be commited at that time period. If `null` at time `t`, the generator's commitment status is then decided by the model. By default, the status is a list of `null` values. | `[null]` | Y
|
||||||
|
|
||||||
#### Profiled Units
|
#### Profiled Units
|
||||||
|
|
||||||
@@ -151,7 +152,8 @@ Note that this curve also specifies the production limits. Specifically, the fir
|
|||||||
"Production cost curve ($)": [0.0, 0.0],
|
"Production cost curve ($)": [0.0, 0.0],
|
||||||
"Initial status (h)": -100,
|
"Initial status (h)": -100,
|
||||||
"Initial power (MW)": 0,
|
"Initial power (MW)": 0,
|
||||||
"Reserve eligibility": ["r1", "r2"]
|
"Reserve eligibility": ["r1", "r2"],
|
||||||
|
"Commitment status": [true, false, null, true]
|
||||||
},
|
},
|
||||||
"gen3": {
|
"gen3": {
|
||||||
"Bus": "b6",
|
"Bus": "b6",
|
||||||
|
|||||||
@@ -282,6 +282,12 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
initial_status *= time_multiplier
|
initial_status *= time_multiplier
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Read commitment status
|
||||||
|
commitment_status = scalar(
|
||||||
|
dict["Commitment status"],
|
||||||
|
default = Vector{Union{Bool,Nothing}}(nothing, T),
|
||||||
|
)
|
||||||
|
|
||||||
unit = ThermalUnit(
|
unit = ThermalUnit(
|
||||||
unit_name,
|
unit_name,
|
||||||
bus,
|
bus,
|
||||||
@@ -302,6 +308,7 @@ function _from_json(json; repair = true)::UnitCommitmentScenario
|
|||||||
initial_power,
|
initial_power,
|
||||||
startup_categories,
|
startup_categories,
|
||||||
unit_reserves,
|
unit_reserves,
|
||||||
|
commitment_status,
|
||||||
)
|
)
|
||||||
push!(bus.thermal_units, unit)
|
push!(bus.thermal_units, unit)
|
||||||
for r in unit_reserves
|
for r in unit_reserves
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ mutable struct ThermalUnit
|
|||||||
initial_power::Union{Float64,Nothing}
|
initial_power::Union{Float64,Nothing}
|
||||||
startup_categories::Vector{StartupCategory}
|
startup_categories::Vector{StartupCategory}
|
||||||
reserves::Vector{Reserve}
|
reserves::Vector{Reserve}
|
||||||
|
commitment_status::Vector{Union{Bool,Nothing}}
|
||||||
end
|
end
|
||||||
|
|
||||||
mutable struct TransmissionLine
|
mutable struct TransmissionLine
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ function _add_unit_dispatch!(
|
|||||||
sc,
|
sc,
|
||||||
)
|
)
|
||||||
_add_startup_shutdown_limit_eqs!(model, g, sc)
|
_add_startup_shutdown_limit_eqs!(model, g, sc)
|
||||||
|
_add_commitment_status_eqs!(model, g, sc)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -270,6 +271,26 @@ function _add_min_uptime_downtime_eqs!(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function _add_commitment_status_eqs!(
|
||||||
|
model::JuMP.Model,
|
||||||
|
g::ThermalUnit,
|
||||||
|
sc::UnitCommitmentScenario,
|
||||||
|
)::Nothing
|
||||||
|
is_on = model[:is_on]
|
||||||
|
T = model[:instance].time
|
||||||
|
eq_commitment_status = _init(model, :eq_commitment_status)
|
||||||
|
for t in 1:T
|
||||||
|
# Fix commitment status
|
||||||
|
if g.commitment_status[t] !== nothing
|
||||||
|
eq_commitment_status[sc.name, g.name, t] = @constraint(
|
||||||
|
model,
|
||||||
|
is_on[g.name, t] == (g.commitment_status[t] ? 1.0 : 0.0)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
function _add_net_injection_eqs!(
|
function _add_net_injection_eqs!(
|
||||||
model::JuMP.Model,
|
model::JuMP.Model,
|
||||||
g::ThermalUnit,
|
g::ThermalUnit,
|
||||||
|
|||||||
@@ -153,3 +153,14 @@ end
|
|||||||
@test second_pu.capacity == [120.0 for t in 1:4]
|
@test second_pu.capacity == [120.0 for t in 1:4]
|
||||||
@test sc.profiled_units_by_name["g8"].name == "g8"
|
@test sc.profiled_units_by_name["g8"].name == "g8"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@testset "read_benchmark commitmemt-status" begin
|
||||||
|
instance = UnitCommitment.read("$FIXTURES/case14-fixed-status.json.gz")
|
||||||
|
sc = instance.scenarios[1]
|
||||||
|
|
||||||
|
@test sc.thermal_units[1].commitment_status == [nothing for t in 1:4]
|
||||||
|
@test sc.thermal_units[2].commitment_status == [true for t in 1:4]
|
||||||
|
@test sc.thermal_units[4].commitment_status == [false for t in 1:4]
|
||||||
|
@test sc.thermal_units[6].commitment_status ==
|
||||||
|
[false, nothing, true, nothing]
|
||||||
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user