@@ -246,15 +246,57 @@ def init(m, gen, period):
246246 mod .GEN_TPS , rule = lambda m , g , t : m .GenCapacity [g , m .tp_period [t ]]
247247 )
248248 mod .DispatchGen = Var (mod .GEN_TPS , within = NonNegativeReals )
249- mod .DispatchGenByFuel = Var (mod .GEN_TP_FUELS , within = NonNegativeReals )
249+
250+ ##########################################
251+ # Define DispatchGenByFuel
252+ #
253+ # Previously DispatchGenByFuel was simply a Variable for all the projects and a constraint ensured
254+ # that the sum of DispatchGenByFuel across all fuels was equal the total dispatch for that project.
255+ # However this approach creates extra variables in our model for projects that have only one fuel.
256+ # Although these extra variables likely get removed during Gurobi pre-solve, we've nonetheless
257+ # simplified the model here to reduce time in presolve and ensure the model is always
258+ # simplified regardless of the solving method.
259+ #
260+ # To do this we redefine DispatchGenByFuel to be an
261+ # expression that is equal to DispatchGenByFuelVar when we have multiple fuels but
262+ # equal to DispatchGen when we have only one fuel.
263+
264+ # Define a set that is used to define DispatchGenByFuelVar
265+ mod .GEN_TP_FUELS_FOR_MULTIFUELS = Set (
266+ dimen = 3 ,
267+ initialize = mod .GEN_TP_FUELS ,
268+ filter = lambda m , g , t , f : g in m .MULTIFUEL_GENS ,
269+ doc = "Same as GEN_TP_FUELS but only includes multi-fuel projects" ,
270+ )
271+ # DispatchGenByFuelVar is a variable that exists only for multi-fuel projects.
272+ mod .DispatchGenByFuelVar = Var (
273+ mod .GEN_TP_FUELS_FOR_MULTIFUELS , within = NonNegativeReals
274+ )
275+ # DispatchGenByFuel_Constraint ensures that the sum of all the fuels is DispatchGen
250276 mod .DispatchGenByFuel_Constraint = Constraint (
251277 mod .FUEL_BASED_GEN_TPS ,
252- rule = lambda m , g , t : sum (
253- m .DispatchGenByFuel [g , t , f ] for f in m .FUELS_FOR_GEN [g ]
254- )
255- == m .DispatchGen [g , t ],
278+ rule = lambda m , g , t : (
279+ Constraint .Skip
280+ if g not in m .MULTIFUEL_GENS
281+ else sum (
282+ m .DispatchGenByFuelVar [g , t , f ] for f in m .FUELS_FOR_MULTIFUEL_GEN [g ]
283+ )
284+ == m .DispatchGen [g , t ]
285+ ),
256286 )
257287
288+ # Define DispatchGenByFuel to equal the matching variable if we have many fuels but to equal
289+ # the total dispatch if we have only one fuel.
290+ mod .DispatchGenByFuel = Expression (
291+ mod .GEN_TP_FUELS ,
292+ rule = lambda m , g , t , f : m .DispatchGenByFuelVar [g , t , f ]
293+ if g in m .MULTIFUEL_GENS
294+ else m .DispatchGen [g , t ],
295+ )
296+
297+ # End Defining DispatchGenByFuel
298+ ##########################################
299+
258300 # Only used to improve the performance of calculating ZoneTotalCentralDispatch and ZoneTotalDistributedDispatch
259301 mod .GENS_FOR_ZONE_TPS = Set (
260302 mod .LOAD_ZONES ,
0 commit comments