|
| 1 | +# Tested with Julia v1.1, JSON v0.21, JuMP v0.19, Cbc v0.6 |
| 2 | + |
| 3 | +using JSON |
| 4 | +using JuMP |
| 5 | + |
| 6 | + |
| 7 | +println("loading data") |
| 8 | + |
| 9 | +## Grab instance file from first command line argument |
| 10 | +data_file = ARGS[1] |
| 11 | +data = JSON.parsefile(data_file) |
| 12 | + |
| 13 | + |
| 14 | +println("model building") |
| 15 | + |
| 16 | +thermal_gens = keys(data["thermal_generators"]) |
| 17 | +renewable_gens = keys(data["renewable_generators"]) |
| 18 | +time_periods = 1:data["time_periods"] |
| 19 | + |
| 20 | +gen_startup_categories = Dict(g => 1:length(gen["startup"]) for (g,gen) in data["thermal_generators"]) |
| 21 | +gen_pwl_points = Dict(g => 1:length(gen["piecewise_production"]) for (g,gen) in data["thermal_generators"]) |
| 22 | + |
| 23 | +m = Model() |
| 24 | + |
| 25 | +@variable(m, cg[thermal_gens,time_periods]) |
| 26 | +@variable(m, pg[thermal_gens,time_periods] >= 0) |
| 27 | +@variable(m, pw[renewable_gens,time_periods] >= 0) |
| 28 | +@variable(m, rg[thermal_gens,time_periods] >= 0) |
| 29 | +@variable(m, ug[thermal_gens,time_periods], binary=true) |
| 30 | +@variable(m, vg[thermal_gens,time_periods], binary=true) |
| 31 | +@variable(m, wg[thermal_gens,time_periods], binary=true) |
| 32 | +@variable(m, delta_sg[g in thermal_gens,gen_startup_categories[g],time_periods], binary=true) |
| 33 | +@variable(m, 0 <= lambda_lg[g in thermal_gens,gen_pwl_points[g],time_periods] <= 1) |
| 34 | + |
| 35 | + |
| 36 | +@objective(m, Min, |
| 37 | + sum( |
| 38 | + sum( |
| 39 | + cg[g,t] + gen["piecewise_production"][1]["cost"]*ug[g,t] + |
| 40 | + sum( |
| 41 | + gen_startup["cost"]*delta_sg[g,i,t] |
| 42 | + for (i, gen_startup) in enumerate(gen["startup"])) |
| 43 | + for t in time_periods) |
| 44 | + for (g, gen) in data["thermal_generators"]) |
| 45 | +) # (1) |
| 46 | + |
| 47 | +for (g, gen) in data["thermal_generators"] |
| 48 | + |
| 49 | + if gen["unit_on_t0"] == 1 |
| 50 | + @constraint(m, sum( (ug[g,t]-1) for t in 1:min(data["time_periods"], gen["time_up_minimum"] - gen["time_up_t0"]) ) == 0) # (4) |
| 51 | + else |
| 52 | + @constraint(m, sum( ug[g,t] for t in 1:min(data["time_periods"], gen["time_down_minimum"] - gen["time_down_t0"]) ) == 0) # (5) |
| 53 | + end |
| 54 | + |
| 55 | + @constraint(m, ug[g,1] - gen["unit_on_t0"] == vg[g,1] - wg[g,1]) # (6) |
| 56 | + |
| 57 | + @constraint(m, 0 == |
| 58 | + sum( |
| 59 | + sum( |
| 60 | + delta_sg[g,i,t] |
| 61 | + for t in max(1, gen["startup"][i+1]["lag"] - gen["time_down_t0"] + 1):min(gen["startup"][i+1]["lag"]-1, data["time_periods"])) |
| 62 | + for (i,startup) in enumerate(gen["startup"][1:end-1])) |
| 63 | + ) # (7) |
| 64 | + |
| 65 | + @constraint(m, pg[g,1] + rg[g,1] - gen["unit_on_t0"]*(gen["power_output_t0"] - gen["power_output_minimum"]) <= gen["ramp_up_limit"]) # (8) |
| 66 | + @constraint(m, gen["unit_on_t0"]*(gen["power_output_t0"] - gen["power_output_minimum"]) - pg[g,1] <= gen["ramp_down_limit"]) # (9) |
| 67 | + @constraint(m, gen["unit_on_t0"]*(gen["power_output_t0"] - gen["power_output_minimum"]) <= gen["unit_on_t0"]*(gen["power_output_maximum"] - gen["power_output_minimum"]) - max(0, gen["power_output_maximum"] - gen["ramp_shutdown_limit"])*wg[g,1]) # (10) |
| 68 | +end |
| 69 | + |
| 70 | +for t in time_periods |
| 71 | + @constraint(m, |
| 72 | + sum( pg[g,t] + gen["power_output_minimum"]*ug[g,t] for (g, gen) in data["thermal_generators"] ) + |
| 73 | + sum( pw[g,t] for g in renewable_gens) |
| 74 | + == data["demand"][t] |
| 75 | + ) # (2) |
| 76 | + |
| 77 | + @constraint(m, sum(rg[g,t] for g in thermal_gens) >= data["reserves"][t]) # (3) |
| 78 | + |
| 79 | + for (g, gen) in data["thermal_generators"] |
| 80 | + |
| 81 | + @constraint(m, ug[g,t] >= gen["must_run"]) # (11) |
| 82 | + |
| 83 | + if t > 1 |
| 84 | + @constraint(m, ug[g,t] - ug[g,t-1] == vg[g,t] - wg[g,t]) # (12) |
| 85 | + @constraint(m, pg[g,t] + rg[g,t] - pg[g,t-1] <= gen["ramp_up_limit"]) # (19) |
| 86 | + @constraint(m, pg[g,t-1] - pg[g,t] <= gen["ramp_down_limit"]) # (20) |
| 87 | + end |
| 88 | + |
| 89 | + |
| 90 | + if t >= gen["time_up_minimum"] || t == data["time_periods"] |
| 91 | + @constraint(m, sum( vg[g,t2] for t2 in (t-min(gen["time_up_minimum"],data["time_periods"])+1):t) <= ug[g,t]) # (13) |
| 92 | + end |
| 93 | + |
| 94 | + if t >= gen["time_down_minimum"] || t == data["time_periods"] |
| 95 | + @constraint(m, sum( wg[g,t2] for t2 in (t-min(gen["time_down_minimum"],data["time_periods"])+1):t) <= 1 - ug[g,t]) # (14) |
| 96 | + end |
| 97 | + |
| 98 | + for (si,startup) in enumerate(gen["startup"][1:end-1]) |
| 99 | + if t >= gen["startup"][si+1]["lag"] |
| 100 | + time_range = startup["lag"]:(gen["startup"][si+1]["lag"]-1) |
| 101 | + @constraint(m, delta_sg[g,si,t] <= sum(wg[g,t-i] for i in time_range)) # (15) |
| 102 | + end |
| 103 | + end |
| 104 | + |
| 105 | + @constraint(m, vg[g,t] == sum( delta_sg[g,i,t] for i in gen_startup_categories[g])) # (16) |
| 106 | + |
| 107 | + @constraint(m, pg[g,t] + rg[g,t] <= (gen["power_output_maximum"] - gen["power_output_minimum"])*ug[g,t] - max(0, (gen["power_output_maximum"] - gen["ramp_startup_limit"]))*vg[g,t]) # (17) |
| 108 | + |
| 109 | + if t < data["time_periods"] |
| 110 | + @constraint(m, pg[g,t] + rg[g,t] <= (gen["power_output_maximum"] - gen["power_output_minimum"])*ug[g,t] - max(0, (gen["power_output_maximum"] - gen["ramp_shutdown_limit"]))*wg[g,t+1]) # (18) |
| 111 | + end |
| 112 | + |
| 113 | + @constraint(m, pg[g,t] == sum((gen["piecewise_production"][l]["mw"] - gen["piecewise_production"][1]["mw"])*lambda_lg[g,l,t] for l in gen_pwl_points[g])) # (21) |
| 114 | + @constraint(m, cg[g,t] == sum((gen["piecewise_production"][l]["cost"] - gen["piecewise_production"][1]["cost"])*lambda_lg[g,l,t] for l in gen_pwl_points[g])) # (22) |
| 115 | + @constraint(m, ug[g,t] == sum(lambda_lg[g,l,t] for l in gen_pwl_points[g])) # (23) |
| 116 | + end |
| 117 | + |
| 118 | + for (rg, rgen) in data["renewable_generators"] |
| 119 | + @constraint(m, rgen["power_output_minimum"][t] <= pw[rg,t] <= rgen["power_output_maximum"][t]) # (24) |
| 120 | + end |
| 121 | +end |
| 122 | + |
| 123 | + |
| 124 | +println("optimization") |
| 125 | + |
| 126 | +using Cbc |
| 127 | +optimize!(m, with_optimizer(Cbc.Optimizer, logLevel=1)) |
0 commit comments