SETS:     ! (unitcom5);
! Electrical generator unit commitment planning;
! Keywords: Electricity generation, Hydro electric, 
  Multi-period planning, Unit commitment;

! The set of all generators;
 GENR: CF, CG, CS, MXG, INITY;
 PERIOD: DEM;
 GXP( GENR, PERIOD): X, YON, YOF, Z;
!  Units with time varying capacity;
 VGEN( GENR);
 VXP( VGEN, PERIOD): VMXG;
!  Hydro and pumped storage units;
 HNP( GENR): FLO, IMX, INI;
 HXP( HNP, PERIOD): INV, SPILL;
!  Pumped storage units;
 STORE( GENR): PF, PMX;
 SXP( STORE, PERIOD): W;
ENDSETS
DATA: GENR = COAL01 GAS001 GAS002 WIND01 HYDRO1 PUMP01;! The units; CF = 2775 5980 5290 1 2.0 1.9;! Fixed cost/period if spinning; CG = 14 22 25 1 1.1 2;! Cost/MWH generated; CS = 90000 12900 8000 1700 800 790;! Cost to start spinning; MXG = 1100 760 680 600 900 660;! Max gen capacity in period; INITY = 0 0 0 0 0 0;! Initially spinning or not; PERIOD = 1..24; DEM = 900 1790 2380 2490 1520 1298 2200 1030 1900 2360 1900 1790 1690 1650 1600 1600 1700 1800 1900 1600 1400 1200 1100 1000; ! Demand in MWH; ! Units with variable capacity; VGEN = WIND01; ! Capacity in each period; VMXG = 180 210 270 280 310 200 300 250 150 100 100 100 100 90 90 100 120 120 130 130 130 140 150 170; ! Hydro and pumped storage units; HNP = HYDRO1 PUMP01;! Name of the hydro and pumped units; FLO = 220 0; ! Inflow per period; IMX = 1000 970; ! Max inventory level; INI = 200 0; ! Initial inventory; ! Pumped storage; STORE = PUMP01; PF = 1.3; ! MWH needed to put 1 MWH in storage; PMX = 320; ! Max pumped into storage/period; ! Here the data are stored directly in the model file. Alternatively, attribute DEM can be read from a spreadsheet by the statement: DEM = @OLE( ); ! if: a) there is only one spreadsheet open in Excel, b) there is a range in the spreadsheet of the appropriate shape with name DEM; ! Similarly, answers can be sent back to the spreadsheet with statements like: @OLE( ) = X; ENDDATA SUBMODEL UnitCom: ! X(i,t) = amount generated by i in period t; ! Z(i,t) = 1 if i is running in t; ! YON(i,t) = 1 if i is started in t; ! YOF(i,t) = 1 if i is turned off in t; ! W(i,t) = amount pumped into i in period t; ! Minimize sum of start-up, spinning, and energy costs; MIN = @SUM( GXP( I, T): CS(I)*YON(I,T) + CF(I)* Z(I,T) + CG(I)*X(I,T)); ! Constraints applicable to all generators; ! Must satisfy demand + used for pumping; @FOR( PERIOD( T): @SUM( GENR( I): X(I,T)) = DEM(T) + @SUM(STORE(I): PF(I)*W(I,T)) ; ); @FOR( GENR( I): ! Generator I has to be spinning (Z(I,T) =1) to get any power; @FOR( PERIOD( T): X(I,T) <= MXG( I) * Z(I,T); ); @FOR( PERIOD( T): @BIN(Z(I,T)); ); ! Turn on YON(I,T) if generator I starts at the beginning of period T, and YOF(I,T) if generator stops at the beginning of period T; YON(I,1) - YOF(I,1) = Z(I,1) - INITY( I); ! Period 1 is special; @FOR( PERIOD(T) | T #GT# 1: YON(I,T) - YOF(I,T) = Z(I,T) - Z(I,T-1); YON(I,T) + YOF(I,T) <= 1; ! Cannot both turn on and off in a period; ); ); ! These constraints apply to variable capacity units; @FOR( VXP( I,T): X(I,T) <= VMXG(I,T); ); ! For plain hydro, we have the inventory equations; @FOR( HNP(I)| #NOT# @IN(STORE, I ): ! For period 1; INI( I) + FLO(I) = INV(I,1) + X(I,1) + SPILL(I,1); INV(I,1) <= IMX(I); ! Remaining periods; @FOR( PERIOD(T)| T #GT# 1: INV(I,T-1) + FLO(I) = INV(I,T) + X(I,T) + SPILL(I,T); INV(I,T) <= IMX(I); ); ); ! For pumped storage; @FOR( STORE(I): ! Beginning Inv + flow in + pumped in = ending inv + generated + spilled; ! For period 1; INI( I) + FLO(I) + W(I,1) = INV(I,1) + X(I,1) + SPILL(I,1); INV(I,1) <= IMX(I); W(I,1) <= PMX(I); ! Remaining periods; @FOR( PERIOD(T)| T #GT# 1: INV(I,T-1) + FLO(I)+ W(I,T) = INV(I,T) + X(I,T) + SPILL(I,T); INV(I,T) <= IMX(I); W(I,T) <= PMX( I) ); ); ENDSUBMODEL
CALC: @SET( 'TERSEO', 2); ! Set output level to TERSE; @SOLVE(UnitCom); @WRITE(@NEWLINE(1), ' Here is a simple report:', @NEWLINE(1)); @WRITE('Prd Demand '); ! List the names of the generators at the top; @FOR( GENR(i): @WRITE(' ',GENR(i)); ); @WRITE(@NEWLINE(1)); ! Loop over the periods; @FOR( PERIOD(t): @WRITE(@FORMAT(t,'2.0f'),' ',@FORMAT(DEM(t),'6.1f'),' '); @FOR( GENR(i): @IFC(X(i,t) #GT# 0.001: @WRITE(' ',@FORMAT(X(i,t),'7.2f')); @ELSE @WRITE(' '); ! Show blank if zero; ); ); @WRITE(@NEWLINE(1)); ); ENDCALC