C $Header: /u/gcmpack/MITgcm/pkg/cal/cal_stepsforday.F,v 1.3 2010/03/16 00:11:46 jmc Exp $
C $Name:  $

#include "CAL_OPTIONS.h"

      subroutine CAL_STEPSFORDAY(
     I                            iday,
     O                            firststep,
     O                            laststep,
     O                            nsteps,
     I                            mythid
     &                          )

c     ==================================================================
c     SUBROUTINE cal_StepsForDay
c     ==================================================================
c
c     o Given the current day of the integration this routine returns
c       first, the last and the number of model steps the will have to
c       be performed.
c
c       This routine also checks consistency of variables quite
c       extensively.
c
c     started: Christian Eckert eckert@mit.edu  06-Apr-2000
c
c     changed:
c
c     ==================================================================
c     SUBROUTINE cal_StepsForDay
c     ==================================================================

      implicit none

c     == global variables ==

#include "cal.h"

c     == routine arguments ==

      integer iday
      integer firststep
      integer laststep
      integer nsteps
      integer mythid

c     == local variables ==

      integer ierr
      integer mdstep
      integer numdays
      integer numsteps
      integer frac1
      integer frac2
      integer frac3
      integer frac4
      integer fullsteps
      integer firstyear
      integer firstmonth
      integer firstday
      integer lyfirst
      integer startsecs
      integer lastday
      integer endsecs

c     == external ==

      external 
      integer  cal_IntDays
      external 
      integer  cal_IsLeap

c     == end of interface ==

      numdays    = cal_IntDays( mythid )
      lyfirst    = cal_IsLeap( firstyear, mythid )

      mdstep     = int(modelstep)

      firstyear  = modelstartdate(1)/10000
      firstmonth = mod(modelstartdate(1)/100,100)
      firstday   = mod(modelstartdate(1),100)
      lastday    = mod(modelenddate(1),100)

      startsecs  = (modelstartdate(2)/10000)*secondsperhour +
     &             mod(modelstartdate(2)/100,100)*secondsperminute +
     &             mod(modelstartdate(2),100)
      endsecs    = (modelenddate(2)/10000)*secondsperhour +
     &             mod(modelenddate(2)/100,100)*secondsperminute +
     &             mod(modelenddate(2),100)

      if ( numdays .eq. 1 ) then
        if ( iday .eq. firstday ) then
c--       Get the number of steps in the first day.
          if ( firstday .eq. lastday ) then
            firststep = 1
            laststep  = modelintsteps
          else if ( mod(firstday+1,ndaymonth(firstmonth,lyfirst)) .eq.
     &              lastday ) then
c--         This can only happen if we end at midnight of the next day.
            if ( modelenddate(2) .eq. 0 ) then
              firststep = 1
              laststep  = modelintsteps
c--           Note: This holds only if modelenddate was determined
c--                 such that it coincides with the model final time.
            else
c--           We do not end at midnight of the first day of
c--           the next month.
              ierr = 2604
              call CAL_PRINTERROR( ierr, mythid )
              stop ' stopped in cal_StepsForDay.'
            endif
          else
c--         The first and the last day are inconsistent with iday.
            ierr = 2603
            call CAL_PRINTERROR( ierr, mythid )
            stop ' stopped in cal_StepsForDay.'
          endif
        else
c--       The variables numdays and iday are inconsistent;
c--       ( iday .gt. numdays ).
          ierr = 2602
          call CAL_PRINTERROR( ierr, mythid )
          stop ' stopped in cal_StepsForDay.'
        endif

      else if ( numdays .gt. 1 ) then
c--     More than one day of integration.
        if ( iday .eq. 1 ) then
          firststep = 1
          laststep  = int((secondsperday - startsecs)/mdstep)
        else if ( ( iday .gt. 1      ) .and.
     &            ( iday .lt. numdays) ) then
c--       Somewhere between first and last month.
c--       The first steps in iday.
          fullsteps = int((secondsperday - startsecs)/mdstep)
          numsteps  = fullsteps
c--       What is left in the first day (frac1).
          frac1     = (secondsperday - startsecs) - fullsteps*mdstep
          fullsteps = int(secondsperday/modelstep)
c--       What is left in a complete day (frac2).
          frac2     = secondsperday - fullsteps*mdstep
c--       What is left up to the current day (frac3).
          frac3     = frac1 + frac2*(iday - 1)
          numsteps  = numsteps + (iday - 1)*fullsteps +
     &                frac3/mdstep
          laststep  = numsteps
          firststep = laststep - secondsperday/mdstep + 1

        else if ( iday .eq. numdays ) then
c--       The last day of integration.
c--       The first step in iday.
          fullsteps = int((secondsperday - startsecs)/mdstep)
          numsteps  = fullsteps
c--       What is left in the first day (frac1).
          frac1     = (secondsperday - startsecs) - fullsteps*mdstep
          fullsteps = int(secondsperday/modelstep)
c--       What is left in a complete day (frac2).
          frac2     = secondsperday - fullsteps*mdstep
c--       What is left up to the day before the last (frac3).
          frac3     = frac1 + frac2*(iday - 2)
          numsteps  = numsteps + (iday - 2)*fullsteps
c--       The last step in iday.
          if ( modelenddate(2) .eq. 0 ) then
c--         This can only happen if we end at midnight of the next day.
            laststep  = numsteps + fullsteps
            firststep = numsteps + 1
c--         Note: There should be no fraction left
c--               ( mod(frac3,mdstep) = frac3/mdstep ) if modelenddate
c--               is based on an integral number of timesteps.
          else
            frac4     = frac3 + endsecs
            numsteps  = numsteps + frac4/mdstep
            laststep  = numsteps

c--         Note: There should be no fraction left
c--               ( mod(frac4,mdstep = frac4/mdstep ) if modelenddate
c--               is based on an integral number of timesteps.

            firststep = laststep - endsecs/mdstep + 1
          endif
        else
c--       The variables iday and numdays are inconsistent.
          ierr = 2605
          call CAL_PRINTERROR( ierr, mythid )
          stop ' stopped in cal_DaysForMonth.'
        endif
      else
c--     The number of days to integrate is wrong; check cal_IntDays.
        ierr = 2601
        call CAL_PRINTERROR( ierr, mythid )
        stop ' stopped in cal_StepsForDay.'
      endif

c--   The number of days to integrate in the given month.
      nsteps = laststep - firststep + 1

      return
      end