! $Id$ ! ! Earth System Modeling Framework ! Copyright 2002-2003, University Corporation for Atmospheric Research, ! Massachusetts Institute of Technology, Geophysical Fluid Dynamics ! Laboratory, University of Michigan, National Centers for Environmental ! Prediction, Los Alamos National Laboratory, Argonne National Laboratory, ! NASA Goddard Space Flight Center. ! Licensed under the GPL. ! !============================================================================== ! ! ESMF TimeInterval Module module ESMF_TimeIntervalMod ! !============================================================================== ! ! This file contains the TimeInterval class definition and all TimeInterval ! class methods. ! !------------------------------------------------------------------------------ ! INCLUDES #include ! !=============================================================================== !BOPI ! !MODULE: ESMF_TimeIntervalMod ! ! !DESCRIPTION: ! Part of Time Manager F90 API wrapper of C++ implemenation ! ! Defines F90 wrapper entry points for corresponding ! C++ implementaion of class {\tt ESMC\_TimeInterval} ! ! See {\tt ../include/ESMC\_TimeInterval.h} for complete description ! !------------------------------------------------------------------------------ ! !USES: ! inherit from ESMF base class use ESMF_BaseMod ! inherit from base time class use ESMF_BaseTimeMod ! associated derived types use ESMF_FractionMod, only : ESMF_Fraction use ESMF_CalendarMod use ESMF_ShrTimeMod, only : ESMF_Time implicit none ! !------------------------------------------------------------------------------ ! !PRIVATE TYPES: private !------------------------------------------------------------------------------ ! ! ESMF_TimeInterval ! ! ! F90 class type to match C++ TimeInterval class in size only; ! ! all dereferencing within class is performed by C++ implementation type ESMF_TimeInterval ! time interval is expressed as basetime type(ESMF_BaseTime) :: basetime ! inherit base class ! Relative year and month fields support monthly or yearly time ! intervals. Many operations are undefined when these fields are ! non-zero! INTEGER :: YR ! relative year INTEGER :: MM ! relative month logical :: starttime_set ! reference time set type(ESMF_Time) :: starttime ! reference time end type !------------------------------------------------------------------------------ ! !PUBLIC TYPES: public ESMF_TimeInterval !------------------------------------------------------------------------------ ! ! for running WRF, add three subroutines or functions (WRFADDITION_TimeIntervalGet, ! ESMF_TimeIntervalDIVQuot, ESMF_TimeIntervalIsPositive), by jhe ! !PUBLIC MEMBER FUNCTIONS: public ESMF_TimeIntervalGet public ESMF_TimeIntervalSet public ESMF_TimeIntervalAbsValue public ESMF_TimeIntervalNegAbsValue public ESMF_TimeIntervalPrint public normalize_timeint ! Required inherited and overridden ESMF_Base class methods !!!!!!!!! added by jhe public ESMF_TimeIntervalDIVQuot public ESMF_TimeIntervalIsPositive ! ! !PRIVATE MEMBER FUNCTIONS: ! overloaded operator functions public operator(/) private ESMF_TimeIntervalQuotI public operator(*) private ESMF_TimeIntervalProdI ! Inherited and overloaded from ESMF_BaseTime public operator(+) private ESMF_TimeIntervalSum public operator(-) private ESMF_TimeIntervalDiff public operator(.EQ.) private ESMF_TimeIntervalEQ public operator(.NE.) private ESMF_TimeIntervalNE public operator(.LT.) private ESMF_TimeIntervalLT public operator(.GT.) private ESMF_TimeIntervalGT public operator(.LE.) private ESMF_TimeIntervalLE public operator(.GE.) private ESMF_TimeIntervalGE !EOPI !------------------------------------------------------------------------------ ! The following line turns the CVS identifier string into a printable variable. character(*), parameter, private :: version = & '$Id$' !============================================================================== ! ! INTERFACE BLOCKS ! !============================================================================== !BOP ! !INTERFACE: interface operator(*) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalProdI ! !DESCRIPTION: ! This interface overloads the * operator for the {\tt ESMF\_TimeInterval} ! class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(/) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalQuotI ! !DESCRIPTION: ! This interface overloads the / operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(+) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalSum ! !DESCRIPTION: ! This interface overloads the + operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(-) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalDiff ! !DESCRIPTION: ! This interface overloads the - operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(.EQ.) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalEQ ! !DESCRIPTION: ! This interface overloads the .EQ. operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(.NE.) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalNE ! !DESCRIPTION: ! This interface overloads the .NE. operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(.LT.) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalLT ! !DESCRIPTION: ! This interface overloads the .LT. operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(.GT.) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalGT ! !DESCRIPTION: ! This interface overloads the .GT. operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(.LE.) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalLE ! !DESCRIPTION: ! This interface overloads the .LE. operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !BOP ! !INTERFACE: interface operator(.GE.) ! !PRIVATE MEMBER FUNCTIONS: module procedure ESMF_TimeIntervalGE ! !DESCRIPTION: ! This interface overloads the .GE. operator for the ! {\tt ESMF\_TimeInterval} class ! !EOP end interface ! !------------------------------------------------------------------------------ !============================================================================== contains !============================================================================== ! ! Generic Get/Set routines which use F90 optional arguments ! !--------------------------------------------------------------------- !BOP ! !IROUTINE: ESMF_TimeIntervalGet - Get value in user-specified units ! !INTERFACE: subroutine ESMF_TimeIntervalGet(timeinterval, StartTimeIn, yy, mm, D, d_r8, S, S_i8, Sn, Sd, TimeString, rc ) ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval type(ESMF_Time), optional, intent(in) :: StartTimeIn integer, intent(out), optional :: yy integer, intent(out), optional :: mm integer, intent(out), optional :: D real(ESMF_KIND_R8), intent(out), optional :: d_r8 integer(ESMF_KIND_I8),intent(out), optional :: S_i8 integer, intent(out), optional :: S integer, intent(out), optional :: Sn integer, intent(out), optional :: Sd character*(*), optional, intent(out) :: TimeString integer, intent(out), optional :: rc ! !DESCRIPTION: ! Get the value of the {\tt ESMF\_TimeInterval} in units specified by the ! user via F90 optional arguments. ! ! Time manager represents and manipulates time internally with integers ! to maintain precision. Hence, user-specified floating point values are ! converted internally from integers. ! ! See {\tt ../include/ESMC\_BaseTime.h} and ! {\tt ../include/ESMC\_TimeInterval.h} for complete description. ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The object instance to query ! \item[{[YY]}] ! Integer years (>= 32-bit) ! \item[{[YYl]}] ! Integer years (large, >= 64-bit) ! \item[{[MO]}] ! Integer months (>= 32-bit) ! \item[{[MOl]}] ! Integer months (large, >= 64-bit) ! \item[{[D]}] ! Integer days (>= 32-bit) ! \item[{[Dl]}] ! Integer days (large, >= 64-bit) ! \item[{[H]}] ! Integer hours ! \item[{[M]}] ! Integer minutes ! \item[{[S]}] ! Integer seconds (>= 32-bit) ! \item[{[Sl]}] ! Integer seconds (large, >= 64-bit) ! \item[{[MS]}] ! Integer milliseconds ! \item[{[US]}] ! Integer microseconds ! \item[{[NS]}] ! Integer nanoseconds ! \item[{[d\_]}] ! Double precision days ! \item[{[h\_]}] ! Double precision hours ! \item[{[m\_]}] ! Double precision minutes ! \item[{[s\_]}] ! Double precision seconds ! \item[{[ms\_]}] ! Double precision milliseconds ! \item[{[us\_]}] ! Double precision microseconds ! \item[{[ns\_]}] ! Double precision nanoseconds ! \item[{[Sn]}] ! Integer fractional seconds - numerator ! \item[{[Sd]}] ! Integer fractional seconds - denominator ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! ! !REQUIREMENTS: ! TMG1.1 !EOP type(ESMF_Time) :: lstarttime logical :: lstarttime_set logical :: doyear INTEGER(ESMF_KIND_I8) :: seconds, secondsym, years INTEGER :: ierr INTEGER :: mpyi4, iyr,imo,mmon,nmon,mstart,ndays ierr = ESMF_FAILURE if (present(StartTimeIn)) then lstarttime_set = .true. lstarttime = StartTimeIn else lstarttime_set = timeinterval%StartTime_set lstarttime = timeinterval%StartTime endif CALL timeintchecknormalized( timeinterval, & 'ESMF_TimeIntervalGet arg1', & relative_interval=.true. ) seconds = timeinterval%basetime%S years = timeinterval%YR secondsym = 0 IF ( PRESENT( YY ) )THEN YY = years + timeinterval%MM / MONTHS_PER_YEAR ! seconds = seconds - years * ( 365_ESMF_KIND_I8 * SECONDS_PER_DAY ) IF ( PRESENT( MM ) )THEN mpyi4 = MONTHS_PER_YEAR MM = MOD( timeinterval%MM, mpyi4) else call wrf_error_fatal("ESMF_TimeIntervalGet: requires MM with YY") END IF ELSE IF ( PRESENT( MM ) )THEN MM = timeinterval%MM + years*12 else if (lstarttime_set) then ! convert years and months to days carefully mpyi4 = MONTHS_PER_YEAR mmon = timeinterval%mm + timeinterval%yr*mpyi4 mstart = nmonthinyearsec(lstarttime%yr,lstarttime%basetime,lstarttime%calendar%type) ! write(6,*) 'tcxti1 ',mmon,lstarttime%yr,mstart,lstarttime%basetime%s iyr = lstarttime%yr if (mmon > 0) then imo = mstart-1 ! if adding months, start with this month after adding first +1 else imo = mstart ! if going backwards, start with last month after first -1 endif nmon = 1 ! do nmon = 1,abs(mmon) do while (nmon <= abs(mmon)) if (mmon > 0) then if (imo == 12 .and. (abs(mmon) - nmon) > 12) then iyr = iyr + 1 nmon = nmon + 12 doyear = .true. else imo = imo + 1 nmon = nmon + 1 doyear = .false. endif else if (imo == 1 .and. (abs(mmon) - nmon) > 12) then iyr = iyr - 1 nmon = nmon + 12 doyear = .true. else imo = imo - 1 nmon = nmon + 1 doyear = .false. endif endif do while (imo > 12) imo = imo - 12 iyr = iyr + 1 enddo do while (imo < 1) imo = imo + 12 iyr = iyr - 1 enddo if (doyear) then ndays = ndaysinyear(iyr,lstarttime%calendar%type) else ndays = ndaysinmonth(iyr,imo,lstarttime%calendar%type) endif secondsym = secondsym + (ndays * SECONDS_PER_DAY) ! write(6,*) 'tcxti2 ',nmon,iyr,imo,ndays enddo if (mmon < 0) then secondsym = -secondsym endif ! write(6,*) 'tcxti3 ',mmon,iyr,imo,secondsym elseif (PRESENT(D) .or. PRESENT(d_r8) .or. present(S) .or. present(S_i8)) then IF (timeinterval%MM /= 0) then CALL wrf_error_fatal("ESMF_TimeIntervalGet: Need MM with D,d_r8,S,or S_i8") endif if (timeinterval%YR /= 0) then CALL wrf_error_fatal("ESMF_TimeIntervalGet: Need YY or MM with D,d_r8,S,or S_i8") endif END IF seconds = seconds+secondsym IF ( PRESENT( D ) )THEN D = seconds / SECONDS_PER_DAY IF ( PRESENT(S) ) S = mod( seconds, SECONDS_PER_DAY ) IF ( PRESENT(S_i8)) S_i8 = mod( seconds, SECONDS_PER_DAY ) ELSE IF ( PRESENT(S) ) S = seconds IF ( PRESENT(S_i8)) S_i8 = seconds END IF IF ( PRESENT( d_r8 ) )THEN D_r8 = REAL( seconds, ESMF_KIND_R8 ) / & REAL( SECONDS_PER_DAY, ESMF_KIND_R8 ) END IF ! If d_r8 present and sec present IF ( PRESENT( d_r8 ) )THEN IF ( PRESENT( S ) .or. present(s_i8) )THEN CALL wrf_error_fatal( & "ESMF_TimeIntervalGet: Can not specify d_r8 and S S_i8 values" ) END IF END IF ierr = ESMF_SUCCESS IF ( PRESENT( timeString ) ) THEN CALL ESMFold_TimeIntervalGetString( timeinterval, timeString, rc=ierr ) ENDIF IF ( PRESENT(Sn) ) THEN Sn = timeinterval%basetime%Sn ENDIF IF ( PRESENT(Sd) ) THEN Sd = timeinterval%basetime%Sd ENDIF IF ( PRESENT(rc) ) rc = ierr end subroutine ESMF_TimeIntervalGet !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalSet - Initialize via user-specified unit set ! !INTERFACE: ! subroutine ESMF_TimeIntervalSet(timeinterval, YY, YYl, MM, MOl, D, Dl, & ! H, M, S, Sl, MS, US, NS, & ! d_, d_r8, h_, m_, s_, ms_, us_, ns_, & ! Sn, Sd, startTime, rc) subroutine ESMF_TimeIntervalSet(timeinterval, YY, MM, D, & H, M, S, S_i8, MS, & d_, d_r8, & Sn, Sd, startTime, rc) ! !ARGUMENTS: type(ESMF_TimeInterval), intent(out) :: timeinterval type(ESMF_Time), intent(in), optional :: StartTime integer, intent(in), optional :: YY ! integer(ESMF_KIND_I8), intent(in), optional :: YYl integer, intent(in), optional :: MM ! integer(ESMF_KIND_I8), intent(in), optional :: MOl integer, intent(in), optional :: D ! integer(ESMF_KIND_I8), intent(in), optional :: Dl integer, intent(in), optional :: H integer, intent(in), optional :: M integer, intent(in), optional :: S integer(ESMF_KIND_I8), intent(in), optional :: S_i8 integer, intent(in), optional :: MS ! integer, intent(in), optional :: US ! integer, intent(in), optional :: NS double precision, intent(in), optional :: d_ double precision, intent(in), optional :: d_r8 ! double precision, intent(in), optional :: h_ ! double precision, intent(in), optional :: m_ ! double precision, intent(in), optional :: s_ ! double precision, intent(in), optional :: ms_ ! double precision, intent(in), optional :: us_ ! double precision, intent(in), optional :: ns_ integer, intent(in), optional :: Sn integer, intent(in), optional :: Sd integer, intent(out), optional :: rc ! locals double precision :: din logical :: dinset ! !DESCRIPTION: ! Set the value of the {\tt ESMF\_TimeInterval} in units specified by ! the user via F90 optional arguments ! ! Time manager represents and manipulates time internally with integers ! to maintain precision. Hence, user-specified floating point values are ! converted internally to integers. ! ! See {\tt ../include/ESMC\_BaseTime.h} and ! {\tt ../include/ESMC\_TimeInterval.h} for complete description. ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The object instance to initialize ! \item[{[YY]}] ! Integer number of interval years (>= 32-bit) ! \item[{[YYl]}] ! Integer number of interval years (large, >= 64-bit) ! \item[{[MM]}] ! Integer number of interval months (>= 32-bit) ! \item[{[MOl]}] ! Integer number of interval months (large, >= 64-bit) ! \item[{[D]}] ! Integer number of interval days (>= 32-bit) ! \item[{[Dl]}] ! Integer number of interval days (large, >= 64-bit) ! \item[{[H]}] ! Integer hours ! \item[{[M]}] ! Integer minutes ! \item[{[S]}] ! Integer seconds (>= 32-bit) ! \item[{[Sl]}] ! Integer seconds (large, >= 64-bit) ! \item[{[MS]}] ! Integer milliseconds ! \item[{[US]}] ! Integer microseconds ! \item[{[NS]}] ! Integer nanoseconds ! \item[{[d\_]}] ! Double precision days ! \item[{[h\_]}] ! Double precision hours ! \item[{[m\_]}] ! Double precision minutes ! \item[{[s\_]}] ! Double precision seconds ! \item[{[ms\_]}] ! Double precision milliseconds ! \item[{[us\_]}] ! Double precision microseconds ! \item[{[ns\_]}] ! Double precision nanoseconds ! \item[{[Sn]}] ! Integer fractional seconds - numerator ! \item[{[Sd]}] ! Integer fractional seconds - denominator ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! ! !REQUIREMENTS: ! TMGn.n.n !EOP IF ( PRESENT(rc) ) rc = ESMF_FAILURE timeinterval%startTime_set = .false. if (present(startTime)) then timeinterval%startTime = startTime timeinterval%startTime_set = .true. endif ! note that YR and MM are relative timeinterval%YR = 0 IF ( PRESENT( YY ) ) THEN timeinterval%YR = YY ENDIF timeinterval%MM = 0 IF ( PRESENT( MM ) ) THEN timeinterval%MM = MM ENDIF if (present(d_) .and. present(d_r8)) then CALL wrf_error_fatal( & "ESMF_TimeIntervalSet: Cannot specify both d_r8 and d_") endif dinset = .false. if (present(d_)) then din = d_ dinset = .true. endif if (present(d_r8)) then din = d_r8 dinset = .true. endif IF ( dinset .AND. PRESENT( D ) ) THEN CALL wrf_error_fatal( & "ESMF_TimeIntervalSet: Cannot specify both D and d_ or d_r8") ENDIF timeinterval%basetime%S = 0 IF ( .NOT. dinset ) THEN IF ( PRESENT( D ) ) THEN timeinterval%basetime%S = timeinterval%basetime%S + & ( SECONDS_PER_DAY * INT( D, ESMF_KIND_I8 ) ) ENDIF !$$$ push H,M,S,Sn,Sd,MS down into BaseTime constructor IF ( PRESENT( H ) ) THEN timeinterval%basetime%S = timeinterval%basetime%S + & ( SECONDS_PER_HOUR * INT( H, ESMF_KIND_I8 ) ) ENDIF IF ( PRESENT( M ) ) THEN timeinterval%basetime%S = timeinterval%basetime%S + & ( SECONDS_PER_MINUTE * INT( M, ESMF_KIND_I8 ) ) ENDIF IF ( PRESENT( S ) ) THEN timeinterval%basetime%S = timeinterval%basetime%S + & INT( S, ESMF_KIND_I8 ) ENDIF IF ( PRESENT( S_i8 ) ) THEN timeinterval%basetime%S = timeinterval%basetime%S + & ( S_i8) ENDIF ELSE timeinterval%basetime%S = timeinterval%basetime%S + & INT( din * SECONDS_PER_DAY, ESMF_KIND_I8 ) ENDIF IF ( PRESENT( Sn ) .AND. ( .NOT. PRESENT( Sd ) ) ) THEN CALL wrf_error_fatal( & "ESMF_TimeIntervalSet: Must specify Sd if Sn is specified") ENDIF IF ( PRESENT( Sd ) .AND. PRESENT( MS ) ) THEN CALL wrf_error_fatal( & "ESMF_TimeIntervalSet: Must not specify both Sd and MS") ENDIF timeinterval%basetime%Sn = 0 timeinterval%basetime%Sd = 0 IF ( PRESENT( MS ) ) THEN timeinterval%basetime%Sn = MS timeinterval%basetime%Sd = 1000_ESMF_KIND_I8 ELSE IF ( PRESENT( Sd ) ) THEN timeinterval%basetime%Sd = Sd IF ( PRESENT( Sn ) ) THEN timeinterval%basetime%Sn = Sn ENDIF ENDIF CALL normalize_timeint( timeinterval ) IF ( PRESENT(rc) ) rc = ESMF_SUCCESS end subroutine ESMF_TimeIntervalSet !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMFold_TimeIntervalGetString - Get time interval value in string format ! !INTERFACE: subroutine ESMFold_TimeIntervalGetString(timeinterval, TimeString, rc) ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval character*(*), intent(out) :: TimeString integer, intent(out), optional :: rc ! locals ! integer :: signnormtimeint LOGICAL :: negative INTEGER(ESMF_KIND_I8) :: iS, iSn, iSd, H, M, S, MM, D, YY character (len=1) :: signstr ! !DESCRIPTION: ! Convert {\tt ESMF\_TimeInterval}'s value into string format ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The object instance to convert ! \item[TimeString] ! The string to return ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.9 !EOP ! NOTE: Sn, and Sd are not yet included in the returned string... !PRINT *,'DEBUG ESMFold_TimeIntervalGetString(): YR,MM,S,Sn,Sd = ', & ! timeinterval%YR, & ! timeinterval%MM, & ! timeinterval%basetime%S, & ! timeinterval%basetime%Sn, & ! timeinterval%basetime%Sd negative = ( signnormtimeint( timeInterval ) == -1 ) IF ( negative ) THEN iS = -timeinterval%basetime%S iSn = -timeinterval%basetime%Sn signstr = '-' ELSE iS = timeinterval%basetime%S iSn = timeinterval%basetime%Sn signstr = '' ENDIF iSd = timeinterval%basetime%Sd D = iS / SECONDS_PER_DAY H = mod( iS, SECONDS_PER_DAY ) / SECONDS_PER_HOUR M = mod( iS, SECONDS_PER_HOUR) / SECONDS_PER_MINUTE S = mod( iS, SECONDS_PER_MINUTE ) !$$$here... need to print Sn and Sd when they are used ??? CALL timeintchecknormalized( timeinterval, 'ESMF_TimeIntervalGetString-arg1', & relative_interval=.true. ) IF ( (timeinterval%MM == 0) .AND. (timeinterval%YR == 0) )THEN write(TimeString,FMT="(A,I10.10,'_',I3.3,':',I3.3,':',I3.3)") & TRIM(signstr), D, H, M, S ELSEif (timeinterval%YR == 0) then MM = timeinterval%MM write(TimeString,FMT="(I4.4, '_Months_',A,I10.10,'_',I3.3,':',I3.3,':',I3.3)") & MM, TRIM(signstr), D, H, M, S else YY = timeinterval%YR MM = timeinterval%MM write(TimeString,FMT="(I6.6,'_Years_',I4.4, '_Months_',A,I10.10,'_',I3.3,':',I3.3,':',I3.3)") & YY, MM, TRIM(signstr), D, H, M, S END IF !write(0,*)'TimeIntervalGetString Sn ',timeinterval%basetime%Sn,' Sd ',timeinterval%basetime%Sd rc = ESMF_SUCCESS end subroutine ESMFold_TimeIntervalGetString !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalAbsValue - Get the absolute value of a time interval ! !INTERFACE: function ESMF_TimeIntervalAbsValue(timeinterval) ! !RETURN VALUE: type(ESMF_TimeInterval) :: ESMF_TimeIntervalAbsValue ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval ! !LOCAL: integer :: rc ! !DESCRIPTION: ! Return a {\tt ESMF\_TimeInterval}'s absolute value. ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The object instance to take the absolute value of. ! Absolute value returned as value of function. ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.8 !EOP ESMF_TimeIntervalAbsValue = timeinterval !$$$here... move implementation into BaseTime ESMF_TimeIntervalAbsValue%basetime%S = & abs(ESMF_TimeIntervalAbsValue%basetime%S) ESMF_TimeIntervalAbsValue%basetime%Sn = & abs(ESMF_TimeIntervalAbsValue%basetime%Sn ) ! ESMF_TimeIntervalAbsValue%MM = & abs(ESMF_TimeIntervalAbsValue%MM) ESMF_TimeIntervalAbsValue%YR = & abs(ESMF_TimeIntervalAbsValue%YR) end function ESMF_TimeIntervalAbsValue !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalNegAbsValue - Get the negative absolute value of a time interval ! !INTERFACE: function ESMF_TimeIntervalNegAbsValue(timeinterval) ! !RETURN VALUE: type(ESMF_TimeInterval) :: ESMF_TimeIntervalNegAbsValue ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval ! !LOCAL: integer :: rc ! !DESCRIPTION: ! Return a {\tt ESMF\_TimeInterval}'s negative absolute value. ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The object instance to take the negative absolute value of. ! Negative absolute value returned as value of function. ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.8 !EOP ESMF_TimeIntervalNegAbsValue = timeinterval !$$$here... move implementation into BaseTime ESMF_TimeIntervalNegAbsValue%basetime%S = & -abs(ESMF_TimeIntervalNegAbsValue%basetime%S) ESMF_TimeIntervalNegAbsValue%basetime%Sn = & -abs(ESMF_TimeIntervalNegAbsValue%basetime%Sn ) ! ESMF_TimeIntervalNegAbsValue%MM = & -abs(ESMF_TimeIntervalNegAbsValue%MM ) ESMF_TimeIntervalNegAbsValue%YR = & -abs(ESMF_TimeIntervalNegAbsValue%YR ) end function ESMF_TimeIntervalNegAbsValue !------------------------------------------------------------------------------ ! ! This section includes overloaded operators defined only for TimeInterval ! (not inherited from BaseTime) ! Note: these functions do not have a return code, since F90 forbids more ! than 2 arguments for arithmetic overloaded operators ! !------------------------------------------------------------------------------ ! new WRF-specific function, Divide two time intervals and return the whole integer, without remainder function ESMF_TimeIntervalDIVQuot(timeinterval1, timeinterval2) ! !RETURN VALUE: INTEGER :: ESMF_TimeIntervalDIVQuot ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !LOCAL INTEGER :: retval, isgn, rc type(ESMF_TimeInterval) :: zero, i1,i2 ! !DESCRIPTION: ! Returns timeinterval1 divided by timeinterval2 as a fraction quotient. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! The dividend ! \item[timeinterval2] ! The divisor ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.5 !EOP CALL timeintchecknormalized( timeinterval1, 'ESMF_TimeIntervalDIVQuot arg1' ) CALL timeintchecknormalized( timeinterval2, 'ESMF_TimeIntervalDIVQuot arg2' ) call ESMF_TimeIntervalSet( zero, rc=rc ) i1 = timeinterval1 i2 = timeinterval2 isgn = 1 if ( i1 .LT. zero ) then i1 = WRFADDITION_TimeIntervalProdI(i1, -1) isgn = -isgn endif if ( i2 .LT. zero ) then i2 = WRFADDITION_TimeIntervalProdI(i2, -1) isgn = -isgn endif ! repeated subtraction retval = 0 DO WHILE ( i1 .GE. i2 ) i1 = i1 - i2 retval = retval + 1 ENDDO retval = retval * isgn ESMF_TimeIntervalDIVQuot = retval end function ESMF_TimeIntervalDIVQuot ! added by jhe !------------------------------------------------------------------------------ !BOP ! !IROUTINE: WRFADDITION_TimeIntervalProdI - Multiply a time interval by an ! integer ! !INTERFACE: function WRFADDITION_TimeIntervalProdI(timeinterval, multiplier) ! !RETURN VALUE: type(ESMF_TimeInterval) :: WRFADDITION_TimeIntervalProdI ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval integer, intent(in) :: multiplier ! !LOCAL: integer :: rc ! !DESCRIPTION: ! Multiply a {\tt ESMF\_TimeInterval} by an integer, return product ! as a ! {\tt ESMF\_TimeInterval} ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The multiplicand ! \item[mutliplier] ! Integer multiplier ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.7, TMG7.2 !EOP CALL timeintchecknormalized( timeinterval, 'ESMF_TimeIntervalProdICarg1') CALL ESMF_TimeIntervalSet( WRFADDITION_TimeIntervalProdI, rc=rc ) !$$$move this into overloaded operator(*) in BaseTime WRFADDITION_TimeIntervalProdI%basetime%S = & timeinterval%basetime%S * INT( multiplier, ESMF_KIND_I8 ) WRFADDITION_TimeIntervalProdI%basetime%Sn = & timeinterval%basetime%Sn * INT( multiplier, ESMF_KIND_I8 ) ! Don't multiply Sd WRFADDITION_TimeIntervalProdI%basetime%Sd = timeinterval%basetime%Sd CALL normalize_timeint( WRFADDITION_TimeIntervalProdI ) end function WRFADDITION_TimeIntervalProdI !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalQuotI - Divide time interval by an integer, return time interval result ! !INTERFACE: function ESMF_TimeIntervalQuotI(timeinterval, divisor) ! !RETURN VALUE: type(ESMF_TimeInterval) :: ESMF_TimeIntervalQuotI ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval integer, intent(in) :: divisor ! !DESCRIPTION: ! Divides a {\tt ESMF\_TimeInterval} by an integer divisor, returns ! quotient as a {\tt ESMF\_TimeInterval} ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The dividend ! \item[divisor] ! Integer divisor ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.6, TMG5.3, TMG7.2 !EOP !PRINT *,'DEBUG ESMF_TimeIntervalQuotI() A: S,Sn,Sd = ', & ! timeinterval%basetime%S,timeinterval%basetime%Sn,timeinterval%basetime%Sd !PRINT *,'DEBUG ESMF_TimeIntervalQuotI() A: divisor = ', divisor CALL timeintchecknormalized( timeinterval, 'ESMF_TimeIntervalQuotI arg1' ) IF ( divisor == 0 ) THEN CALL wrf_error_fatal( 'ESMF_TimeIntervalQuotI: divide by zero' ) ENDIF ESMF_TimeIntervalQuotI = timeinterval !PRINT *,'DEBUG ESMF_TimeIntervalQuotI() B: S,Sn,Sd = ', & ! ESMF_TimeIntervalQuotI%basetime%S,ESMF_TimeIntervalQuotI%basetime%Sn,ESMF_TimeIntervalQuotI%basetime%Sd ESMF_TimeIntervalQuotI%basetime = timeinterval%basetime / divisor !PRINT *,'DEBUG ESMF_TimeIntervalQuotI() C: S,Sn,Sd = ', & ! ESMF_TimeIntervalQuotI%basetime%S,ESMF_TimeIntervalQuotI%basetime%Sn,ESMF_TimeIntervalQuotI%basetime%Sd CALL normalize_timeint( ESMF_TimeIntervalQuotI ) !PRINT *,'DEBUG ESMF_TimeIntervalQuotI() D: S,Sn,Sd = ', & ! ESMF_TimeIntervalQuotI%basetime%S,ESMF_TimeIntervalQuotI%basetime%Sn,ESMF_TimeIntervalQuotI%basetime%Sd end function ESMF_TimeIntervalQuotI !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalProdI - Multiply a time interval by an integer ! !INTERFACE: function ESMF_TimeIntervalProdI(timeinterval, multiplier) ! !RETURN VALUE: type(ESMF_TimeInterval) :: ESMF_TimeIntervalProdI ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval integer, intent(in) :: multiplier ! !LOCAL: integer :: rc ! !DESCRIPTION: ! Multiply a {\tt ESMF\_TimeInterval} by an integer, return product as a ! {\tt ESMF\_TimeInterval} ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! The multiplicand ! \item[mutliplier] ! Integer multiplier ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.7, TMG7.2 !EOP CALL timeintchecknormalized( timeinterval, 'ESMF_TimeIntervalProdI arg1', & relative_interval=.true. ) CALL ESMF_TimeIntervalSet( ESMF_TimeIntervalProdI, rc=rc ) !$$$move this into overloaded operator(*) in BaseTime ESMF_TimeIntervalProdI%basetime%S = & timeinterval%basetime%S * INT( multiplier, ESMF_KIND_I8 ) ESMF_TimeIntervalProdI%basetime%Sn = & timeinterval%basetime%Sn * INT( multiplier, ESMF_KIND_I8 ) ! Don't multiply Sd ESMF_TimeIntervalProdI%basetime%Sd = timeinterval%basetime%Sd ESMF_TimeIntervalProdI%MM = timeinterval%MM * multiplier ESMF_TimeIntervalProdI%YR = timeinterval%YR * multiplier CALL normalize_timeint( ESMF_TimeIntervalProdI ) end function ESMF_TimeIntervalProdI !------------------------------------------------------------------------------ ! ! This section includes the inherited ESMF_BaseTime class overloaded operators ! !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalSum - Add two time intervals together ! !INTERFACE: function ESMF_TimeIntervalSum(timeinterval1, timeinterval2) ! !RETURN VALUE: type(ESMF_TimeInterval) :: ESMF_TimeIntervalSum ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !LOCAL: integer :: rc ! !DESCRIPTION: ! Add two {\tt ESMF\_TimeIntervals}, return sum as a ! {\tt ESMF\_TimeInterval}. Maps overloaded (+) operator interface ! function to {\tt ESMF\_BaseTime} base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! The augend ! \item[timeinterval2] ! The addend ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.4, TMG2.4.4, TMG2.4.5, TMG2.4.6, TMG5.1, TMG5.2, ! TMG7.2 !EOP CALL timeintchecknormalized( timeinterval1, 'ESMF_TimeIntervalSum arg1', & relative_interval=.true. ) CALL timeintchecknormalized( timeinterval2, 'ESMF_TimeIntervalSum arg2', & relative_interval=.true. ) ESMF_TimeIntervalSum = timeinterval1 ESMF_TimeIntervalSum%basetime = ESMF_TimeIntervalSum%basetime + & timeinterval2%basetime ESMF_TimeIntervalSum%MM = ESMF_TimeIntervalSum%MM + & timeinterval2%MM ESMF_TimeIntervalSum%YR = ESMF_TimeIntervalSum%YR + & timeinterval2%YR CALL normalize_timeint( ESMF_TimeIntervalSum ) end function ESMF_TimeIntervalSum !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalDiff - Subtract one time interval from another ! !INTERFACE: function ESMF_TimeIntervalDiff(timeinterval1, timeinterval2) ! !RETURN VALUE: type(ESMF_TimeInterval) :: ESMF_TimeIntervalDiff ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !LOCAL: integer :: rc ! !DESCRIPTION: ! Subtract timeinterval2 from timeinterval1, return remainder as a ! {\tt ESMF\_TimeInterval}. ! Map overloaded (-) operator interface function to {\tt ESMF\_BaseTime} ! base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! The minuend ! \item[timeinterval2] ! The subtrahend ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.4, TMG2.4.4, TMG2.4.5, TMG2.4.6, TMG5.1, TMG5.2, TMG7.2 !EOP CALL timeintchecknormalized( timeinterval1, 'ESMF_TimeIntervalDiff arg1', & relative_interval=.true. ) CALL timeintchecknormalized( timeinterval2, 'ESMF_TimeIntervalDiff arg2', & relative_interval=.true. ) ESMF_TimeIntervalDiff = timeinterval1 ESMF_TimeIntervalDiff%basetime = ESMF_TimeIntervalDiff%basetime - & timeinterval2%basetime ESMF_TimeIntervalDiff%MM = ESMF_TimeIntervalDiff%MM - & timeinterval2%MM ESMF_TimeIntervalDiff%YR = ESMF_TimeIntervalDiff%YR - & timeinterval2%YR CALL normalize_timeint( ESMF_TimeIntervalDiff ) end function ESMF_TimeIntervalDiff !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalEQ - Compare two time intervals for equality ! !INTERFACE: function ESMF_TimeIntervalEQ(timeinterval1, timeinterval2) ! ! !RETURN VALUE: logical :: ESMF_TimeIntervalEQ ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 !DESCRIPTION: ! Return true if both given time intervals are equal, false otherwise. ! Maps overloaded (==) operator interface function to {\tt ESMF\_BaseTime} ! base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! First time interval to compare ! \item[timeinterval2] ! Second time interval to compare ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.3, TMG2.4.3, TMG7.2 !EOP INTEGER :: res CALL timeintcmp(timeinterval1,timeinterval2,res) ESMF_TimeIntervalEQ = (res .EQ. 0) end function ESMF_TimeIntervalEQ !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalNE - Compare two time intervals for inequality ! !INTERFACE: function ESMF_TimeIntervalNE(timeinterval1, timeinterval2) ! ! !RETURN VALUE: logical :: ESMF_TimeIntervalNE ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !DESCRIPTION: ! Return true if both given time intervals are not equal, false otherwise. ! Maps overloaded (/=) operator interface function to {\tt ESMF\_BaseTime} ! base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! First time interval to compare ! \item[timeinterval2] ! Second time interval to compare ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.3, TMG2.4.3, TMG7.2 !EOP INTEGER :: res CALL timeintcmp(timeinterval1,timeinterval2,res) ESMF_TimeIntervalNE = (res .NE. 0) end function ESMF_TimeIntervalNE !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalLT - Time interval 1 less than time interval 2 ? ! !INTERFACE: function ESMF_TimeIntervalLT(timeinterval1, timeinterval2) ! ! !RETURN VALUE: logical :: ESMF_TimeIntervalLT ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !DESCRIPTION: ! Return true if first time interval is less than second time interval, ! false otherwise. Maps overloaded (<) operator interface function to ! {\tt ESMF\_BaseTime} base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! First time interval to compare ! \item[timeinterval2] ! Second time interval to compare ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.3, TMG2.4.3, TMG7.2 !EOP INTEGER :: res CALL timeintcmp(timeinterval1,timeinterval2,res) ESMF_TimeIntervalLT = (res .LT. 0) end function ESMF_TimeIntervalLT !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalGT - Time interval 1 greater than time interval 2? ! !INTERFACE: function ESMF_TimeIntervalGT(timeinterval1, timeinterval2) ! ! !RETURN VALUE: logical :: ESMF_TimeIntervalGT ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !DESCRIPTION: ! Return true if first time interval is greater than second time interval, ! false otherwise. Maps overloaded (>) operator interface function to ! {\tt ESMF\_BaseTime} base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! First time interval to compare ! \item[timeinterval2] ! Second time interval to compare ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.3, TMG2.4.3, TMG7.2 !EOP INTEGER :: res CALL timeintcmp(timeinterval1,timeinterval2,res) ESMF_TimeIntervalGT = (res .GT. 0) end function ESMF_TimeIntervalGT !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalLE - Time interval 1 less than or equal to time interval 2 ? ! !INTERFACE: function ESMF_TimeIntervalLE(timeinterval1, timeinterval2) ! !RETURN VALUE: logical :: ESMF_TimeIntervalLE ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !DESCRIPTION: ! Return true if first time interval is less than or equal to second time ! interval, false otherwise. ! Maps overloaded (<=) operator interface function to {\tt ESMF\_BaseTime} ! base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! First time interval to compare ! \item[timeinterval2] ! Second time interval to compare ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.3, TMG2.4.3, TMG7.2 !EOP INTEGER :: res CALL timeintcmp(timeinterval1,timeinterval2,res) ESMF_TimeIntervalLE = (res .LE. 0) end function ESMF_TimeIntervalLE !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalGE - Time interval 1 greater than or equal to time interval 2 ? ! !INTERFACE: function ESMF_TimeIntervalGE(timeinterval1, timeinterval2) ! ! !RETURN VALUE: logical :: ESMF_TimeIntervalGE ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval1 type(ESMF_TimeInterval), intent(in) :: timeinterval2 ! !DESCRIPTION: ! Return true if first time interval is greater than or equal to second ! time interval, false otherwise. Maps overloaded (>=) operator interface ! function to {\tt ESMF\_BaseTime} base class. ! ! The arguments are: ! \begin{description} ! \item[timeinterval1] ! First time interval to compare ! \item[timeinterval2] ! Second time interval to compare ! \end{description} ! ! !REQUIREMENTS: ! TMG1.5.3, TMG2.4.3, TMG7.2 !EOP INTEGER :: res CALL timeintcmp(timeinterval1,timeinterval2,res) ESMF_TimeIntervalGE = (res .GE. 0) end function ESMF_TimeIntervalGE !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalIsPositive - Time interval greater than zero? ! !INTERFACE: function ESMF_TimeIntervalIsPositive(timeinterval) ! ! !RETURN VALUE: logical :: ESMF_TimeIntervalIsPositive ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval ! !LOCALS: type(ESMF_TimeInterval) :: zerotimeint integer :: rcint ! !DESCRIPTION: ! Return true if time interval is greater than zero, ! false otherwise. ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! Time interval to compare ! \end{description} !EOP CALL timeintchecknormalized( timeinterval, & 'ESMF_TimeIntervalIsPositive arg' ) CALL ESMF_TimeIntervalSet ( zerotimeint, rc=rcint ) IF ( rcint /= ESMF_SUCCESS ) THEN CALL wrf_error_fatal( & 'ESMF_TimeIntervalIsPositive: ESMF_TimeIntervalSet failed' ) ENDIF ! hack for bug in PGI 5.1-x ! ESMF_TimeIntervalIsPositive = timeinterval > zerotimeint ESMF_TimeIntervalIsPositive = ESMF_TimeIntervalGT( timeinterval, & zerotimeint ) end function ESMF_TimeIntervalIsPositive !------------------------------------------------------------------------------ !BOP ! !IROUTINE: ESMF_TimeIntervalPrint - Print out a time interval's properties ! !INTERFACE: subroutine ESMF_TimeIntervalPrint(timeinterval, opts, rc) ! !ARGUMENTS: type(ESMF_TimeInterval), intent(in) :: timeinterval character (len=*), intent(in), optional :: opts integer, intent(out), optional :: rc ! !DESCRIPTION: ! To support testing/debugging, print out an {\tt ESMF\_TimeInterval}'s ! properties. ! ! The arguments are: ! \begin{description} ! \item[timeinterval] ! Time interval to print out ! \item[{[opts]}] ! Print options ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! ! !REQUIREMENTS: ! TMGn.n.n !EOP INTEGER :: ierr ierr = ESMF_SUCCESS call print_a_timeinterval( timeinterval ) IF ( PRESENT(rc) ) rc = ierr end subroutine ESMF_TimeIntervalPrint !------------------------------------------------------------------------------ ! Exits with error message if timeInt is not normalized. SUBROUTINE timeintchecknormalized( timeInt, msgstr, relative_interval ) IMPLICIT NONE TYPE(ESMF_TimeInterval), INTENT(IN) :: timeInt CHARACTER(LEN=*), INTENT(IN) :: msgstr LOGICAL, INTENT(IN), optional :: relative_interval ! If relative intervals are ok or not ! locals CHARACTER(LEN=256) :: outstr LOGICAL :: non_relative IF ( .NOT. PRESENT( relative_interval ) )THEN non_relative = .true. ELSE IF ( relative_interval )THEN non_relative = .false. ELSE non_relative = .true. END IF END IF IF ( non_relative )THEN IF ( ( timeInt%YR /= 0 ) .OR. & ( timeInt%MM /= 0 ) ) THEN outstr = 'un-normalized TimeInterval not allowed: '//TRIM(msgstr) CALL wrf_error_fatal( outstr ) ENDIF ELSE IF ( ( timeInt%YR /= 0 ) .OR. & ( timeInt%MM < -MONTHS_PER_YEAR) .OR. ( timeInt%MM > MONTHS_PER_YEAR ) ) THEN ! tcraig, don't require normalize TimeInterval for relative diffs ! outstr = 'un-normalized TimeInterval not allowed: '//TRIM(msgstr) ! CALL wrf_error_fatal( outstr ) ENDIF END IF END SUBROUTINE timeintchecknormalized !============================================================================== SUBROUTINE print_a_timeinterval( time ) IMPLICIT NONE type(ESMF_TimeInterval) time character*128 :: s integer rc CALL ESMFold_TimeIntervalGetString( time, s, rc ) write(6,*)'Print a time interval|',time%yr, time%mm, time%basetime%s, time%starttime_set, time%starttime%calendar%type%caltype write(6,*)'Print a time interval|',TRIM(s),'|' return END SUBROUTINE print_a_timeinterval !============================================================================== SUBROUTINE timeintcmp(timeint1in, timeint2in, retval ) IMPLICIT NONE INTEGER, INTENT(OUT) :: retval ! ! !ARGUMENTS: TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1in TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2in TYPE(ESMF_TimeInterval) :: timeint1 TYPE(ESMF_TimeInterval) :: timeint2 timeint1 = timeint1in timeint2 = timeint2in call normalize_timeint(timeint1) call normalize_timeint(timeint2) IF ( (timeint1%MM /= timeint2%MM) .and. (timeint1%YR /= timeint2%YR) )THEN CALL wrf_error_fatal( & 'timeintcmp: Can not compare two intervals with different months and years' ) END IF if (timeint1%YR .gt. timeint2%YR) then retval = 1 elseif (timeint1%YR .lt. timeint2%YR) then retval = -1 else if (timeint1%MM .gt. timeint2%MM) then retval = 1 elseif (timeint1%MM .lt. timeint2%MM) then retval = 1 else CALL seccmp( timeint1%basetime%S, timeint1%basetime%Sn, & timeint1%basetime%Sd, & timeint2%basetime%S, timeint2%basetime%Sn, & timeint2%basetime%Sd, retval ) endif endif END SUBROUTINE timeintcmp !============================================================================== SUBROUTINE normalize_timeint( timeInt ) IMPLICIT NONE TYPE(ESMF_TimeInterval), INTENT(INOUT) :: timeInt INTEGER :: mpyi4 ! normalize basetime ! this will force abs(Sn) < Sd and ensure that signs of S and Sn match ! YR and MM are ignored CALL normalize_basetime( timeInt%basetime ) ! Rollover months to years mpyi4 = MONTHS_PER_YEAR IF ( abs(timeInt%MM) .GE. MONTHS_PER_YEAR ) THEN timeInt%YR = timeInt%YR + timeInt%MM/MONTHS_PER_YEAR timeInt%MM = mod(timeInt%MM,mpyi4) ENDIF ! make sure yr and mm have same sign IF (timeInt%YR * timeInt%MM < 0) then if (timeInt%YR > 0) then timeInt%MM = timeInt%MM + MONTHS_PER_YEAR timeInt%YR = timeInt%YR - 1 endif if (timeInt%YR < 0) then timeInt%MM = timeInt%MM - MONTHS_PER_YEAR timeInt%YR = timeInt%YR + 1 endif endif END SUBROUTINE normalize_timeint !============================================================================== integer FUNCTION signnormtimeint ( timeInt ) ! Compute the sign of a time interval. ! YR and MM fields are *IGNORED*. ! returns 1, 0, or -1 or exits if timeInt fields have inconsistent signs. IMPLICIT NONE TYPE(ESMF_TimeInterval), INTENT(IN) :: timeInt LOGICAL :: positive, negative positive = .FALSE. negative = .FALSE. signnormtimeint = 0 ! Note that Sd is required to be non-negative. This is enforced in ! normalize_timeint(). ! Note that Sn is required to be zero when Sd is zero. This is enforced ! in normalize_timeint(). IF ( ( timeInt%basetime%S > 0 ) .OR. & ( timeInt%basetime%Sn > 0 ) ) THEN positive = .TRUE. ENDIF IF ( ( timeInt%basetime%S < 0 ) .OR. & ( timeInt%basetime%Sn < 0 ) ) THEN negative = .TRUE. ENDIF IF ( positive .AND. negative ) THEN CALL wrf_error_fatal( & 'signnormtimeint: signs of fields cannot be mixed' ) ELSE IF ( positive ) THEN signnormtimeint = 1 ELSE IF ( negative ) THEN signnormtimeint = -1 ENDIF END FUNCTION signnormtimeint !============================================================================== end module ESMF_TimeIntervalMod