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