Updated randomize, validate and initial conditions

pull/28/head
Jun He 3 years ago
parent bea42d174c
commit b71a1c3d5f

@ -17,24 +17,29 @@ function generate_initial_conditions!(
)::Nothing )::Nothing
G = sc.thermal_units G = sc.thermal_units
B = sc.buses B = sc.buses
PU = sc.profiled_units
t = 1 t = 1
mip = JuMP.Model(optimizer) mip = JuMP.Model(optimizer)
# Decision variables # Decision variables
@variable(mip, x[G], Bin) @variable(mip, x[G], Bin)
@variable(mip, p[G] >= 0) @variable(mip, p[G] >= 0)
@variable(mip, pu[PU])
# Constraint: Minimum power # Constraint: Minimum power
@constraint(mip, min_power[g in G], p[g] >= g.min_power[t] * x[g]) @constraint(mip, min_power[g in G], p[g] >= g.min_power[t] * x[g])
@constraint(mip, pu_min_power[k in PU], pu[k] >= k.min_power[t])
# Constraint: Maximum power # Constraint: Maximum power
@constraint(mip, max_power[g in G], p[g] <= g.max_power[t] * x[g]) @constraint(mip, max_power[g in G], p[g] <= g.max_power[t] * x[g])
@constraint(mip, pu_max_power[k in PU], pu[k] <= k.capacity[t])
# Constraint: Production equals demand # Constraint: Production equals demand
@constraint( @constraint(
mip, mip,
power_balance, power_balance,
sum(b.load[t] for b in B) == sum(p[g] for g in G) sum(b.load[t] for b in B) ==
sum(p[g] for g in G) + sum(pu[k] for k in PU)
) )
# Constraint: Must run # Constraint: Must run
@ -58,7 +63,12 @@ function generate_initial_conditions!(
return c / mw return c / mw
end end
end end
@objective(mip, Min, sum(p[g] * cost_slope(g) for g in G)) @objective(
mip,
Min,
sum(p[g] * cost_slope(g) for g in G) +
sum(pu[k] * k.cost[t] for k in PU)
)
JuMP.optimize!(mip) JuMP.optimize!(mip)

@ -133,6 +133,10 @@ function _randomize_costs(
s.cost *= α s.cost *= α
end end
end end
for pu in sc.profiled_units
α = rand(rng, distribution)
pu.cost *= α
end
return return
end end

@ -305,6 +305,35 @@ function _validate_units(instance::UnitCommitmentInstance, solution; tol = 0.01)
end end
end end
end end
for pu in sc.profiled_units
production = solution[sc.name]["Profiled production (MW)"][pu.name]
for t in 1:instance.time
# Unit must produce at least its minimum power
if production[t] < pu.min_power[t] - tol
@error @sprintf(
"Profiled unit %s produces below its minimum limit at time %d (%.2f < %.2f)",
pu.name,
t,
production[t],
pu.min_power[t]
)
err_count += 1
end
# Unit must produce at most its maximum power
if production[t] > pu.capacity[t] + tol
@error @sprintf(
"Profiled unit %s produces above its maximum limit at time %d (%.2f > %.2f)",
pu.name,
t,
production[t],
pu.capacity[t]
)
err_count += 1
end
end
end
end end
return err_count return err_count
end end
@ -316,16 +345,25 @@ function _validate_reserve_and_demand(instance, solution, tol = 0.01)
load_curtail = 0 load_curtail = 0
fixed_load = sum(b.load[t] for b in sc.buses) fixed_load = sum(b.load[t] for b in sc.buses)
ps_load = 0 ps_load = 0
production = 0
if length(sc.price_sensitive_loads) > 0 if length(sc.price_sensitive_loads) > 0
ps_load = sum( ps_load = sum(
solution[sc.name]["Price-sensitive loads (MW)"][ps.name][t] solution[sc.name]["Price-sensitive loads (MW)"][ps.name][t]
for ps in sc.price_sensitive_loads for ps in sc.price_sensitive_loads
) )
end end
production = sum( if length(sc.thermal_units) > 0
solution[sc.name]["Thermal production (MW)"][g.name][t] for production = sum(
g in sc.thermal_units solution[sc.name]["Thermal production (MW)"][g.name][t]
) for g in sc.thermal_units
)
end
if length(sc.profiled_units) > 0
production += sum(
solution[sc.name]["Profiled production (MW)"][pu.name][t]
for pu in sc.profiled_units
)
end
if "Load curtail (MW)" in keys(solution) if "Load curtail (MW)" in keys(solution)
load_curtail = sum( load_curtail = sum(
solution[sc.name]["Load curtail (MW)"][b.name][t] for solution[sc.name]["Load curtail (MW)"][b.name][t] for

@ -62,4 +62,22 @@ test_approx(x, y) = @test isapprox(x, y, atol = 1e-3)
@test round.(system_load(sc), digits = 1)[1:8] @test round.(system_load(sc), digits = 1)[1:8]
[4854.7, 4849.2, 4732.7, 4848.2, 4948.4, 5231.1, 5874.8, 5934.8] [4854.7, 4849.2, 4732.7, 4848.2, 4948.4, 5231.1, 5874.8, 5934.8]
end end
@testset "profiled unit cost" begin
sc =
UnitCommitment.read("$FIXTURES/case14-profiled.json.gz").scenarios[1]
# Check original costs
pu1 = sc.profiled_units[1]
pu2 = sc.profiled_units[2]
test_approx(pu1.cost[1], 100.0)
test_approx(pu2.cost[1], 50.0)
randomize!(
sc,
XavQiuAhm2021.Randomization(randomize_load_profile = false),
rng = MersenneTwister(42),
)
# Check randomized costs
test_approx(pu1.cost[1], 98.039)
test_approx(pu2.cost[1], 48.385)
end
end end

Loading…
Cancel
Save