LCOV - code coverage report
Current view: top level - hemco/HEMCO/src/Core - hco_timeshift_mod.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 158 0.0 %
Date: 2025-01-13 21:54:50 Functions: 0 2 0.0 %

          Line data    Source code
       1             : !------------------------------------------------------------------------------
       2             : !                   Harmonized Emissions Component (HEMCO)                    !
       3             : !------------------------------------------------------------------------------
       4             : !BOP
       5             : !
       6             : ! !MODULE: hco_timeshift_mod.F90
       7             : !
       8             : ! !DESCRIPTION: Module hco\_timeshift\_mod.F90 contains routines to shift the
       9             : ! file reference time by a given value. Time stamps shifts can be provided as
      10             : ! optional fifth element to the time stamp attribute in the HEMCO configuration
      11             : ! file.
      12             : !\\
      13             : !\\
      14             : ! For instance, consider the case where 3-hourly averages are provided in
      15             : ! individual files with centered time stamps, e.g.: file.yyyymmdd\_0130z.nc,
      16             : ! file.yyyymmdd\_0430z.nc, ..., file.yyymmdd\_2230z.nc
      17             : ! To read these files *at the beginning* of their time intervals, the time
      18             : ! stamp can be shifted by 90 minutes, e.g. the file name, variable, and time
      19             : ! attribute section reads:
      20             : ! ... file.\$yyyy$mm$dd\_\$hh\$mnz.nc VARNAME 2000-2016/1-12/1-31/0-23/+90minutes ...
      21             : !\\
      22             : !\\
      23             : ! At time 00z, HEMCO will then read file 0130z and keep using this file until
      24             : ! 03z, when it switches to file 0430z. Similarly, it is possible to shift the
      25             : ! file reference time by any number of years, months, days, or hours. Time
      26             : ! shifts can be forward or backward in time (use - sign to shift backwards).
      27             : !\\
      28             : !\\
      29             : ! This module contains subroutines to determine the time to be shifted (stored
      30             : ! in filedata variable tshift) and shifts the desired reference time as needed.
      31             : !\\
      32             : !\\
      33             : ! !INTERFACE:
      34             : !
      35             : MODULE HCO_TIMESHIFT_MOD
      36             : !
      37             : ! !USES:
      38             : !
      39             :   USE HCO_Error_Mod
      40             :   USE HCO_State_Mod,  ONLY : HCO_State
      41             : 
      42             :   IMPLICIT NONE
      43             :   PRIVATE
      44             : !
      45             : ! !PUBLIC MEMBER FUNCTIONS:
      46             : !
      47             :   PUBLIC :: TimeShift_Set
      48             :   PUBLIC :: TimeShift_Apply
      49             : !
      50             : ! !REMARKS:
      51             : !
      52             : ! !REVISION HISTORY:
      53             : !  29 Feb 2016 - C. Keller   - Initial version
      54             : !  See https://github.com/geoschem/hemco for complete history
      55             : !EOP
      56             : !------------------------------------------------------------------------------
      57             : !BOC
      58             : !
      59             : ! !PRIVATE TYPES:
      60             : !
      61             : CONTAINS
      62             : !EOC
      63             : !------------------------------------------------------------------------------
      64             : !                   Harmonized Emissions Component (HEMCO)                    !
      65             : !------------------------------------------------------------------------------
      66             : !BOP
      67             : !
      68             : ! !IROUTINE: TimeShift_Set
      69             : !
      70             : ! !DESCRIPTION: Subroutine TimeShift\_Set sets the time shift values. The
      71             : ! time shift attribute tshift contains two entries: the first entry denotes
      72             : ! the number of months to be shifted (integer value), while the second entry
      73             : ! denotes then number of seconds to be shifted.
      74             : !\\
      75             : !\\
      76             : ! !INTERFACE:
      77             : !
      78           0 :   SUBROUTINE TimeShift_Set( HcoConfig, Dta, shift, RC )
      79             : !
      80             : ! !USES:
      81             : !
      82             :     USE HCO_TYPES_MOD,    ONLY : ListCont
      83             :     USE HCO_TYPES_MOD,    ONLY : FileData
      84             :     USE HCO_TYPES_MOD,    ONLY : ConfigObj
      85             : !
      86             : ! !INPUT/OUTPUT PARAMETERS:
      87             : !
      88             :     TYPE(ConfigObj),  POINTER        :: HcoConfig    ! HEMCO config
      89             :     TYPE(FileData),   POINTER        :: Dta       ! file container
      90             :     CHARACTER(LEN=*), INTENT(IN   )  :: shift     ! time shift
      91             :     INTEGER,          INTENT(INOUT)  :: RC        ! Return code
      92             : !
      93             : ! !REVISION HISTORY:
      94             : !  29 Feb 2016 - C. Keller - Initial version
      95             : !  See https://github.com/geoschem/hemco for complete history
      96             : !EOP
      97             : !------------------------------------------------------------------------------
      98             : !BOC
      99             : !
     100             : ! !LOCAL VARIABLES:
     101             : !
     102             :     INTEGER                        :: SHFT, IDX
     103             :     CHARACTER(LEN=255)             :: MSG
     104             :     CHARACTER(LEN=255)             :: iShift
     105             :     CHARACTER(LEN=255)             :: tShift
     106             :     CHARACTER(LEN=255), PARAMETER  :: LOC = 'TimeShift_Set (hco_timeshift_mod.F90)'
     107             : 
     108             :     !======================================================================
     109             :     ! TimeShift_Set begins here!
     110             :     !======================================================================
     111             : 
     112             :     ! Assume success until otherwise
     113           0 :     RC = HCO_SUCCESS
     114             : 
     115             :     ! Init
     116           0 :     Dta%tShift(:) = 0.0_hp
     117             : 
     118             :     ! Mirror variable
     119           0 :     iShift = TRIM(ADJUSTL(Shift))
     120             : 
     121             :     ! Parse time iShift and write to desired slot:
     122           0 :     IDX = INDEX( TRIM(iShift), 'year' )
     123           0 :     IF( IDX < 0 ) IDX = INDEX( TRIM(iShift), 'yr' )
     124           0 :     IF ( IDX > 1 ) THEN
     125           0 :        READ( iShift(1:(IDX-1)), * ) SHFT
     126           0 :        Dta%tShift(1) = Dta%tShift(1) + SHFT
     127           0 :        WRITE(tShift,*) Dta%tShift(1), ' years'
     128             :     ENDIF
     129             : 
     130           0 :     IDX = INDEX( TRIM(iShift), 'month' )
     131           0 :     IF( IDX < 0 ) IDX = INDEX( TRIM(iShift), 'mt' )
     132           0 :     IF ( IDX > 1 ) THEN
     133           0 :        READ( iShift(1:(IDX-1)), * ) SHFT
     134           0 :        Dta%tShift(2) = Dta%tShift(2) + SHFT
     135           0 :        WRITE(tShift,*) Dta%tShift(2), ' months'
     136             :     ENDIF
     137             : 
     138           0 :     IDX = INDEX( TRIM(iShift), 'day' )
     139           0 :     IF( IDX < 0 ) IDX = INDEX( TRIM(iShift), 'dy' )
     140           0 :     IF ( IDX > 1 ) THEN
     141           0 :        READ( iShift(1:(IDX-1)), * ) SHFT
     142           0 :        Dta%tShift(3) = Dta%tShift(3) + SHFT
     143           0 :        WRITE(tShift,*) Dta%tShift(3), ' days'
     144             :     ENDIF
     145             : 
     146           0 :     IDX = INDEX( TRIM(iShift), 'hour' )
     147           0 :     IF( IDX < 0 ) IDX = INDEX( TRIM(iShift), 'hr' )
     148           0 :     IF ( IDX > 1 ) THEN
     149           0 :        READ( iShift(1:(IDX-1)), * ) SHFT
     150           0 :        Dta%tShift(4) = Dta%tShift(4) + SHFT
     151           0 :        WRITE(tShift,*) Dta%tShift(4), ' hours'
     152             :     ENDIF
     153             : 
     154           0 :     IDX = INDEX( TRIM(iShift), 'min' )
     155           0 :     IF( IDX < 0 ) IDX = INDEX( TRIM(iShift), 'mn' )
     156           0 :     IF ( IDX > 1 ) THEN
     157           0 :        READ( iShift(1:(IDX-1)), * ) SHFT
     158           0 :        Dta%tShift(5) = Dta%tShift(5) + SHFT
     159           0 :        WRITE(tShift,*) Dta%tShift(5), ' minutes'
     160             :     ENDIF
     161             : 
     162           0 :     IDX = INDEX( TRIM(iShift), 'sec' )
     163           0 :     IF ( IDX > 1 ) THEN
     164           0 :        READ( iShift(1:(IDX-1)), * ) SHFT
     165           0 :        Dta%tShift(6) = Dta%tShift(6) + SHFT
     166           0 :        WRITE(tShift,*) Dta%tShift(6), ' seconds'
     167             :     ENDIF
     168             : 
     169             :     ! Error: cannot shift data if we use weekday data
     170             :     IF ( Dta%tShift(1) /= 0 .OR. Dta%tShift(2) /= 0 .or. &
     171             :          Dta%tShift(3) /= 0 .OR. Dta%tShift(4) /= 0 .or. &
     172           0 :          Dta%tShift(5) /= 0 .OR. Dta%tShift(6) /= 0 ) THEN
     173           0 :        IF (   Dta%ncDys(1) == -10 .OR. &
     174             :             ( Dta%ncDys(1) == 1 .AND. Dta%ncDys(2) == 7 ) ) THEN
     175           0 :           WRITE(MSG,*) 'Time shift not supported for weekday data: ', &
     176           0 :              TRIM(Dta%ncFile)
     177           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
     178           0 :           RETURN
     179             :        ENDIF
     180             :     ENDIF
     181             : 
     182             :     ! verbose mode
     183           0 :     IF ( HCO_IsVerb( HcoConfig%Err ) ) THEN
     184           0 :        WRITE(MSG,*) 'Will shift time stamp of field ', TRIM(Dta%ncPara), &
     185           0 :                     ': ', TRIM(tShift)
     186           0 :        CALL HCO_MSG(HcoConfig%Err,MSG)
     187             :     ENDIF
     188             : 
     189           0 :     RC = HCO_SUCCESS
     190             : 
     191           0 :   END SUBROUTINE TimeShift_Set
     192             : !EOC
     193             : !------------------------------------------------------------------------------
     194             : !                   Harmonized Emissions Component (HEMCO)                    !
     195             : !------------------------------------------------------------------------------
     196             : !BOP
     197             : !
     198             : ! !IROUTINE: TimeShift_Apply
     199             : !
     200             : ! !DESCRIPTION: Subroutine TimeShift\_Apply shifts the reference time
     201             : ! (provided through arguments yr, mt, dy, hr, and mn, by the time shift
     202             : ! specified in the HEMCO configuration file (if specified at all).
     203             : !\\
     204             : !\\
     205             : ! !INTERFACE:
     206             : !
     207           0 :   SUBROUTINE TimeShift_Apply( HcoState, Lct, &
     208             :                               yr, mt, dy, hr, mn,  RC )
     209             : !
     210             : ! !USES:
     211             : !
     212             :     USE HCO_Julday_Mod
     213             :     USE HCO_TYPES_MOD,    ONLY : ListCont
     214             : !
     215             : ! !INPUT/OUTPUT PARAMETERS:
     216             : !
     217             :     TYPE(HCO_State),  POINTER        :: HcoState  ! Hemco state
     218             :     TYPE(ListCont),   POINTER        :: Lct       ! List container
     219             :     INTEGER,          INTENT(INOUT)  :: yr        ! year
     220             :     INTEGER,          INTENT(INOUT)  :: mt        ! month
     221             :     INTEGER,          INTENT(INOUT)  :: dy        ! day
     222             :     INTEGER,          INTENT(INOUT)  :: hr        ! hour
     223             :     INTEGER,          INTENT(INOUT)  :: mn        ! minute
     224             :     INTEGER,          INTENT(INOUT)  :: RC        ! Return code
     225             : !
     226             : ! !REVISION HISTORY:
     227             : !  29 Feb 2016 - C. Keller - Initial version
     228             : !  See https://github.com/geoschem/hemco for complete history
     229             : !EOP
     230             : !------------------------------------------------------------------------------
     231             : !BOC
     232             : !
     233             : ! !LOCAL VARIABLES:
     234             : !
     235             :     INTEGER                        :: nYr, nMt, nDy, nHr, nMn
     236             :     INTEGER                        :: oYr, oMt, oDy, oHr, oMn
     237             :     INTEGER                        :: SHFT, IDX
     238             :     INTEGER                        :: YYYYMMDD, HHMMSS
     239             :     REAL(dp)                       :: TimeShift, DAY, UTC, JD
     240             : 
     241             :     CHARACTER(LEN=255)             :: MSG
     242             :     CHARACTER(LEN=255), PARAMETER  :: LOC = 'TimeShift_Apply (hco_timeshift_mod.F90)'
     243             : 
     244             :     !======================================================================
     245             :     ! TimeShift_Apply begins here!
     246             :     !======================================================================
     247             : 
     248             :     ! Assume success until otherwise
     249           0 :     RC = HCO_SUCCESS
     250             : 
     251             :     ! Nothing to do if time shift is zero
     252             :     IF ( Lct%Dct%Dta%tShift(1) == 0 .AND. &
     253             :          Lct%Dct%Dta%tShift(2) == 0 .AND. &
     254             :          Lct%Dct%Dta%tShift(3) == 0 .AND. &
     255             :          Lct%Dct%Dta%tShift(4) == 0 .AND. &
     256           0 :          Lct%Dct%Dta%tShift(5) == 0 .AND. &
     257           0 :          Lct%Dct%Dta%tShift(6) == 0 ) RETURN
     258             : 
     259             :     ! Mirror values
     260           0 :     nYr = MAX(Yr,1)
     261           0 :     nMt = MAX(Mt,1)
     262           0 :     nDy = MAX(Dy,1)
     263           0 :     nHr = MAX(Hr,0)
     264           0 :     nMn = MAX(Mn,0)
     265             : 
     266             :     ! Archive original values
     267           0 :     oYr = nYr
     268           0 :     oMt = nMt
     269           0 :     oDy = nDy
     270           0 :     oHr = nHr
     271           0 :     oMn = nMn
     272             : 
     273             :     ! Apply minute time shift
     274           0 :     IF ( ABS(Lct%Dct%Dta%tShift(5)) > 0 ) THEN
     275           0 :        nMn = nMn + Lct%Dct%Dta%tShift(5)
     276             :     ENDIF
     277             : 
     278             :     ! Make sure new minute value is within 0-59 and adjust hour accordingly
     279           0 :     IF ( nMn > 59 ) THEN
     280           0 :        DO WHILE ( nMn > 59 )
     281           0 :           nMn = nMn - 60
     282           0 :           nHr = nHr + 1
     283             :        ENDDO
     284           0 :     ELSEIF( nMn < 0 ) THEN
     285           0 :        DO WHILE ( nMn < 1 )
     286           0 :           nMn = nMn + 60
     287           0 :           nHr = nHr - 1
     288             :        ENDDO
     289             :     ENDIF
     290             : 
     291             :     ! Apply hour time shift
     292           0 :     IF ( ABS(Lct%Dct%Dta%tShift(4)) > 0 ) THEN
     293           0 :        nHr = nHr + Lct%Dct%Dta%tShift(4)
     294             :     ENDIF
     295             : 
     296             :     ! Make sure new hour value is within 0-23 and adjust day accordingly
     297           0 :     IF ( nHr > 23 ) THEN
     298           0 :        DO WHILE ( nHr > 23 )
     299           0 :           nHr = nHr - 24
     300           0 :           nDy = nDy + 1
     301             :        ENDDO
     302           0 :     ELSEIF( nHr < 0 ) THEN
     303           0 :        DO WHILE ( nHr < 1 )
     304           0 :           nHr = nHr + 24
     305           0 :           nDy = nDy - 1
     306             :        ENDDO
     307             :     ENDIF
     308             : 
     309             :     ! Apply day time shift
     310           0 :     IF ( ABS(Lct%Dct%Dta%tShift(3)) > 0 ) THEN
     311           0 :        nDy = nDy + Lct%Dct%Dta%tShift(3)
     312             :     ENDIF
     313             : 
     314             :     ! Make sure new day is within ndays in month and adjust month accordingly
     315           0 :     IF ( nDy > 28 .AND. oMt == 2 .AND. MOD( oYr, 4 ) /= 0 ) THEN
     316           0 :        nDy = nDy - 28
     317           0 :        nMt = nMt + 1
     318           0 :     ELSEIF ( nDy > 29 .AND. oMt == 2 .AND. MOD( oYr, 4 ) == 0) THEN
     319           0 :        nDy = nDy - 29
     320           0 :        nMt = nMt + 1
     321           0 :     ELSEIF ( nDy > 30 .AND. &
     322             :            ( oMt == 4 .OR. oMt == 6 .OR. oMt == 9 .OR. oMt == 11 ) ) THEN
     323           0 :        nDy = nDy - 30
     324           0 :        nMt = nMt + 1
     325           0 :     ELSEIF ( nDy > 31 .AND. &
     326             :            ( oMt == 1 .OR. oMt == 3  .OR. oMt == 5 .OR. oMt == 7 .OR. &
     327             :              oMt == 8 .OR. oMt == 10 .OR. oMt == 12 ) ) THEN
     328           0 :        nDy = nDy - 31
     329           0 :        nMt = nMt + 1
     330           0 :     ELSEIF ( nDy <= 0 ) THEN
     331           0 :        IF ( oMt == 3 ) THEN
     332           0 :           IF ( MOD( oYr, 4 ) == 0 ) THEN
     333           0 :              nDy = nDy + 29
     334             :           ELSE
     335           0 :              nDy = nDy + 28
     336             :           ENDIF
     337           0 :           nMt = nMt - 1
     338           0 :        ELSEIF ( oMt == 5 .OR. oMt == 7 .OR. oMt == 10 .OR. oMt == 12 ) THEN
     339           0 :           nDy = nDy + 30
     340           0 :           nMt = nMt - 1
     341             :        ELSEIF ( oMt == 1. .OR. oMt == 2 .OR. oMt == 4 .OR. oMt == 6 .OR. &
     342           0 :                 oMt == 8  .OR. oMt == 9 .OR. oMt == 11 ) THEN
     343           0 :           nDy = nDy + 31
     344           0 :           nMt = nMt - 1
     345             :        ENDIF
     346             :     ENDIF
     347             : 
     348             :     ! Apply month time shift
     349           0 :     IF ( ABS(Lct%Dct%Dta%tShift(2)) > 0 ) THEN
     350           0 :        nMt = nMt + Lct%Dct%Dta%tShift(2)
     351             :     ENDIF
     352             : 
     353             :     ! Make sure new month is within 1-12 and adjust year accordingly
     354           0 :     IF ( nMt > 12 ) THEN
     355           0 :        DO WHILE ( nMt > 12 )
     356           0 :           nMt = nMt - 12
     357           0 :           nYr = nYr + 1
     358             :        ENDDO
     359           0 :     ELSEIF( nMt <= 0 ) THEN
     360           0 :        DO WHILE ( nMt < 1 )
     361           0 :           nMt = nMt + 12
     362           0 :           nYr = nYr - 1
     363             :        ENDDO
     364             :     ENDIF
     365             : 
     366             :     ! Apply year time shift
     367           0 :     IF ( ABS(Lct%Dct%Dta%tShift(1)) > 0 ) THEN
     368           0 :        nYr = nYr + Lct%Dct%Dta%tShift(1)
     369             :     ENDIF
     370             : 
     371             :     ! Eventually cap time shift for the same day.
     372           0 :     IF ( HcoState%Options%TimeShiftCap ) THEN
     373             :        IF ( ( nYr < oYr                  ) .OR. &
     374           0 :             ( nMt < oMt .AND. nYr == oYr ) .OR. &
     375             :             ( nDy < oDy .AND. nMt == oMt )       ) THEN
     376           0 :           nYr = oYr
     377           0 :           nMt = oMt
     378           0 :           nDy = oDy
     379           0 :           nHr = 0
     380           0 :           nMn = 0
     381           0 :           IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
     382           0 :              MSG = 'Options set to cap time shift - set to low bound'
     383           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     384             :           ENDIF
     385           0 :        ELSEIF ( nYr > oYr .OR. nMt > oMt .OR. nDy > oDy ) THEN
     386           0 :           nYr = oYr
     387           0 :           nMt = oMt
     388           0 :           nDy = oDy
     389           0 :           nHr = 23
     390           0 :           nMn = 59
     391           0 :           IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
     392           0 :              MSG = 'Options set to cap time shift - set to high bound'
     393           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     394             :           ENDIF
     395             :        ENDIF
     396             :     ENDIF
     397             : 
     398             :     ! verbose mode
     399           0 :     IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
     400           0 :        WRITE(MSG,*) 'Adjusted time stamp of field ', TRIM(Lct%Dct%cName)
     401           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     402           0 :        WRITE(MSG,*) 'Time shift (YMDhms): ', Lct%Dct%Dta%tShift
     403           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     404           0 :        WRITE(MSG,'(a27,i4.4,a1,i2.2,a1,i2.2,a1,i2.2,a1,i2.2)') 'Original Yr/Mt/Dy-Hr:Mn = ',oYr,'/',oMt,'/',oDy,'-',oHr,':',oMn
     405           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     406             :     ENDIF
     407             : 
     408             :     ! Add back to output values
     409           0 :     Yr = nYr
     410           0 :     Mt = nMt
     411           0 :     Dy = nDy
     412           0 :     Hr = nHr
     413           0 :     Mn = nMn
     414             : 
     415             :     ! verbose mode
     416           0 :     IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
     417           0 :        WRITE(MSG,'(a27,i4.4,a1,i2.2,a1,i2.2,a1,i2.2,a1,i2.2)') 'Adjusted Yr/Mt/Dy-Hr:Mn = ',Yr,'/',Mt,'/',Dy,'-',Hr,':',Mn
     418           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     419             :     ENDIF
     420             : 
     421             :     ! Return w/ success
     422           0 :     RC = HCO_SUCCESS
     423             : 
     424             :   END SUBROUTINE TimeShift_Apply
     425             : !EOC
     426             : END MODULE HCO_TIMESHIFT_MOD

Generated by: LCOV version 1.14