subroutine integrator455(time,delt,time0,tfinal,nin,par,xin,out,store,first_run)

!C-----------------------------------------------------------------------------------------------------------------------
!C    PERIODIC SUMMARY ROUTINE                              
!C                                                                
!C    THIS ROUTINE TAKES UP TO TEN INPUTS AND CALCULATES THE MEAN, STANDARD DEVIATION, MINIMUM, MAXIMUM AND VARIANCE 
!C    OF EACH INPUT. THIS ROUTINE WILL ALSO CALCULATE THE INTEGRAL OF EACH INPUT WITH RESPECT TO TIME - OR THE SUM OF 
!C    THE INPUT OVER THE TIME RANGE.
!C                                                    
!C    REVISION HISTORY
!C      2/03 - JWT - ADDED TO VERSION 16     
!C      7/04 - JWT - FIXED A BUG WITH DAILY RESETS     
!C     10/06 - DAA - FIXED A BUG WITH DAILY RESETS, WHEN THE INITIAL TIME OF SIMULATION WAS DIFFERENT THAN 0
!C-----------------------------------------------------------------------------------------------------------------------

!    TRNSYS DECLARATIONS
    IMPLICIT NONE						!REQUIRES THE USER TO DEFINE ALL VARIABLES BEFORE USING THEM
    INTEGER, PARAMETER :: iknd=SELECTED_INT_KIND(8)  ! nobody does this
    INTEGER, PARAMETER :: DP=SELECTED_REAL_KIND(14)  ! this is double precision
    INTEGER, PARAMETER :: SP=SELECTED_REAL_KIND(6)  ! this is single precision
    real(DP), intent(in) :: XIN(10)				!THE ARRAY FROM WHICH THE INPUTS TO THIS TYPE WILL BE RETRIEVED
    real(DP), intent(out) :: OUT(100)				!THE ARRAY WHICH WILL BE USED TO STORE THE OUTPUTS FROM THIS TYPE
    !real(DP), intent(in) :: TIME				!THE CURRENT SIMULATION TIME - YOU MAY USE THIS VARIABLE BUT DO NOT SET IT!
    real(DP), intent(in) :: DELT,TIME
    real(DP), intent(in) :: PAR(70)				!THE ARRAY FROM WHICH THE PARAMETERS FOR THIS TYPE WILL BE RETRIEVED
    real(DP) :: T					!AN ARRAY CONTAINING THE RESULTS FROM THE DIFFERENTIAL EQUATION SOLVER

!C-----------------------------------------------------------------------------------------------------------------------
!C    DECLARATIONS AND DEFINITIONS FOR THE USER-VARIABLES
!C    IQUANT(I)  - TELLS ROUTINE WHETHER INPUT(I) IS A RATE OR NOT
!C    KEEP(I)    - POINTER INTO MONTH ARRAY
!C    LAST(I)    - TIME FOR END OF SUMMARY OF INPUT(I) = F(LENGTH,REPEAT)
!C    MEAN(I)    - THE AVERAGE VALUE OF INPUT I
!C    MONTH      - ARRAY CONTAINING ENDING HOURS OF MONTHS
!C    MONTH1,2,3 - LOGICAL VARIABLES INDICATING MONTHLY
!C    NEWVAL(I)  - TIME FOR NEXT RESET
!C    NEXT(I)    - TIME TO START EVALUATING INPUT (I) = F(TON,REPEAT)
!C    NTGRAL(I)  - INTEGRAL OF XIN(I) WITH RESPECT TO TIME
!C    NUM(I)     - NUMBER OF VALUES OF INPUT I
!C    XREPEAT(I)  - REPEAT TIME FOR SUMMARY OF INPUT(I)
!C    RESET(I)   - RESET TIME FOR SUMMARY OF INPUT(I)
!C    SSQ(I)     - SUM OF SQUARES OF VAL(I)-MEAN(I)
!C    START(I)   - START TIME FOR SUMMARY OF INPUT(I)
!C    STDEV(I)   - STANDARD DEVIATION OF SAMPLE INPUT I
!C    XSTOP(I)    - STOP TIME FOR SUMMARY OF INPUT(I)
!C    XSUM(I)     - SUM OF INPUTS I OVER TIME RANGE
!C    SUMSQ(I)   - SUM OF (INPUT I)^2 OVER TIME RANGE
!C    TMAX(I)    - TIME AT WHICH MAXIMUM VALUE OF INPUT I OCCURRED
!C    TMIN(I)    - TIME AT WHICH MINIMUM VALUE OF INPUT I OCCURRED
!C    TON(I)     - TIME OF DAY FOR START OF PERIODIC SUMMARY OF INPUT(I)
!C    LENGTH(I)  - LENGTH OF TIME FOR PERIODIC SUMMARY OF INPUT(I)
!C    VAL(I)     - INPUT I
!C    VAR(I)     - VARIANCE OF INPUT I
!C    VMAX(I)    - MAXIMUM VALUE OF INPUT I
!C    VMIN(I)    - MINIMUM VALUE OF INPUTS I

    real(DP) NTGRAL,NEXT,LAST,NEWVAL,MEAN,VMIN,VMAX, &
    TMIN,TMAX,TON,LENGTH,START,XSTOP,RESET,XREPEAT,XSUM,STDEV,VAL, &
    SSQ,SUMSQ,M1,M2,M3,VAR,DUMM,TIME0_MOD,STORE(251),TIME0,TFINAL, &
    month,temp
    INTEGER IQUANT,I,KEEP,NUM,J,II,JJ,IYEAR,IMONTH,nin
    LOGICAL MONTH1,MONTH2,MONTH3,CONT

    DIMENSION TON(10),LENGTH(10),START(10),XSTOP(10),RESET(10)
    DIMENSION IQUANT(10),NEXT(10),LAST(10),NUM(10),NEWVAL(10)
    DIMENSION XSUM(10),MEAN(10),STDEV(10),VMIN(10),VMAX(10)
    DIMENSION VAL(10),MONTH(0:13),KEEP(10),SSQ(10),TMIN(10),TMAX(10)
    DIMENSION VAR(10),MONTH1(10),MONTH2(10),MONTH3(10),NTGRAL(10)
    DIMENSION SUMSQ(10),M1(10),M2(10),M3(10),XREPEAT(10)
    logical first_run
    DATA MONTH /0.,744.,1416.,2160.,2880.,3624.,4344.,5088.,5832., &
              6552.,7296.,8016.,8760.,9504./
    !save store
    save month
    !save first_run
    !first_run
!    DO ALL OF THE INITIAL TIMESTEP MANIPULATIONS HERE - THERE ARE NO ITERATIONS AT THE INTIAL TIME
 !IF(.not.first_run)then 
 if (time < delt)THEN
    first_run = .true.
    !       READ IN THE VALUES OF THE PARAMETERS IN SEQUENTIAL ORDER
    DO I=1,NIN
        J=int((I-1)*7)
        IQUANT(I)=int(PAR(1+J)+0.5D0)
        TON(I)=PAR(2+J)
        LENGTH(I)=PAR(3+J)
        XREPEAT(I)=PAR(4+J)
        RESET(I)=PAR(5+J)
        START(I)=PAR(6+J)
        XSTOP(I)=PAR(7+J)
        !          CHECK THE PARAMETERS FOR PROBLEMS AND RETURN FROM THE SUBROUTINE IF AN ERROR IS FOUND
        IF(START(I) >= XSTOP(I)) write(*,510) "start >= stop"
        IF(TON(I) >= XSTOP(I)) write(*,510) "ton >= stop" 
        510 format(a)
    ENDDO
!       DO SOME INITIAL PROCESSING
    DO I=1,NIN
    !          CHECK TO SEE IF STOP TIME SHOULD BE THE END OF THE MONTH
        IF(LENGTH(I) < 0.D0) THEN
            MONTH1(I)=.TRUE.
            M1(I)=1.D0
        ELSE
            MONTH1(I)=.FALSE.
            M1(I)=0.D0
        ENDIF
        !          CHECK TO SEE IF REPEAT TIME IS MONTHLY
        IF(XREPEAT(I) < 0.D0) THEN
           MONTH2(I)=.TRUE.
           M2(I)=1.D0
        ELSE IF (MONTH1(I)) THEN
           MONTH2(I)=.TRUE.
           M2(I)=1.D0
        ELSE
           MONTH2(I)=.FALSE.
           M2(I)=0.D0
        ENDIF
    !          CHECK TO SEE IF RESET TIME IS MONTHLY
        IF(RESET(I) < 0.D0) THEN
           MONTH3(I)=.TRUE.
           M3(I)=1.D0
        ELSE
           MONTH3(I)=.FALSE.
           M3(I)=0.D0
        ENDIF
    !          SET INITIAL NEXT VALUES FOR EACH INPUT
        IF(TON(I) < 0.D0) THEN
           NEXT(I)=0.D0
        ELSE IF(NEXT(I) < (TIME0-DELT/2.D0)) THEN
          NEXT(I)=TON(I)+(TIME0-DMOD(TIME0,24.D0))
          IF(NEXT(I) < (TIME0-DELT/2.D0)) NEXT(I)=NEXT(I)+24.D0
        ELSE
          NEXT(I)=TON(I)
        ENDIF
    !          DETERMINE THE MONTH CONTAINING TIME0
        IF(MONTH1(I).OR.MONTH2(I).OR.MONTH3(I)) THEN
         IYEAR=int(TIME0/8760.D0)
         TIME0_MOD=TIME0-DBLE(IYEAR)
           DO II=1,13
              IF (MONTH(II) > TIME0_MOD) THEN
                 KEEP(I)=II+12*IYEAR
                 GO TO 200
              ENDIF
           ENDDO
        ENDIF
        200        CONTINUE
    !         SET THE INITIAL VALUES OF LAST
        IF (MONTH1(I)) THEN
        IMONTH=KEEP(I)
        IYEAR=0
        210	        IF(IMONTH > 12) THEN
           IYEAR=IYEAR+1
           IMONTH=IMONTH-12
           GOTO 210
        ENDIF
          LAST(I)=MONTH(IMONTH)+DBLE(IYEAR)*8760.D0
        ELSE
          LAST(I)=NEXT(I)+LENGTH(I)
        ENDIF
    !          SET THE INITIAL VALUE OF THE RESET TIME
        IF(MONTH3(I)) THEN
        IMONTH=KEEP(I)
        IYEAR=0
        220	        IF(IMONTH > 12) THEN
             IYEAR=IYEAR+1
             IMONTH=IMONTH-12
           GOTO 220
        ENDIF
           RESET(I)=MONTH(IMONTH)+DBLE(IYEAR)*8760.D0
           NEWVAL(I)=RESET(I)
        ELSE IF(TON(I) <= 0.) THEN
           NEWVAL(I)=RESET(I)
        ELSE
           NEWVAL(I)=TIME0 + TON(I)+RESET(I)
        ENDIF

    !         INITIALIZE VARIABLE ARRAYS
        XSUM(I)=0.D0
        NTGRAL(I)=0.D0
        VMIN(I)=1.0D12
        VMAX(I)=-1.0D12
    ENDDO

!       PERFORM ANY REQUIRED CALCULATIONS TO SET THE INITIAL STORAGE VARIABLES HERE
    DO I=1,NIN
        STORE(I)=DBLE(IQUANT(I))
        STORE(I+10)=LENGTH(I)
        STORE(I+20)=XREPEAT(I)
        STORE(I+30)=RESET(I)
        STORE(I+40)=START(I)
        STORE(I+50)=XSTOP(I)
        STORE(I+60)=M1(I)
        STORE(I+70)=M2(I)
        STORE(I+80)=M3(I)
        STORE(I+90)=NEXT(I)
        STORE(I+100)=LAST(I)
        STORE(I+120)=XSUM(I)
        STORE(I+140)=NTGRAL(I)
        STORE(I+150)=VMAX(I)
        STORE(I+170)=VMIN(I)
        STORE(I+230)=DBLE(KEEP(I))
        STORE(I+240)=NEWVAL(I)
    ENDDO

!       PERFORM ANY REQUIRED CALCULATIONS TO SET THE INITIAL VALUES OF THE OUTPUTS HERE
    DO JJ=1,3*nin
      OUT(JJ)=0.D0
    ENDDO

!else
endif
!imonth = store(251)
        if(time >= 8759.75)then
        temp = 1
      endif
!    RETRIEVE ANY VALUES NEEDED FROM THE STORAGE ARRAY
      DO I=1,NIN
	     IQUANT(I)=int(STORE(I)+0.5D0)
         LENGTH(I)=STORE(I+10)
         XREPEAT(I)=STORE(I+20)
         RESET(I) =STORE(I+30)
         START(I) =STORE(I+40)
         XSTOP(I)  =STORE(I+50)

         M1(I)=STORE(I+60)
         IF(M1(I) > 0.5D0) THEN
            MONTH1(I)=.TRUE.
         ELSE
            MONTH1(I)=.FALSE.
         ENDIF

         M2(I)=STORE(I+70)
         IF(M2(I) > 0.5D0) THEN
            MONTH2(I)=.TRUE.
         ELSE
            MONTH2(I)=.FALSE.
         ENDIF

         M3(I)=STORE(I+80)
         IF(M3(I) > 0.5D0) THEN
            MONTH3(I)=.TRUE.
         ELSE
            MONTH3(I)=.FALSE.
         ENDIF

         NEXT(I)  =STORE(I+90)
         LAST(I)  =STORE(I+100)
         XSUM(I)   =STORE(I+120)
         NTGRAL(I)=STORE(I+140)
         VMAX(I)  =STORE(I+150)
         VMIN(I)  =STORE(I+170)
         KEEP(I)  =JFIX(STORE(I+230)+0.5D0)
         NEWVAL(I)=STORE(I+240)

!       DETERMINE THE RELATIVE MONTHLY TIME
         IF(MONTH1(I).OR.MONTH2(I).OR.MONTH3(I)) THEN
	      IMONTH=KEEP(I)
	      IYEAR=0
 230	      IF(IMONTH > 12) THEN
               IYEAR=IYEAR+1
	           IMONTH=IMONTH-12
	         GOTO 230
	      ENDIF
         ENDIF

!       SET THE RESET AND REPEAT TIMES
         IF(MONTH3(I)) RESET(I)=MONTH(IMONTH)+DBLE(IYEAR)*8760.D0
         IF(MONTH2(I)) XREPEAT(I)=MONTH(IMONTH)+DBLE(IYEAR)*8760.D0
      ENDDO

!    RETRIEVE THE CURRENT VALUES OF THE INPUTS TO THIS MODEL FROM THE XIN ARRAY
     DO I=1,NIN
	   VAL(I)=XIN(I)
	 ENDDO
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!    PERFORM ALL THE CALCULATION HERE FOR THIS MODEL.

!    CHECK TO SEE WHETHER CURRENT TIME FALLS BETWEEN TIME RANGE FOR SUMMARY MANIPULATION AND START-STOP TIMES IF 
!    IT DOES, ALLOW SUMMARY MANIPULATION
      DO I=1,NIN
      
         IF((TIME >= (NEXT(I)+DELT/2.D0)).AND.(TIME <= (LAST(I)+DELT/2.D0)).AND. &
            (TIME >= (START(I)-DELT/2.D0)).AND.(TIME <= (XSTOP(I)+DELT/2.D0)))  THEN
            CONT=.TRUE.
         ELSE
            CONT=.FALSE.
         ENDIF

!       START THE SUMMARY FOR INPUT I
         IF(CONT) THEN
!          CALCULATE SUM AND SUM SQUARED OF I
            XSUM(I)=XSUM(I)+VAL(I)
!          CALCULATE INTEGRALS
            NTGRAL(I)=NTGRAL(I)+VAL(I)*DELT
!          CHECK TO SEE IF INPUT IS A LOCAL MINIMUM OR MAXIMUM
            IF(VAL(I) > VMAX(I)) THEN
               VMAX(I)=VAL(I)
            ENDIF
            IF(VAL(I) < VMIN(I)) THEN
               VMIN(I)=VAL(I)
            ENDIF

!          SET THE NEW RANGE VALUES FOR TIME SUMMARY IF THE NEXT TIME-
!          STEP IS OUTSIDE OF THE CURRENT RANGE
            IF(MONTH1(I)) THEN
               IF((TIME+DELT) > (LAST(I)+DELT/2.D0)) THEN
                  NEXT(I)=NEXT(I)+MONTH(IMONTH)-MONTH(IMONTH-1)
                  LAST(I)=MONTH(IMONTH+1)+DBLE(IYEAR)*8760.D0
               ENDIF
            ELSE
               IF((TIME+DELT) >= (LAST(I)+DELT/2.D0)) THEN
                  IF(MONTH2(I)) THEN
                     NEXT(I)=NEXT(I)+MONTH(IMONTH)-MONTH(IMONTH-1)
                     LAST(I)=NEXT(I)+LENGTH(I)
                  ELSE
                     NEXT(I)=NEXT(I)+XREPEAT(I)
                     LAST(I)=NEXT(I)+LENGTH(I)
                  ENDIF
               ENDIF
            ENDIF
         ELSE
	      IF(MONTH1(I)) THEN
               IF((TIME+DELT) > (LAST(I)+DELT/2.D0)) THEN
                  NEXT(I)=NEXT(I)+MONTH(IMONTH)-MONTH(IMONTH-1)
                  LAST(I)=MONTH(IMONTH+1)+DBLE(IYEAR)*8760.D0
               ENDIF
            ELSE
               IF((TIME+DELT) >= (LAST(I)+DELT/2.D0)) THEN
                  IF(MONTH2(I)) THEN
                     NEXT(I)=NEXT(I)+MONTH(IMONTH)-MONTH(IMONTH-1)
                     LAST(I)=NEXT(I)+LENGTH(I)
                  ELSE
                     NEXT(I)=NEXT(I)+XREPEAT(I)
                     LAST(I)=NEXT(I)+LENGTH(I)
                  ENDIF
               ENDIF
            ENDIF
         ENDIF
	ENDDO
	
!    SET THE OUTPUTS FROM THIS MODEL
    DO I=1,NIN
        J=int((I-1)*10)
        IF(IQUANT(I) > 0) THEN
            OUT(1+J)=NTGRAL(I)
        ELSE
            OUT(1+J)=XSUM(I)
        ENDIF
        OUT(2+J)=VMIN(I)
        OUT(3+J)=VMAX(I)
    ENDDO

!    UPDATE THE RESET TIMES
    DO I=1,NIN
        IF(((TIME >= (NEWVAL(I)-DELT/2.D0)).AND.(TIME <= (NEWVAL(I)+DELT/2.D0)).OR.(TIME >= (TFINAL-DELT/2.D0)))) THEN

        !          RESET THE VALUES
        NTGRAL(I)=0.D0
        VMIN(I)=1.0D12
        VMAX(I)=-1.0D12
        XSUM(I)=0.D0

        !          SET THE NEW RESET TIME
        IF(MONTH3(I)) THEN
           NEWVAL(I)=MONTH(IMONTH+1)+DBLE(IYEAR)*8760.D0
        ELSE
           NEWVAL(I)=NEWVAL(I)+RESET(I)
        ENDIF
        ENDIF

        !       UPDATE THE MONTH COUNTER
        IF(TIME >= (MONTH(IMONTH)+DBLE(IYEAR)*8760.D0-DELT/2.D0)) THEN
        KEEP(I)=KEEP(I)+1
        ENDIF

    ENDDO

!    RESET THE STORAGE VARIABLES
    DO I=1,NIN
        STORE(I+20)=XREPEAT(I)
        STORE(I+30)=RESET(I)
        STORE(I+90)=NEXT(I)
        STORE(I+100)=LAST(I)
        STORE(I+120)=XSUM(I)
        STORE(I+140)=NTGRAL(I)
        STORE(I+150)=VMAX(I)
        STORE(I+170)=VMIN(I)
        STORE(I+230)=DBLE(KEEP(I))
        STORE(I+240)=NEWVAL(I)
    ENDDO
!endif
store(251) = imonth
return
end subroutine integrator455