SUBROUTINE integrator24(time,delt,tfinal,ni_deck,XIN,reset,base, &
                        out,store,first_run)				
!C-----------------------------------------------------------------------------------------------------------------------
!C     THIS TYPE INTEGRATES A SERIES OF INPUTS.  IT WAS WRIITEN TO REPLACE THE ORIGINAL
!C     INTEGRATOR WHICH HAS BEEN A PART OF THE TRNSYS KERNAL SINCE BEFORE THE DAWN OF MAN.
!C     UP TO 250 INPUTS MAY BE INTEGRATED IN ITS DEFAULT FORM.  THE USER MAY MODIFY THE MAXIMUM
!C     NUMBER OF INPUTS BY CHANGING THE NI=250 DECLARATION.  THE OUTPUTS FROM THIS TYPE ARE
!C     THE CURRENT INTEGRATED VALUES OF THE INPUTS.
!C
!C     LAST MODIFIED:
!C       7/02 -- JWT - ORIGINAL WORK
!C-----------------------------------------------------------------------------------------------------------------------
! Copyright © 2004 Solar Energy Laboratory, University of Wisconsin-Madison. All rights reserved.

!    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
INTEGER, intent(in) :: NI_DECK 					!NUMBER OF INPUTS IN THE INPUT FILE
real(DP),intent(in) :: XIN(NI_deck)				!THE ARRAY FROM WHICH THE INPUTS TO THIS TYPE WILL BE RETRIEVED
real(DP),intent(out) :: OUT(NI_deck)				!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) :: T,store(3)				!AN ARRAY CONTAINING THE RESULTS FROM THE DIFFERENTIAL EQUATION SOLVER
real(DP),intent(in) ::  tfinal

!    DECLARATIONS AND DEFINITIONS FOR THE USER-VARIABLES
INTEGER :: J		 					!A COUNTER VARIABLE
INTEGER*8 :: I_RESETS 					!THE NUMBER OF RESETS THAT HAVE OCCURED SO FAR
INTEGER :: IMONTH	 					!A MONTHLY COUNTER VARIABLE
INTEGER*8 :: I_STEPS 					!NUMBER OF TIMESTEPS IN A RESET TIME
INTEGER :: IYEARS						!AN INDICATOR OF THE CURRENT YEAR
LOGICAL MONTHLY						!LOGICAL VARIABLE FOR MONTHLY RESETS    
real(DP) :: MONTH_TIME(0:12)	!THE ENDING TIME OF EACH MONTH OF THE YEAR
real(DP) :: RESET				!THE RESET TIME
real(DP) :: RESET2				!THE RESET TIME
real(DP) :: BASE				!AN INDICATOR FOR RELATIVE OR ABSOLUTE RESET TIMES
real(DP) :: TIME_ROUND			!THE AMOUNT OF TIME LOST BY ROUNDING THE RESET TIME TO A NUMBER OF TIMESTEPS
real(DP) :: TIME_NOW			!THE CURRENT ANNUALIZE TIME
real(DP) :: TIME_NEXT			!THE NEXT TIME AT WHICH THE OUTPUTS SHOULD BE RESET
real(DP) :: temp
logical first_run
!INDICATES WHETHER THE RESET SHOULD BE RELATIVE OR ABSOLUTE
!0 OR LESS = RELATIVE TIME,GREATER THAN 0 = ABSOLUTE TIME

DATA MONTH_TIME/0.D0,744.D0,1416.D0,2160.D0,2880.D0,3624.D0, &
                4344.D0,5088.D0,5832.D0,6552.D0,7296.D0,8016.D0, &
                8760.D0/
save month_time
!save store
!save first_run
!first_run
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!IF(.not.first_run)THEN
if (time < delt) then
    first_run = .true.
!       DETERMINE HOW MANY TIMESTEPS ARE CONTAINED IN THE RESET TIME
    IF(RESET > 0) THEN
        MONTHLY = 0

    !         CHECK THE RESET TIME FOR REASONABLENESS
        IF(RESET > TFINAL) RESET = TFINAL

        I_STEPS = int(RESET/DELT+0.5)

    !          CHECK TO SEE HOW MUCH TIME HAS BEEN ROUNDED AND WARN THE USER IF ITS A PROBLEM
        TIME_ROUND = ABS(DBLE(I_STEPS)*DELT-RESET)
    ELSE
        MONTHLY = 1
    ENDIF

    RESET2 = DBLE(I_STEPS)*DELT

!       DETERMINE THE NEXT RESET TIME FOR MONTHLY INTEGRATIONS
    IF(MONTHLY > 0) THEN
        TIME_NOW = MOD(TIME,8760.D0)
        IYEARS = int((TIME-DELT/2.D0)/8760.D0)
        IMONTH = 1
        DO J = 1,12
            IF((TIME_NOW+DELT/2.D0) > MONTH_TIME(J)) IMONTH = IMONTH+1
        ENDDO
        TIME_NEXT = MONTH_TIME(IMONTH)+DBLE(IYEARS)*8760.D0

    !       DETERMINE THE NEXT RESET TIME FOR RELATIVE INTEGRATIONS
    ELSEIF(BASE <= 0.D0) THEN
        TIME_NEXT = RESET2

    !       DETERMINE THE NEXT RESET TIME FOR ABSOLUTE INTEGRATIONS
    ELSE
        I_RESETS = int((DELT/2.D0)/RESET2)
        TIME_NEXT = (DBLE(I_RESETS)+1)*RESET2
    ENDIF

    !       SET THE INITIAL STORAGE VARIABLES
    !CALL setStorageVars(TIME_NEXT,1,INFO)

    DO J=1,NI_DECK
      OUT(J) = OUT(J)+DELT*XIN(J)
    ENDDO

    store(1) = time_next
    store(2) = monthly
    store(3) = reset2

!else
endif
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    time_next = store(1)
    monthly = store(2)
    reset2 = store(3)
    IF((TIME-DELT/2.D0) < TIME_NEXT) THEN
        DO J=1,NI_DECK
          OUT(J)=OUT(J)+DELT*XIN(J)
        ENDDO
    ELSE
    !       DETERMINE THE NEXT RESET TIME FOR MONTHLY INTEGRATIONS
        IF(MONTHLY > 0) THEN
          TIME_NOW = MOD(TIME,8760.D0)
          IYEARS = int((TIME-DELT/2.D0)/8760.D0)
          IMONTH = 1
          DO J = 1,12
             IF((TIME_NOW+DELT/2.D0) > MONTH_TIME(J)) IMONTH = IMONTH+1
          ENDDO
          TIME_NEXT = MONTH_TIME(IMONTH)+DBLE(IYEARS)*8760.D0
        ELSE
          TIME_NEXT = TIME_NEXT+RESET2
        ENDIF

        DO J = 1,NI_DECK
          OUT(J) = DELT*XIN(J)
        ENDDO

    ENDIF

    store(1) = time_next
    store(2) = monthly
!endif

RETURN 
END subroutine integrator24

