#include "FIZHI_OPTIONS.h"

C--  File fizhi_clockstuff.F:
C--   Contents
C--   o SET_ALARM
C--   o GET_ALARM
C--   o ALARM      (function)
C--   o ALARM2     (function)
C--   o ALARM2NEXT (function)
C--   o SET_TIME
C--   o GET_TIME
C--   o NSECF      (function)
C--   o NHMSF      (function)
C--   o NSECF2     (function)
C--   o FIXDATE
C--   o INTERP_TIME
C--   o TICK
C--   o TIC_TIME
C--   o NALARM     (function)
C--   o NALARM2    (function)
C--   o INCYMD     (function)
C--   o ASTRO
C--   o TIME_BOUND
C--   o TIME2FREQ2

C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|

      subroutine set_alarm (tag,datein,timein,freq)
C***********************************************************************
C  Purpose
C  -------
C     Utility to Set Internal Alarms
C
C  Argument Description
C  --------------------
C     tag ....... Character String Tagging Alarm Process
C     date ...... Begining Date for Alarm
C     time ...... Begining Time for Alarm
C     freq ...... Repeating Frequency Interval for Alarm
C
C***********************************************************************

      implicit none
#include "EEPARAMS.h"
#include "chronos.h"

      character*(*) tag
      integer       freq,datein,timein

C-    functions:
      INTEGER  ILNBLNK
      EXTERNAL ILNBLNK

C-    local variables:
      integer myid
      logical first,set
      data          first /.true./
      integer n, iL

      myid = 1
      if(first) then
         ntags    = 1
          tags(1) = tag
         freqs(1) = freq
         dates(1) = datein
         times(1) = timein
         iL = ILNBLNK(tag)
         WRITE(standardMessageUnit,'(A,I8,A,I6.6,A,I10,2A)')
     &    '  Set Alarm for: ', datein, '  ', timein,
     &    ', with frequency: ', freq, ', and Tag: ',tag(1:iL)
      else

      set = .false.
      do n=1,ntags
       if(tag.eq.tags(n)) then
        if( myid.eq.1 ) then
         print *, 'Warning!  Alarm has already been set for Tag: ',tag
         print *, 'Changing  Alarm Information:'
         print *, 'Frequency: ',freqs(n),' (Old) ',freq,' (New)'
         print *, '    Date0: ',dates(n),' (Old) ',datein,' (New)'
         print *, '    Time0: ',times(n),' (Old) ',timein,' (New)'
        endif
        freqs(n) = freq
        dates(n) = datein
        times(n) = timein
        set = .true.
       endif
      enddo
      if(.not.set) then
            ntags = ntags+1
         if(ntags.gt.maxtag ) then
            if( myid.eq.1 ) then
            print *, 'Too many Alarms are Set!!'
            print *, 'Maximum Number of Alarms = ',maxtag
            endif
         call my_finalize
         call my_exit (101)
         endif
          tags(ntags) = tag
         freqs(ntags) = freq
         dates(ntags) = datein
         times(ntags) = timein
         iL = ILNBLNK(tag)
         WRITE(standardMessageUnit,'(A,I8,A,I6.6,A,I10,2A)')
     &    '  Set Alarm for: ', datein, '  ', timein,
     &    ', with frequency: ', freq, ', and Tag: ',tag(1:iL)
      endif
      endif

      first = .false.
      return
      end

      subroutine get_alarm (tag,datein,timein,freq,tleft)
C***********************************************************************
C  Purpose
C  -------
C     Utility to Get Internal Alarm Information
C
C  Input
C  -----
C     tag ....... Character String Tagging Alarm Process
C
C  Output
C  ------
C     datein ...... Begining  Date for Alarm
C     timein ...... Begining  Time for Alarm
C     freq ........ Frequency Interval for Alarm
C     tleft ....... Time Remaining (seconds) before Alarm is TRUE
C
C***********************************************************************

      implicit none
      character*(*) tag
      integer freq,datein,timein,tleft

#include "chronos.h"

      logical set,alarm
      external alarm
      integer myid,n,nalarm,nsecf

      myid = 1
      set = .false.
      do n=1,ntags
       if (tag.eq.tags(n)) then
         freq   = freqs(n)
         datein = dates(n)
         timein = times(n)

         if ( alarm(tag) ) then
          tleft = 0
         else
          call get_time (nymd,nhms)
          tleft = nsecf(freq) - nalarm(freq,nymd,nhms,datein,timein )
         endif

         set = .true.
       endif
      enddo

      if(.not.set) then
      if( myid.eq.1 ) print *, 'Alarm has not been set for Tag: ',tag
      freq  = 0
      datein  = 0
      timein  = 0
      tleft = 0
      endif

      return
      end

      LOGICAL FUNCTION ALARM (tag)
      implicit none
      character*(*) tag
#include "chronos.h"

      integer datein,timein
      integer n,nalarm
      external nalarm

      call get_time (datein,timein)

      alarm = .false.
      do n=1,ntags
       if( tags(n).eq.tag  ) then
        if( freqs(n).eq.0 ) then
          alarm = (dates(n).eq.datein) .and. (times(n).eq.timein)
        else
          alarm = ( datein.gt.dates(n) .or.
     &             (datein.eq.dates(n) .and. timein.ge.times(n)) )
     &    .and. nalarm( freqs(n),datein,timein,dates(n),times(n) ).eq.0
        endif
       endif
      enddo

      return
      end

      LOGICAL FUNCTION ALARM2 (tag)
      implicit none
      character*(*) tag
#include "chronos.h"

      integer datein,timein
      integer n,nalarm2
      external nalarm2

      call get_time (datein,timein)

      alarm2 = .false.
      do n=1,ntags
       if( tags(n).eq.tag  ) then
        if( freqs(n).eq.0 ) then
          alarm2 = (dates(n).eq.datein) .and. (times(n).eq.timein)
        else
          alarm2 = ( datein.gt.dates(n) .or.
     &              (datein.eq.dates(n) .and. timein.ge.times(n)) )
     &    .and. nalarm2( freqs(n),datein,timein,dates(n),times(n) ).eq.0
        endif
       endif
      enddo

      return
      end

      LOGICAL FUNCTION ALARM2NEXT (tag,deltat)
      implicit none
      character*(*) tag
      _RL deltat
#include "chronos.h"

      integer datein,timein,ndt
      integer dateminus,timeminus
      integer n,nalarm2
      external nalarm2

      ndt = int(deltat)
      call get_time (dateminus,timeminus)
      datein = dateminus
      timein = timeminus
      call tick(datein,timein,ndt)

      alarm2next = .false.
      do n=1,ntags
       if( tags(n).eq.tag  ) then
        if( freqs(n).eq.0 ) then
          alarm2next = (dates(n).eq.datein) .and. (times(n).eq.timein)
        else
          alarm2next = ( datein.gt.dates(n) .or.
     &                  (datein.eq.dates(n) .and. timein.ge.times(n)) )
     &    .and. nalarm2( freqs(n),datein,timein,dates(n),times(n) ).eq.0
        endif
       endif
      enddo

      return
      end

      subroutine set_time (datein,timein)
      implicit none
      integer  datein,timein

#include "chronos.h"

      integer myid

      myid = 1
      if(  myid.eq.1 ) then
      print *, 'Setting Clock'
      print *, 'Date: ',datein
      print *, 'Time: ',timein
      endif

      nymd = datein
      nhms = timein
      return
      end

      subroutine get_time (datein,timein)
      implicit none
      integer datein,timein

#include "chronos.h"

      datein = nymd
      timein = nhms
      return
      end

      function nsecf (nhms)
C***********************************************************************
C  Purpose
C     Converts NHMS format to Total Seconds
C
C***********************************************************************
      implicit none
      integer  nhms, nsecf
      nsecf =  nhms/10000*3600 + mod(nhms,10000)/100*60 + mod(nhms,100)
      return
      end

      function nhmsf (nsec)
C***********************************************************************
C  Purpose
C     Converts Total Seconds to NHMS format
C
C***********************************************************************
      implicit none
      integer  nhmsf, nsec
      nhmsf =  nsec/3600*10000 + mod(nsec,3600)/60*100 + mod(nsec,60)
      return
      end

      function nsecf2 (nhhmmss,nmmdd,nymd)
C***********************************************************************
C  Purpose
C     Computes the Total Number of seconds from NYMD using NHHMMSS & NMMDD
C
C  Arguments   Description
C     NHHMMSS  IntervaL Frequency (HHMMSS)
C     NMMDD    Interval Frequency (MMDD)
C     NYMD     Current  Date      (YYMMDD)
C
C  NOTE:
C     IF (NMMDD.ne.0), THEN HOUR FREQUENCY HH MUST BE < 24
C
C***********************************************************************
      implicit none

      integer nsecf2,nhhmmss,nmmdd,nymd

      INTEGER NSDAY, NCYCLE
      PARAMETER ( NSDAY  = 86400 )
      PARAMETER ( NCYCLE = 1461*24*3600 )

      INTEGER YEAR, MONTH, DAY

c     INTEGER  MNDY(12,4)
      INTEGER  MNDY(12*4)
      DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366,
     &           397,34*0 /

      integer nsecf,i,nsegm,nsegd,iday,iday2,nday

C***********************************************************************
C*                 COMPUTE # OF SECONDS FROM NHHMMSS                   *
C***********************************************************************

      nsecf2 = nsecf( nhhmmss )

      if( nmmdd.eq.0 ) return

C***********************************************************************
C*                 COMPUTE # OF DAYS IN A 4-YEAR CYCLE                 *
C***********************************************************************

      DO I=15,48
c     MNDY(I,1) = MNDY(I-12,1) + 365
        MNDY(I) = MNDY(I-12) + 365
      ENDDO

C***********************************************************************
C*                 COMPUTE # OF SECONDS FROM NMMDD                     *
C***********************************************************************

      nsegm =     nmmdd/100
      nsegd = mod(nmmdd,100)

      YEAR   = NYMD / 10000
      MONTH  = MOD(NYMD,10000) / 100
      DAY    = MOD(NYMD,100)

c     IDAY   = MNDY( MONTH ,MOD(YEAR ,4)+1 )
      IDAY   = MNDY( MONTH +12*MOD(YEAR ,4) )
      month = month + nsegm
      If( month.gt.12 ) then
      month = month - 12
      year = year + 1
      endif
c     IDAY2  = MNDY( MONTH ,MOD(YEAR ,4)+1 )
      IDAY2  = MNDY( MONTH +12*MOD(YEAR ,4) )

                    nday = iday2-iday
      if(nday.lt.0) nday = nday + 1461
                    nday = nday + nsegd

      nsecf2 = nsecf2 + nday*nsday

      return
      end

      subroutine fixdate (nymd)
      implicit none
      integer nymd

C Modify 6-digit YYMMDD for dates between 1950-2050
C -------------------------------------------------
      if (nymd .lt. 500101) then
        nymd = 20000000 + nymd
      else if (nymd .le. 991231) then
        nymd = 19000000 + nymd
      endif

      return
      end

      subroutine interp_time ( nymd ,nhms ,
     &                         nymd1,nhms1, nymd2,nhms2, fac1,fac2 )
C***********************************************************************
C
C  PURPOSE:
C  ========
C    Compute interpolation factors, fac1 & fac2, to be used in the
C    calculation of the instantanious boundary conditions, ie:
C
C               q(i,j) = fac1*q1(i,j) + fac2*q2(i,j)
C    where:
C               q(i,j) => Boundary Data valid    at (nymd  , nhms )
C              q1(i,j) => Boundary Data centered at (nymd1 , nhms1)
C              q2(i,j) => Boundary Data centered at (nymd2 , nhms2)
C
C  INPUT:
C  ======
C    nymd     : Date (yymmdd) of Current Timestep
C    nhms     : Time (hhmmss) of Current Timestep
C    nymd1    : Date (yymmdd) of Boundary Data 1
C    nhms1    : Time (hhmmss) of Boundary Data 1
C    nymd2    : Date (yymmdd) of Boundary Data 2
C    nhms2    : Time (hhmmss) of Boundary Data 2
C
C  OUTPUT:
C  =======
C    fac1     : Interpolation factor for Boundary Data 1
C    fac2     : Interpolation factor for Boundary Data 2
C
C
C***********************************************************************
      implicit none

      integer nhms,nymd,nhms1,nymd1,nhms2,nymd2
      _RL fac1,fac2

      INTEGER  YEAR , MONTH , DAY , SEC
      INTEGER  YEAR1, MONTH1, DAY1, SEC1
      INTEGER  YEAR2, MONTH2, DAY2, SEC2

      _RL time00, time1, time2

      INTEGER    DAYSCY
      parameter ( dayscy   = 365*4 + 1 )

      INTEGER MNDY(12*4)

      LOGICAL FIRST
      DATA    FIRST/.TRUE./

      DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366,
     &           397,34*0 /

      integer i,nsecf

C***********************************************************************
C*                         SET TIME BOUNDARIES                         *
C***********************************************************************

      YEAR   = NYMD / 10000
      MONTH  = MOD(NYMD,10000) / 100
      DAY    = MOD(NYMD,100)
      SEC    = NSECF(NHMS)

      YEAR1  = NYMD1 / 10000
      MONTH1 = MOD(NYMD1,10000) / 100
      DAY1   = MOD(NYMD1,100)
      SEC1   = NSECF(NHMS1)

      YEAR2  = NYMD2 / 10000
      MONTH2 = MOD(NYMD2,10000) / 100
      DAY2   = MOD(NYMD2,100)
      SEC2   = NSECF(NHMS2)

C***********************************************************************
C*                    COMPUTE DAYS IN 4-YEAR CYCLE                     *
C***********************************************************************

      IF(FIRST) THEN
      DO I=15,48
        MNDY(I) = MNDY(I-12) + 365
      ENDDO
      FIRST=.FALSE.
      ENDIF

C***********************************************************************
C*                     COMPUTE INTERPOLATION FACTORS                   *
C***********************************************************************

      time00 = DAY + MNDY(MONTH +12*MOD(YEAR ,4)) + float(sec )/86400.
      time1 = DAY1 + MNDY(MONTH1+12*MOD(YEAR1,4)) + float(sec1)/86400.
      time2 = DAY2 + MNDY(MONTH2+12*MOD(YEAR2,4)) + float(sec2)/86400.

      if( time00 .lt.time1 ) time00  = time00  + dayscy
      if( time2.lt.time1 ) time2 = time2 + dayscy

      fac1  = (time2-time00)/(time2-time1)
      fac2  = (time00-time1)/(time2-time1)

      RETURN
      END

      subroutine tick (nymd,nhms,ndt)
C***********************************************************************
C  Purpose
C     Tick the Date (nymd) and Time (nhms) by NDT (seconds)
C
C***********************************************************************
      implicit none

      integer nymd,nhms,ndt

      integer nsec,nsecf,incymd,nhmsf

      IF(NDT.NE.0) THEN
      NSEC = NSECF(NHMS) + NDT

      IF (NSEC.GT.86400)  THEN
      DO WHILE (NSEC.GT.86400)
      NSEC = NSEC - 86400
      NYMD = INCYMD (NYMD,1)
      ENDDO
      ENDIF

      IF (NSEC.EQ.86400)  THEN
      NSEC = 0
      NYMD = INCYMD (NYMD,1)
      ENDIF

      IF (NSEC.LT.00000)  THEN
      DO WHILE (NSEC.LT.0)
      NSEC = 86400 + NSEC
      NYMD = INCYMD (NYMD,-1)
      ENDDO
      ENDIF

      NHMS = NHMSF (NSEC)
      ENDIF

#ifdef FIZHI_USE_FIXED_DAY
      NYMD = 20040321
#endif

      RETURN
      END

      subroutine tic_time (mymd,mhms,ndt)
C***********************************************************************
C  PURPOSE
C     Tick the Clock by NDT (seconds)
C
C***********************************************************************
      implicit none
#include "chronos.h"

      integer mymd,mhms,ndt

      integer nsec,nsecf,incymd,nhmsf

      IF(NDT.NE.0) THEN
      NSEC = NSECF(NHMS) + NDT

      IF (NSEC.GT.86400)  THEN
      DO WHILE (NSEC.GT.86400)
      NSEC = NSEC - 86400
      NYMD = INCYMD (NYMD,1)
      ENDDO
      ENDIF

      IF (NSEC.EQ.86400)  THEN
      NSEC = 0
      NYMD = INCYMD (NYMD,1)
      ENDIF

      IF (NSEC.LT.00000)  THEN
      DO WHILE (NSEC.LT.0)
      NSEC = 86400 + NSEC
      NYMD = INCYMD (NYMD,-1)
      ENDDO
      ENDIF

      NHMS = NHMSF (NSEC)
      ENDIF

C Pass Back Current Updated Time
C ------------------------------
      mymd = nymd
      mhms = nhms

      RETURN
      END

      FUNCTION NALARM (MHMS,NYMD,NHMS,NYMD0,NHMS0)
C***********************************************************************
C  PURPOSE
C     COMPUTES MODULO-FRACTION BETWEEN MHHS AND TOTAL TIME
C  USAGE
C  ARGUMENTS   DESCRIPTION
C     MHMS     INTERVAL FREQUENCY (HHMMSS)
C     NYMD     CURRENT   YYMMDD
C     NHMS     CURRENT   HHMMSS
C     NYMD0    BEGINNING YYMMDD
C     NHMS0    BEGINNING HHMMSS
C
C***********************************************************************
      implicit none

      integer nalarm,MHMS,NYMD,NHMS,NYMD0,NHMS0

      integer nsday, ncycle
      PARAMETER ( NSDAY  = 86400 )
      PARAMETER ( NCYCLE = 1461*24*3600 )

      INTEGER YEAR, MONTH, DAY, SEC, YEAR0, MONTH0, DAY0, SEC0

      integer MNDY(12*4)
      DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366,
     &           397,34*0 /

      integer i,nsecf,iday,iday0,nsec,nsec0,ntime

C***********************************************************************
C*                 COMPUTE # OF DAYS IN A 4-YEAR CYCLE                 *
C***********************************************************************

      DO I=15,48
        MNDY(I) = MNDY(I-12) + 365
      ENDDO

C***********************************************************************
C*                   SET CURRENT AND BEGINNING TIMES                   *
C***********************************************************************

      YEAR   = NYMD / 10000
      MONTH  = MOD(NYMD,10000) / 100
      DAY    = MOD(NYMD,100)
      SEC    = NSECF(NHMS)

      YEAR0  = NYMD0 / 10000
      MONTH0 = MOD(NYMD0,10000) / 100
      DAY0   = MOD(NYMD0,100)
      SEC0   = NSECF(NHMS0)

C***********************************************************************
C*      COMPUTE POSITIONS IN CYCLE FOR CURRENT AND BEGINNING TIMES     *
C***********************************************************************

      IDAY   = (DAY -1) + MNDY( MONTH +12*MOD(YEAR ,4) )
      IDAY0  = (DAY0-1) + MNDY( MONTH0+12*MOD(YEAR0,4) )

      NSEC   = IDAY *NSDAY + SEC
      NSEC0  = IDAY0*NSDAY + SEC0

                       NTIME  = NSEC-NSEC0
      IF (NTIME.LT.0 ) NTIME  = NTIME + NCYCLE
                       NALARM = NTIME
      IF ( MHMS.NE.0 ) NALARM = MOD( NALARM,NSECF(MHMS) )

      RETURN
      END

      FUNCTION NALARM2(MHMS,NYMD,NHMS,NYMD0,NHMS0)
C***********************************************************************
C  PURPOSE
C     COMPUTES MODULO-FRACTION BETWEEN MHHS AND TOTAL TIME
C  USAGE
C  ARGUMENTS   DESCRIPTION
C     MHMS     INTERVAL FREQUENCY (MMDDHHMMSS)
C     NYMD     CURRENT   YYMMDD
C     NHMS     CURRENT   HHMMSS
C     NYMD0    BEGINNING YYMMDD
C     NHMS0    BEGINNING HHMMSS
C
C***********************************************************************
      implicit none

      integer nalarm2,MHMS,NYMD,NHMS,NYMD0,NHMS0

      integer nsday, ncycle
      PARAMETER ( NSDAY  = 86400 )
      PARAMETER ( NCYCLE = 1461*24*3600 )

      INTEGER YEAR, MONTH, DAY, SEC, YEAR0, MONTH0, DAY0, SEC0

      integer MNDY(12*4)
      DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366,
     &           397,34*0 /
      INTEGER NDPM(12)
      DATA NDPM /31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/

      integer i,nsecf,iday,iday0,nsec,nsec0,ntime
      integer NHMMSS,NMMDD
      integer iloop
      integer testnymd,testnhms,testndpm

C***********************************************************************
C*                 COMPUTE # OF DAYS IN A 4-YEAR CYCLE                 *
C***********************************************************************

      DO I=15,48
        MNDY(I) = MNDY(I-12) + 365
      ENDDO

C***********************************************************************
C*                   SET CURRENT AND BEGINNING TIMES                   *
C***********************************************************************

      YEAR   = NYMD / 10000
      MONTH  = MOD(NYMD,10000) / 100
      DAY    = MOD(NYMD,100)
      SEC    = NSECF(NHMS)

      YEAR0  = NYMD0 / 10000
      MONTH0 = MOD(NYMD0,10000) / 100
      DAY0   = MOD(NYMD0,100)
      SEC0   = NSECF(NHMS0)

C***********************************************************************
C*      COMPUTE POSITIONS IN CYCLE FOR CURRENT AND BEGINNING TIMES     *
C***********************************************************************

      IDAY   = (DAY -1) + MNDY( MONTH +12*MOD(YEAR ,4) )
      IDAY0  = (DAY0-1) + MNDY( MONTH0+12*MOD(YEAR0,4) )

      NSEC   = IDAY *NSDAY + SEC
      NSEC0  = IDAY0*NSDAY + SEC0

      NTIME  = NSEC-NSEC0
      IF(NTIME.LT.0) NTIME  = NTIME + NCYCLE
      NALARM2 = NTIME
      IF(MHMS.NE.0)NALARM2 = MOD( NALARM2,NSECF(MHMS) )
      IF(MHMS.GE.1000000) THEN
       testnymd=nymd0
       testnhms=nhms0
       NMMDD = MHMS / 1000000
       NHMMSS = MOD(MHMS,1000000)
       do iloop=1,100000
        testnymd=testnymd + nmmdd
        testnhms=testnhms + nhmmss
        year0=testnymd/10000
        month0=mod(testnymd,10000)/100
        day0 = mod(testnymd,100)
        testndpm = ndpm(month0)
        if( month0.eq.2  .and. mod(year0,4).eq.0) testndpm = 29
        if(testnhms.ge.240000) then
         testnhms = testnhms-240000
         testnymd = testnymd + 1
         day0 = day0 + 1
        endif
        if(day0.gt.testndpm) then
         testnymd = testnymd - testndpm
         testnymd = testnymd + 100
         day0 = day0 - testndpm
         month0 = month0 + 1
        endif
        if(month0.gt.12) then
         month0 = month0 - 12
         year0 = year0 + 1
         testnymd = testnymd + 10000 - 1200
        endif
        sec0 = nsecf(testnhms)
        iday0 = (day0-1) + MNDY(month0+12*mod(year0,4) )
        nsec0 = iday0 *nsday + sec0
        if( (testnymd.gt.nymd) .or.
     &         (testnymd.eq.testnymd) .and. (testnhms.gt.nhms) )
     &                    go to 200
        nalarm2 = nsec-nsec0
       enddo
 200   continue
      ENDIF

      RETURN
      END

      FUNCTION INCYMD (NYMD,M)
C***********************************************************************
C  PURPOSE
C     INCYMD:  NYMD CHANGED BY ONE DAY
C     MODYMD:  NYMD CONVERTED TO JULIAN DATE
C  DESCRIPTION OF INPUT VARIABLES
C     NYMD     CURRENT DATE IN YYMMDD FORMAT
C     M        +/- 1 (DAY ADJUSTMENT)
C
C***********************************************************************
      implicit none
      integer incymd,nymd,m

      integer ny,nm,nd,ny00,modymd

      INTEGER NDPM(12)
      DATA NDPM /31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/
      LOGICAL LEAP
      DATA NY00 /1900 /
      LEAP(NY) = MOD(NY,4).EQ.0 .AND. (NY.NE.0 .OR. MOD(NY00,400).EQ.0)

C***********************************************************************
C
      NY = NYMD / 10000
      NM = MOD(NYMD,10000) / 100
      ND = MOD(NYMD,100) + M

      IF (ND.EQ.0) THEN
      NM = NM - 1
      IF (NM.EQ.0) THEN
          NM = 12
          NY = NY - 1
      ENDIF
      ND = NDPM(NM)
      IF (NM.EQ.2 .AND. LEAP(NY))  ND = 29
      ENDIF

      IF (ND.EQ.29 .AND. NM.EQ.2 .AND. LEAP(NY))  GO TO 20

      IF (ND.GT.NDPM(NM)) THEN
      ND = 1
      NM = NM + 1
      IF (NM.GT.12) THEN
          NM = 1
          NY = NY + 1
      ENDIF
      ENDIF

   20 CONTINUE
      INCYMD = NY*10000 + NM*100 + ND

      RETURN

C***********************************************************************
C                      E N T R Y    M O D Y M D
C***********************************************************************

      ENTRY MODYMD (NYMD)

      NY = NYMD / 10000
      NM = MOD(NYMD,10000) / 100
      ND = MOD(NYMD,100)

   40 CONTINUE
      IF (NM.LE.1)  GO TO 60
      NM = NM - 1
      ND = ND + NDPM(NM)
      IF (NM.EQ.2 .AND. LEAP(NY))  ND = ND + 1
      GO TO 40

   60 CONTINUE
      MODYMD = ND

      RETURN
      END

      SUBROUTINE ASTRO ( NYMD,NHMS,ALAT,ALON,IRUN,COSZ,RA )
C***********************************************************************
C
C  INPUT:
C  ======
C    NYMD      : CURRENT YYMMDD
C    NHMS      : CURRENT HHMMSS
C    ALAT(IRUN):LATITUDES  IN DEGREES.
C    ALON(IRUN):LONGITUDES IN DEGREES. (0 = GREENWICH, + = EAST).
C    IRUN      : # OF POINTS TO CALCULATE
C
C  OUTPUT:
C  =======
C    COSZ(IRUN)  : COSINE OF ZENITH ANGLE.
C    RA          : EARTH-SUN DISTANCE IN UNITS OF
C                  THE ORBITS SEMI-MAJOR AXIS.
C
C  NOTE:
C  =====
C  THE INSOLATION AT THE TOP OF THE ATMOSPHERE IS:
C
C  S(I) = (SOLAR CONSTANT)*(1/RA**2)*COSZ(I),
C
C  WHERE:
C  RA AND COSZ(I) ARE THE TWO OUTPUTS OF THIS SUBROUTINE.
C
C***********************************************************************

      implicit none

C Input Variables
C ---------------
      integer nymd, nhms, irun
      _RL getcon, cosz(irun), alat(irun), alon(irun), ra

C Local Variables
C ---------------
      integer year, day, sec, month, iday, idayp1
      integer dayscy
      integer i,nsecf,k,km,kp

      _RL hc
      _RL pi, zero, one, two, six, dg2rd, yrlen, eqnx, ob, ecc, per
      _RL daylen, fac, thm, thp, thnow, zs, zc, sj, cj

      parameter ( zero  = 0.0 )
      parameter ( one   = 1.0 )
      parameter ( two   = 2.0 )
      parameter ( six   = 6.0 )
      parameter ( dayscy   = 365*4 + 1 )

      _RL      TH(DAYSCY),T0,T1,T2,T3,T4,FUN,Y
      INTEGER  MNDY(12*4)

      LOGICAL FIRST
      DATA    FIRST/.TRUE./
      SAVE

      DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366,
     &           397,34*0 /

      FUN(Y,PI,ECC,YRLEN,PER) = (TWO*PI/((ONE-ECC**2)**1.5))*(ONE/YRLEN)
     &       * (ONE - ECC*COS(Y-PER)) ** 2

C***********************************************************************
C*                         SET SOME CONSTANTS                          *
C***********************************************************************
      pi = getcon('PI')
      dg2rd = getcon('DEG2RAD')
      yrlen = getcon('YRLEN')
      ob =  getcon('OBLDEG') * dg2rd
      daylen = getcon('SDAY')
      eqnx = getcon('VERNAL EQUINOX')
      ecc = getcon('ECCENTRICITY')
      per = getcon('PERIHELION') * dg2rd

C***********************************************************************
C*                          SET CURRENT TIME                           *
C***********************************************************************

      YEAR  = NYMD / 10000
      MONTH = MOD(NYMD,10000) / 100
      DAY   = MOD(NYMD,100)
      SEC   = NSECF(NHMS)

C***********************************************************************
C*                 COMPUTE DAY-ANGLES FOR 4-YEAR CYCLE                 *
C***********************************************************************

      IF(FIRST) THEN
           DO 100 I=15,48
             MNDY(I) = MNDY(I-12) + 365
100        CONTINUE

           KM  = INT(EQNX) + 1
           FAC = KM-EQNX
           T0 = ZERO
           T1 = FUN(T0,PI,ECC,YRLEN,PER         )*FAC
           T2 = FUN(ZERO+T1/TWO,PI,ECC,YRLEN,PER)*FAC
           T3 = FUN(ZERO+T2/TWO,PI,ECC,YRLEN,PER)*FAC
           T4 = FUN(ZERO+T3,PI,ECC,YRLEN,PER    )*FAC
           TH(KM) = (T1 + TWO*(T2 + T3) + T4) / SIX

           DO 200 K=2,DAYSCY
           T1 = FUN(TH(KM),PI,ECC,YRLEN,PER       )
           T2 = FUN(TH(KM)+T1/TWO,PI,ECC,YRLEN,PER)
           T3 = FUN(TH(KM)+T2/TWO,PI,ECC,YRLEN,PER)
           T4 = FUN(TH(KM)+T3,PI,ECC,YRLEN,PER    )
           KP = MOD(KM,DAYSCY) + 1
           TH(KP) = TH(KM) + (T1 + TWO*(T2 + T3) + T4) / SIX
           KM = KP
 200       CONTINUE

           FIRST=.FALSE.
      ENDIF

C***********************************************************************
C*            COMPUTE EARTH-SUN DISTANCE TO CURRENT SECOND             *
C***********************************************************************

      IDAY   = DAY + MNDY(MONTH+12*MOD(YEAR,4) )
      IDAYP1 = MOD( IDAY,DAYSCY) + 1
      THM    = MOD( TH(IDAY)  ,TWO*PI)
      THP    = MOD( TH(IDAYP1),TWO*PI)

      IF(THP.LT.THM) THP = THP + TWO*PI
      FAC   = FLOAT(SEC)/DAYLEN
      THNOW = THM*(ONE-FAC) + THP*FAC

      ZS = SIN(THNOW) * SIN(OB)
      ZC = SQRT(ONE-ZS*ZS)
      RA = (1.-ECC*ECC) / ( ONE-ECC*COS(THNOW-PER) )

C***********************************************************************
C*                 COMPUTE COSINE OF THE ZENITH ANGLE                  *
C***********************************************************************

      FAC  = FAC*TWO*PI + PI
      DO I = 1,IRUN

      HC = COS( FAC+ALON(I)*DG2RD )
      SJ = SIN(ALAT(I)*DG2RD)
      CJ = SQRT(ONE-SJ*SJ)

          COSZ(I) = SJ*ZS + CJ*ZC*HC
      IF( COSZ(I).LT.ZERO ) COSZ(I) = ZERO
      ENDDO

      RETURN
      END

      subroutine time_bound(nymd,nhms,nymd1,nhms1,nymd2,nhms2,imnm,imnp)
C***********************************************************************
C  PURPOSE
C     Compute Date and Time boundaries.
C
C  ARGUMENTS   DESCRIPTION
C     nymd .... Current    Date
C     nhms .... Current    Time
C     nymd1 ... Previous   Date Boundary
C     nhms1 ... Previous   Time Boundary
C     nymd2 ... Subsequent Date Boundary
C     nhms2 ... Subsequent Time Boundary
C
C     imnm .... Previous   Time Index for Interpolation
C     imnp .... Subsequent Time Index for Interpolation
C
C***********************************************************************

      implicit none
      integer  nymd,nhms, nymd1,nhms1, nymd2,nhms2

C Local Variables
C ---------------
      integer  month,day,nyear,midmon1,midmon,midmon2
      integer  imnm,imnp
      INTEGER  DAYS(14), daysm, days0, daysp
      DATA     DAYS /31,31,28,31,30,31,30,31,31,30,31,30,31,31/

      integer nmonf,ndayf,n
      NMONF(N) = MOD(N,10000)/100
      NDAYF(N) = MOD(N,100)

C*********************************************************************
C**** Find Proper Month and Time Boundaries for Climatological Data **
C*********************************************************************

      MONTH  = NMONF(NYMD)
      DAY    = NDAYF(NYMD)

      daysm  = days(month  )
      days0  = days(month+1)
      daysp  = days(month+2)

C Check for Leap Year
C -------------------
      nyear = nymd/10000
      if( 4*(nyear/4).eq.nyear ) then
      if( month.eq.3 ) daysm = daysm+1
      if( month.eq.2 ) days0 = days0+1
      if( month.eq.1 ) daysp = daysp+1
      endif

      MIDMON1 = daysm/2 + 1
      MIDMON  = days0/2 + 1
      MIDMON2 = daysp/2 + 1


      IF(DAY.LT.MIDMON) THEN
         imnm = month
         imnp = month + 1
         nymd2 = (nymd/10000)*10000 + month*100 + midmon
         nhms2 = 000000
         nymd1 = nymd2
         nhms1 = nhms2
         call tick ( nymd1,nhms1,       -midmon  *86400 )
         call tick ( nymd1,nhms1,-(daysm-midmon1)*86400 )
      ELSE
         IMNM = MONTH + 1
         IMNP = MONTH + 2
         nymd1 = (nymd/10000)*10000 + month*100 + midmon
         nhms1 = 000000
         nymd2 = nymd1
         nhms2 = nhms1
         call tick ( nymd2,nhms2,(days0-midmon)*86400 )
         call tick ( nymd2,nhms2,       midmon2*86400 )
      ENDIF

C -------------------------------------------------------------
C Note:  At this point, imnm & imnp range between 01-14, where
C        01    -> Previous years December
C        02-13 -> Current  years January-December
C        14    -> Next     years January
C -------------------------------------------------------------

      imnm = imnm-1
      imnp = imnp-1

      if( imnm.eq.0  ) imnm = 12
      if( imnp.eq.0  ) imnp = 12
      if( imnm.eq.13 ) imnm = 1
      if( imnp.eq.13 ) imnp = 1

      return
      end
      subroutine time2freq2(MMDD,NYMD,NHMS,timeleft)
C***********************************************************************
C  PURPOSE
C     COMPUTES TIME IN SECONDS UNTIL WE REACH THE NEXT MMDD
C       (ASSUME that the target time is 0Z)
C
C  ARGUMENTS   DESCRIPTION
C     MMDD     FREQUENCY (MMDDHHMMSS)
C     NYMD     CURRENT   YYMMDD
C     NHMS     CURRENT   HHMMSS
C     TIMELEFT TIME LEFT (SECONDS)
C
C  NOTES - Only used when the frequency is in units of months
C          Assumes that we always want to be at a month boundary
C***********************************************************************
      implicit none

      integer mmdd,nymd,nhms,timeleft,daysleft

      integer nsday
      PARAMETER ( NSDAY  = 86400 )
      integer year, month, day, sec
      integer yearnext, monthnext, daynext
      integer i,nsecf,iday,idaynext,nsec
      integer testnymd
      integer MNDY(12*4)
      DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366,
     &           397,34*0 /

C***********************************************************************
C*                 COMPUTE # OF DAYS IN A 4-YEAR CYCLE                 *
C***********************************************************************
      DO I=15,48
        MNDY(I) = MNDY(I-12) + 365
      ENDDO
C***********************************************************************
C*                   SET CURRENT TIME ELEMENTS                                 *
C***********************************************************************
      YEAR   = NYMD / 10000
      MONTH  = MOD(NYMD,10000) / 100
      DAY    = MOD(NYMD,100)
      SEC    = NSECF(NHMS)
C***********************************************************************
C*      COMPUTE POSITIONS IN CYCLE FOR CURRENT AND BEGINNING TIMES     *
C***********************************************************************
      IDAY   = (DAY -1) + MNDY( MONTH +12*MOD(YEAR ,4) )
      NSEC   = IDAY *NSDAY + SEC

      testnymd=nymd + mmdd
      yearnext=testnymd/10000
      monthnext=mod(testnymd,10000)/100
      daynext = 1
      if(monthnext.gt.12) then
       monthnext = monthnext - 12
       yearnext = yearnext + 1
      endif
      testnymd = yearnext*10000 + monthnext*100 + daynext
      idaynext = MNDY(monthnext+12*mod(yearnext,4) )
      daysleft = idaynext - iday
      if(daysleft.lt.0) daysleft = daysleft + 1461

      timeleft = daysleft * nsday - sec

      RETURN
      END
