C ********************************************************** SUBROUTINE TYPE90(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*) C This component handles utility rate schedules and performs economic calculations C for a customer employing electric parallel generation. Net-metering is assumed. C The rate schedule is read from a text file. Schedules support daily time-of-use C rates as well as seasonal variations. Useage and demand charges are included. C Weekends and hoidays have separate off-peak C rates. This component must be connected to a TYPE 3 calendar unit to know where to C look in the rate schedule to determine the electrical rate. Inputs include load and C parallel generation. Outputs include power purchased and sold and the values C associated with these transactions. In addition, the component writes two "electric C bill" files to disk. These files show useage and demand charges for each month. One C is intended to be read from a text editor and the second is space-delimited for C spreadsheet viewing. C C************************************************************************** C C C PARAMETERS, INPUTS, AND OUTPUTS C C PAR(1) Logical unit number of rate schedule file (read) C PAR(2) Logical unit number of text editor bill file (written) C PAR(3) Logical unit number of spreadsheet bill file (written) C PAR(4) Flag for observing weekend rates from schedule file C PAR(5) Flag for observing holiday rates from schedule file C PAR(6) Maximum power which may be sold back to utility (W) C C XIN(1) Hour of Day (from TYPE 3) C XIN(2) Hour of Year (from TYPE 3) C XIN(3) Month "" C XIN(4) Year "" C XIN(5) Load (W) C XIN(6) Weekend Flag "" C XIN(7) Holiday Flag "" C XIN(8) Parallel Generation (W) C C OUT(1) Useage rate ($/kW-hr) C OUT(2) Demand rate ($/kW) C OUT(3) Netload (Load-Generation) C OUT(4) Purchased power (W) C OUT(5) Sold power (W) C OUT(6) $ value of purchased power C OUT(7) $ value of sold power C OUT(8) Instantaneous savings from parallel generation C OUT(9) Fraction of load met by parallel generation (max of 1) C **************************************************************** C C VARIABLES (Way too many) C C DEMAND Instantaneous demand charge (rate*net load) ($) C DEMCUM Monthly demand charge at present time ($) C DEMRATE Demand rate ($/kW-hr) C DEMROLLCHG 12-month rolling demand charge ($) C DEMROLLRATE 12-month rolling demand rate ($/KW) C DEMSCHD(I,J) Demand rate ($/kW) for annual division I, hour of day J C DEMWKEND(J) Weekend/Holiday demand rate for annual division J ($/kW) C FILELINE Line in rate schedule text file C HOLFLAG Flag for holiday C HOLOBS Flag indicating if off-peak rates should be used on holidays C HOUR Hour of day C HOUREND(J) Hour of year at which rate division J ends C HOURSTART(J) Hour of year at which rate division J begins C HRYEAR Hour of year C LEAP Leap year flag C LOAD Electrical load (kW) C LOADCUM Cumulative net load, reset each month (kW) C LUBILL Logical unit of text-editor bill file C LUSCHD Logical unit of rate schedule file C LUSPR Logical unit of space-delimited spreadsheet bill file C MAXNETLOAD Maximum instantaneous load during month (kW) C MAXSELL Maximum power which may be sold back to utility (kW) C MONSAVE Instantaneous savings from parallel generation ($) C MONTH Month (Jan=1, Feb=2) C MONTHDIS Month displayed on utility bill C NETLOAD Net load! Load-generation (kW) C NYEARDIV Number of "annual" divisions in rate scheduel over calendar year C OLDMONTH Month at last timestep C OLDROLL(J) 12-month rolling demand array from previous timestep (kW) C OLDTIME Simulation time at last step C PBUY Power purchased (kW) C PDUMP Power dumped (surpuls power exceeding MAXSELL) (kW) C PGEN Parallel generation (kW) C PSELL Power sold (kW) C ROLLOAD Largest instantaneous load in past 12 months (kW) C ROLLSTORE(J) Storage array for 12-month rolling demand charge, J month previous C SIMEND Flag for last timestep of simlation C SOLFRAC Fraction of load met by parallel generation C TOTALBILL Total electrical bill over simulation C TOTALCHG Total monthly bill ($) C USEAGE Instantaneous useage charge ($) C USECUM Cumulative useage charge, reset each month ($) C USERATE Useage rate ($/kW-hr) C USESCHD(I,J) Useage rate ($/kW-hr) for annual division I, hour of day J C USEWKEND(J) Weekend/Holiday useage rate for annual division J ($/kW-hr) C WKENDFLAG Flag for weekend C WKENDOBS Flag indicating if off-peak rate should be used on weekends C YEAR Year! C YEARDIS Year displayed on utility bill C YEARDIV Present annual division in rate schedule C C C****************************************************************************** C C Declaration of Variables IMPLICIT NONE COMMON /LUNITS/ LUR,LUW,IFORM,LUK COMMON /SIM/ TIME0,TFINAL,DELT,IWARN C COMMON /STORE/SLOC/IAV/S(5000) REAL PAR,TIME,T,DTDT,ICNTRL,IWARN,TIME0,TFINAL,DELT DOUBLE PRECISION XIN, OUT,NYEARDIV,HOURSTART,HOUREND,USESCHD, &DEMSCHD,USEWKEND,DEMWKEND,ROLLSTORE,LOAD,HOUR,USEAGE,DEMAND, &OLDROLL,DEMROLLRATE,USECUM,LOADCUM,DEMCUM,MAXNETLOAD,ROLLLOAD, &DEMROLLCHG,FILELINE,TOTALCHG,HRYEAR,OLDTIME, &USERATE,DEMRATE,TOTALBILL,PSELL,NETLOAD,PGEN,MONSAVE, &SOLFRAC,MAXSELL,PDUMP,PBUY INTEGER INFO,LUR,LUW,N,J,K,HOLFLAG,WKENDFLAG,MONTH,HOLOBS, &WKENDOBS,OLDMONTH,YEAR,LUBILL,YEARDIV,IFORM,LUK,LUSCHD,LEAP, &SIMEND,MONTHDIS,YEARDIS,LUSPR CHARACTER*10 MONTHNAME CHARACTER*3 MONTHABR DIMENSION HOURSTART(12),HOUREND(12),USESCHD(12,24),DEMSCHD(12,24), &USEWKEND(12),DEMWKEND(12),ROLLSTORE(12),OLDROLL(12),OUT(9), &XIN(8),PAR(6),INFO(15),FILELINE(53),MONTHNAME(12),MONTHABR(12) DATA MONTHNAME/'JANUARY','FEBRUARY','MARCH','APRIL','MAY', &'JUNE','JULY','AUGUST','SEPTEMBER','OCTOBER','NOVEMBER', &'DECEMBER'/ DATA MONTHABR/'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG', &'SEP','OCT','NOV','DEC'/ C**** Check for Initial Call of Simulation IF (INFO(7).EQ.-1) THEN C Outputs, Inputs Parameters INFO(6)=9 C Time Dependence INFO(9)=1 C Storage Allocation INFO(10)=1 C Discrete Control Variables INFO(11)=0 CALL TYPECK(1,INFO,8,6,0) C Read Parameters LUSCHD=INT(PAR(1)+0.1) LUBILL=INT(PAR(2)+0.1) LUSPR=INT(PAR(3)+0.1) WKENDOBS=INT(PAR(4)+0.1) HOLOBS=INT(PAR(5)+0.1) MAXSELL=PAR(6)/1000 C Read Inputs HOUR=INT(XIN(1))+1 IF (HOUR.EQ.0) HOUR=24 HRYEAR=XIN(2) MONTH=INT(XIN(3)+0.1) YEAR=INT(XIN(4)+0.1) LOAD=XIN(5)/1000 WKENDFLAG=INT(XIN(6)+0.1) HOLFLAG=INT(XIN(7)+0.1) PGEN=XIN(8)/1000 NETLOAD=LOAD-PGEN PSELL=0 PDUMP=0 IF (NETLOAD.LT.0) THEN PSELL=ABS(NETLOAD) IF (PSELL.GT.MAXSELL) THEN PDUMP=PSELL-MAXSELL PSELL=MAXSELL NETLOAD=(-1)*PSELL ENDIF ENDIF C Read Schedule from data file REWIND (LUSCHD) READ (LUSCHD,*,ERR=500,END=500) (NYEARDIV) N=INT(NYEARDIV+0.1) DO 10 J=1,N READ (LUSCHD,*,ERR=500,END=500) (FILELINE(K),K=1,52) HOURSTART(J)=FILELINE(1) HOUREND(J)=FILELINE(2) DO 20 K=1,24 USESCHD(J,K)=FILELINE(K+2) DEMSCHD(J,K)=FILELINE(K+27) 20 CONTINUE USEWKEND(J)=FILELINE(27) DEMWKEND(J)=FILELINE(52) 10 CONTINUE READ (LUSCHD,*,ERR=500,END=500) (DEMROLLRATE) C Clear Rolling Demand Array and Cumulative Use Variables DO 40 J =1,12 ROLLSTORE(J)=0 40 CONTINUE USECUM=0 LOADCUM=0 DEMCUM=0 MAXNETLOAD=0 TOTALBILL=0 MONSAVE=0 C Write Labels in Spreadsheet-readable output file WRITE (LUSPR,1020) WRITE (LUSPR,1021) 1020 FORMAT ('Month',1X,'Year',1X,'Usage',1X,'MaxLoad',1X & 'UsageChg',1X,'DemandChg',1X,'12-MonDemChg',1X, & 'TotalChg',1X,'CumulativeTotal') 1021 FORMAT('/',1X,'/',1X,'kW-hr',1X,'kW',1X,'$$$',1X,'$$$',1X,'$$$', & 1X,'$$$',1X,'$$$') IF (MOD(YEAR,4).EQ.0) THEN LEAP=1 ELSE LEAP=0 ENDIF OLDMONTH=INT(XIN(1)+0.1) OLDTIME=-1.0 C On first call of simulation, exit unit without performing calculations GOTO 3000 ENDIF C Component should only be called once per timestep. If it is called more, C exit unit IF (TIME.EQ.OLDTIME) GOTO 3000 C Read Inputs HOUR=INT(XIN(1))+1 IF (HOUR.EQ.0) HOUR=24 HRYEAR=XIN(2) MONTH=INT(XIN(3)+0.1) YEAR=INT(XIN(4)+0.1) LOAD=XIN(5)/1000 WKENDFLAG=INT(XIN(6)+0.1) HOLFLAG=INT(XIN(7)+0.1) PGEN=XIN(8)/1000 NETLOAD=LOAD-PGEN PSELL=0 PDUMP=0 IF (NETLOAD.LT.0) THEN PSELL=ABS(NETLOAD) IF (PSELL.GT.MAXSELL) THEN PDUMP=PSELL-MAXSELL PSELL=MAXSELL NETLOAD=(-1)*PSELL ENDIF ENDIF C Check for end-of-month. If month has changed, print bill IF ((OLDMONTH.LT.MONTH).OR.(OLDMONTH.GT.MONTH)) THEN SIMEND=0 MONTHDIS=OLDMONTH GOTO 2000 ENDIF C Determine Which Yearly Bracket to Use for rate calculations 49 J=1 50 IF (((HRYEAR.EQ.HOURSTART(J)).OR.(HRYEAR.GT.HOURSTART(J))). & AND.(HRYEAR.LT.HOUREND(J)+1)) THEN YEARDIV=J J=0 GOTO 60 ENDIF J=J+1 IF (J.GT.(INT(NYEARDIV)+0.01)) THEN GOTO 500 ELSE GOTO 50 ENDIF C Check for weekends and holidays, determine instantaneous demand and usage charge 60 IF (((WKENDFLAG.EQ.1).AND.(WKENDOBS.EQ.1)).OR. &((HOLFLAG.EQ.1).AND.(HOLOBS.EQ.1))) THEN USERATE=USEWKEND(YEARDIV) DEMRATE=DEMWKEND(YEARDIV) ELSE USERATE=USESCHD(YEARDIV,(INT(HOUR)+0.001)) DEMRATE=DEMSCHD(YEARDIV,(INT(HOUR)+0.001)) ENDIF DEMAND=DEMRATE*NETLOAD USEAGE=USERATE*(NETLOAD*DELT) IF (DEMAND.LT.0) DEMAND=0 C Calculate cumulative useage, monthly demand, savings USECUM=USECUM+USEAGE LOADCUM=LOADCUM+(NETLOAD*DELT) IF (DEMAND.GT.DEMCUM) DEMCUM=DEMAND IF (NETLOAD.GT.MAXNETLOAD) MAXNETLOAD=NETLOAD MONSAVE=(PGEN-PDUMP)*USERATE C Check for end-of-simulation: If this is final timestep, print bill IF (TIME.EQ.TFINAL) THEN SIMEND=1 MONTHDIS=MONTH GOTO 2000 ENDIF C Set output, end unit call 3000 SOLFRAC=PGEN/(LOAD+0.000001) IF (SOLFRAC.GT.1) SOLFRAC=1 IF (NETLOAD.LT.0) NETLOAD=0 PBUY=NETLOAD IF (NETLOAD.LT.0) PBUY=0 OUT(1)=USERATE OUT(2)=DEMRATE OUT(3)=NETLOAD OUT(4)=PBUY*1000 OUT(5)=PSELL*1000 OUT(6)=PBUY*USERATE OUT(7)=PSELL*USERATE OUT(8)=MONSAVE OUT(9)=SOLFRAC OLDMONTH=MONTH IF (NOT(INFO(7).EQ.-1)) OLDTIME=TIME RETURN 1 C Print the utility bill, either at the end of month or end of simulation C Update rolling demand array 2000 DO 70 J=1,12 OLDROLL(J)=ROLLSTORE(J) 70 CONTINUE ROLLSTORE(1)=MAXNETLOAD DO 80 J=1,11 ROLLSTORE(J+1)=OLDROLL(J) 80 CONTINUE C Determine rolling demand for this month ROLLLOAD=0 DO 90 J=1,12 IF (ROLLSTORE(J).GT.ROLLLOAD) ROLLLOAD=ROLLSTORE(J) 90 CONTINUE DEMROLLCHG=ROLLLOAD*DEMROLLRATE TOTALCHG=USECUM+DEMCUM+DEMROLLCHG TOTALBILL=TOTALBILL+TOTALCHG C Append the electric bill file IF ((MONTH.EQ.1).AND.(SIMEND.EQ.0)) THEN YEARDIS=YEAR-1 ELSE YEARDIS=YEAR ENDIF C Print Bill WRITE (LUBILL,1000) MONTHNAME(MONTHDIS),YEARDIS WRITE (LUBILL,1001) LOADCUM WRITE (LUBILL,1002) USECUM WRITE (LUBILL,1003) MAXNETLOAD WRITE (LUBILL,1004) DEMCUM WRITE (LUBILL,1005) DEMROLLCHG WRITE (LUBILL,1006) TOTALCHG 1000 FORMAT(//,'Month:',A12,1X,'Year:',I4) 1001 FORMAT(/,'Total Energy Usage: ',F12.1, & ' kW-hr') 1002 FORMAT('Usage Charge: $',F12.2) 1003 FORMAT('Maximum Load for Month: ',F12.2,' kW') 1004 FORMAT('Monthly Demand Charge: $',F12.4) 1005 FORMAT('Twelve Month Rolling Demand Charge: $',F12.2) 1006 FORMAT('MONTHLY ELECTRICITY CHARGE: $',F12.2,//) C Print Spreadsheet-Readable Output File WRITE (LUSPR,1010) MONTHABR(MONTHDIS),YEARDIS,LOADCUM,MAXNETLOAD, & USECUM, DEMCUM, DEMROLLCHG,TOTALCHG,TOTALBILL 1010 FORMAT(A3,1X,I4,1X,F12.2,1X,F12.2,1X,F12.2,1X,F12.2,1X,F12.2, & 1X,F12.2,1X,F13.2) C Reset Monthly Variables LOADCUM=0 USECUM=0 MAXNETLOAD=0 DEMCUM=0 C End of simulation? If so, set outputs and leave component IF (SIMEND.EQ.1) THEN WRITE (LUBILL,1007) TOTALBILL 1007 FORMAT('///TOTAL CHARGE FOR BILLING PERIOD: $',F13.2,/) GOTO 3000 ENDIF C If not, perform load calculations for this timestep GOTO 49 C Update TRNSYS list file to indicate error reading utility data 500 WRITE(LUW,501) 71,INFO(1),INFO(2) 501 FORMAT(//,1X,'***** ERROR *****',8X,'TRNSYS ERROR # ',I3,/1X, .'UNIT ',I3,' TYPE ',I3,/1X, .'UNABLE TO CORRECTLY READ THE SPECIFIED DATA FILE') CALL MYSTOP(71) END