|
| 1 | +# Model Name: Energy Portfolio Optimization |
| 2 | + |
| 3 | +### SETS |
| 4 | +set PERIODS ordered; # hours |
| 5 | +set THERMAL_GENERATORS default {}; |
| 6 | +set RESERVOIR_HYDRO_GENERATORS default {}; |
| 7 | +set CONVENTIONAL_GENERATORS = THERMAL_GENERATORS union RESERVOIR_HYDRO_GENERATORS; |
| 8 | +set ROR_HYDRO_GENERATORS default {}; |
| 9 | +set HYDRO_GENERATORS = RESERVOIR_HYDRO_GENERATORS union ROR_HYDRO_GENERATORS; |
| 10 | +set UPSTREAM_GENERATORS {HYDRO_GENERATORS} within HYDRO_GENERATORS default {}; |
| 11 | +set SOLAR_GENERATORS default {}; |
| 12 | +set WIND_GENERATORS default {}; |
| 13 | +set RENEWABLE_GENERATORS = SOLAR_GENERATORS union WIND_GENERATORS; |
| 14 | +set GENERATORS = THERMAL_GENERATORS union HYDRO_GENERATORS union RENEWABLE_GENERATORS; |
| 15 | + |
| 16 | + |
| 17 | +### PARAMETERS |
| 18 | +# Forecasted Params |
| 19 | +param market_price {PERIODS} >= 0; # Forecasted market energy price ($/MWh) |
| 20 | +param marginal_cost {THERMAL_GENERATORS, PERIODS} >= 0; # Marginal fuel cost ($/MWh) |
| 21 | +param inflows {HYDRO_GENERATORS, PERIODS} >= 0 default 0; # Water contributions/inflows (m3/s) |
| 22 | +param renewable_resource {RENEWABLE_GENERATORS, PERIODS} >= 0; # Renewable resource availability (MW) |
| 23 | + |
| 24 | +# Thermal Units Params |
| 25 | +param ramp_up_rate {THERMAL_GENERATORS} >= 0; # Ramp up limit (MW/hour) |
| 26 | +param ramp_down_rate {THERMAL_GENERATORS} >= 0; # Ramp down limit (MW/hour) |
| 27 | + |
| 28 | +# Hydro Params |
| 29 | +param efficiency {HYDRO_GENERATORS} > 0; # Conversion Factor (MW/m3/s) |
| 30 | +param reservoir_max_capacity {RESERVOIR_HYDRO_GENERATORS} >= 0; # Reservoir max capacity (Hm3) |
| 31 | +param initial_storage {r in RESERVOIR_HYDRO_GENERATORS} >= 0 default 0.7*reservoir_max_capacity[r]; # Initial reservoir energy (Hm3) |
| 32 | +param final_storage {r in RESERVOIR_HYDRO_GENERATORS} >= 0 default initial_storage[r]; # Required energy at end of horizon (Hm3) |
| 33 | + |
| 34 | +# Operational Params/Limits |
| 35 | +param max_generation {CONVENTIONAL_GENERATORS, PERIODS} >= 0; # Maximum generation (MW) |
| 36 | +param min_generation {GENERATORS, PERIODS} >= 0 default 0; # Minimum generation (MW) |
| 37 | + |
| 38 | +# Penalty Params |
| 39 | +param penalty_spillage {HYDRO_GENERATORS} >= 0 default 2.5* max{t in PERIODS}(market_price[t]); # Penalty for water spillage ($/MWh) |
| 40 | + |
| 41 | +# Computed/Scalar Params |
| 42 | +param period_duration >=0 default 3600; # Duration of each period in seconds (default: 1 hour) |
| 43 | +param delta_t = period_duration / 1000000; # Constant to convert m3/s to Hm3 per period |
| 44 | + |
| 45 | + |
| 46 | +### VARIABLES |
| 47 | +var Generation {GENERATORS, PERIODS} >= 0; # MW |
| 48 | +var ReservoirStorage {RESERVOIR_HYDRO_GENERATORS, PERIODS} >= 0; # Hm3 |
| 49 | +var TurbiningFlow {HYDRO_GENERATORS, PERIODS} >= 0; # m3/s |
| 50 | +var Spillage {HYDRO_GENERATORS, PERIODS} >= 0; # MWh |
| 51 | +var SpillageFlow {HYDRO_GENERATORS, PERIODS} >= 0; # m3/s |
| 52 | + |
| 53 | + |
| 54 | +### OBJECTIVE FUNCTION |
| 55 | +maximize TotalProfit: |
| 56 | + sum {g in GENERATORS, t in PERIODS} (market_price[t] * Generation[g, t]) |
| 57 | + - sum {g in THERMAL_GENERATORS, t in PERIODS} (marginal_cost[g, t] * Generation[g, t]) |
| 58 | + - sum {g in HYDRO_GENERATORS, t in PERIODS} (penalty_spillage[g] * Spillage[g, t]); |
| 59 | + |
| 60 | + |
| 61 | +### CONSTRAINTS |
| 62 | +subject to ReservoirHydroBalance {g in RESERVOIR_HYDRO_GENERATORS, t in PERIODS}: |
| 63 | + ReservoirStorage[g, t] = (if t = first(PERIODS) then initial_storage[g] else ReservoirStorage[g, prev(t)]) |
| 64 | + + delta_t * (inflows[g, t] |
| 65 | + + sum {ug in UPSTREAM_GENERATORS[g]} (TurbiningFlow[ug, t] + SpillageFlow[ug, t]) |
| 66 | + - TurbiningFlow[g, t] |
| 67 | + - SpillageFlow[g, t]); |
| 68 | + |
| 69 | +subject to RunOfRiverBalance {g in ROR_HYDRO_GENERATORS, t in PERIODS}: |
| 70 | + TurbiningFlow[g, t] + SpillageFlow[g, t] <= inflows[g, t]; |
| 71 | + |
| 72 | +subject to ReservoirStorageLimit {g in RESERVOIR_HYDRO_GENERATORS, t in PERIODS}: |
| 73 | + ReservoirStorage[g, t] <= reservoir_max_capacity[g]; |
| 74 | + |
| 75 | +subject to ReservoirFinalStorage {g in RESERVOIR_HYDRO_GENERATORS}: |
| 76 | + ReservoirStorage[g, last(PERIODS)] = final_storage[g]; |
| 77 | + |
| 78 | +subject to HydroGenerationFromFlow {g in HYDRO_GENERATORS, t in PERIODS}: |
| 79 | + Generation[g, t] = efficiency[g] * TurbiningFlow[g, t]; |
| 80 | + |
| 81 | +subject to HydroSpillageFromFlow {g in HYDRO_GENERATORS, t in PERIODS}: |
| 82 | + Spillage[g, t] = efficiency[g] * SpillageFlow[g, t]; |
| 83 | + |
| 84 | +subject to RenewableGenerationLimit {g in RENEWABLE_GENERATORS, t in PERIODS}: |
| 85 | + Generation[g, t] <= renewable_resource[g, t]; |
| 86 | + |
| 87 | +subject to ThermalRampUp {g in THERMAL_GENERATORS, t in PERIODS: ord(t) > 1}: |
| 88 | + Generation[g, t] - Generation[g, prev(t)] <= ramp_up_rate[g]; |
| 89 | + |
| 90 | +subject to ThermalRampDown {g in THERMAL_GENERATORS, t in PERIODS: ord(t) > 1}: |
| 91 | + Generation[g, prev(t)] - Generation[g, t] <= ramp_down_rate[g]; |
| 92 | + |
| 93 | +subject to GenerationMaxLimit {g in CONVENTIONAL_GENERATORS, t in PERIODS}: |
| 94 | + Generation[g, t] <= max_generation[g, t]; |
| 95 | + |
| 96 | +subject to GenerationMinLimit {g in GENERATORS, t in PERIODS}: |
| 97 | + Generation[g, t] >= min_generation[g, t]; |
| 98 | + |
0 commit comments