@@ -233,10 +233,47 @@ def init(m, gen, period):
233233 mod .DispatchGen = Var (
234234 mod .GEN_TPS ,
235235 within = NonNegativeReals )
236- mod .DispatchGenByFuel = Var (mod .GEN_TP_FUELS , within = NonNegativeReals )
236+
237+ ##########################################
238+ # Define DispatchGenByFuel
239+ #
240+ # Previously DispatchGenByFuel was simply a Variable for all the projects and a constraint ensured
241+ # that the sum of DispatchGenByFuel across all fuels was equal the total dispatch for that project.
242+ # However this approach creates extra variables in our model for projects that have only one fuel.
243+ # Although these extra variables likely get removed during Gurobi pre-solve, we've nonetheless
244+ # simplified the model here to reduce time in presolve and ensure the model is always
245+ # simplified regardless of the solving method.
246+ #
247+ # To do this we redefine DispatchGenByFuel to be an
248+ # expression that is equal to DispatchGenByFuelVar when we have multiple fuels but
249+ # equal to DispatchGen when we have only one fuel.
250+
251+ # Define a set that is used to define DispatchGenByFuelVar
252+ mod .GEN_TP_FUELS_FOR_MULTIFUELS = Set (
253+ dimen = 3 ,
254+ initialize = mod .GEN_TP_FUELS ,
255+ filter = lambda m , g , t , f : g in m .MULTIFUEL_GENS ,
256+ doc = "Same as GEN_TP_FUELS but only includes multi-fuel projects"
257+ )
258+ # DispatchGenByFuelVar is a variable that exists only for multi-fuel projects.
259+ mod .DispatchGenByFuelVar = Var (mod .GEN_TP_FUELS_FOR_MULTIFUELS , within = NonNegativeReals )
260+ # DispatchGenByFuel_Constraint ensures that the sum of all the fuels is DispatchGen
237261 mod .DispatchGenByFuel_Constraint = Constraint (
238262 mod .FUEL_BASED_GEN_TPS ,
239- rule = lambda m , g , t : sum (m .DispatchGenByFuel [g , t , f ] for f in m .FUELS_FOR_GEN [g ]) == m .DispatchGen [g , t ])
263+ rule = lambda m , g , t :
264+ (Constraint .Skip if g not in m .MULTIFUEL_GENS
265+ else sum (m .DispatchGenByFuelVar [g , t , f ] for f in m .FUELS_FOR_MULTIFUEL_GEN [g ]) == m .DispatchGen [g , t ])
266+ )
267+
268+ # Define DispatchGenByFuel to equal the matching variable if we have many fuels but to equal
269+ # the total dispatch if we have only one fuel.
270+ mod .DispatchGenByFuel = Expression (
271+ mod .GEN_TP_FUELS ,
272+ rule = lambda m , g , t , f : m .DispatchGenByFuelVar [g , t , f ] if g in m .MULTIFUEL_GENS else m .DispatchGen [g , t ]
273+ )
274+
275+ # End Defining DispatchGenByFuel
276+ ##########################################
240277
241278 # Only used to improve the performance of calculating ZoneTotalCentralDispatch and ZoneTotalDistributedDispatch
242279 mod .GENS_FOR_ZONE_TPS = Set (
0 commit comments