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

          Line data    Source code
       1             : !------------------------------------------------------------------------------
       2             : !                   Harmonized Emissions Component (HEMCO)                    !
       3             : !------------------------------------------------------------------------------
       4             : !BOP
       5             : !
       6             : ! !MODULE: hcoio_util_mod.F90
       7             : !
       8             : ! !DESCRIPTION: Module HCOIO\_Util\_Mod contains utility functions
       9             : ! for use in data processing including file reading, unit conversions,
      10             : ! and regridding.
      11             : !\\
      12             : !\\
      13             : ! !INTERFACE:
      14             : !
      15             : MODULE HCOIO_Util_Mod
      16             : !
      17             : ! !USES:
      18             : !
      19             :   USE HCO_Types_Mod
      20             :   USE HCO_Error_Mod
      21             :   USE HCO_CharTools_Mod
      22             :   USE HCO_State_Mod,       ONLY : Hco_State
      23             : 
      24             :   IMPLICIT NONE
      25             :   PRIVATE
      26             : !
      27             : ! !PUBLIC MEMBER FUNCTIONS:
      28             : !
      29             : #if !defined(ESMF_)
      30             :   PUBLIC :: GET_TIMEIDX
      31             :   PUBLIC :: Check_AvailYMDhm
      32             :   PUBLIC :: prefYMDhm_Adjust
      33             :   PUBLIC :: Set_tIdx2
      34             :   PUBLIC :: IsClosest
      35             :   PUBLIC :: GetIndex2Interp
      36             :   PUBLIC :: GetWeights
      37             :   PUBLIC :: YMDhm2hrs
      38             :   PUBLIC :: Normalize_Area
      39             :   PUBLIC :: SrcFile_Parse
      40             :   PUBLIC :: SigmaMidToEdges
      41             :   PUBLIC :: CheckMissVal
      42             :   PUBLIC :: GetArbDimIndex
      43             : #endif
      44             :   PUBLIC :: HCOIO_ReadOther
      45             :   PUBLIC :: HCOIO_ReadCountryValues
      46             :   PUBLIC :: HCOIO_ReadFromConfig
      47             :   PUBLIC :: GetDataVals
      48             :   PUBLIC :: GetSliceIdx
      49             :   PUBLIC :: FillMaskBox
      50             :   PUBLIC :: ReadMath
      51             : !
      52             : ! !REVISION HISTORY:
      53             : !  12 Jun 2020 - E. Lundgren - Initial version, created from subset of
      54             : !                              hcoio_util_mod.F90
      55             : !  See https://github.com/geoschem/hemco for complete history
      56             : !EOP
      57             : !------------------------------------------------------------------------------
      58             : !BOC
      59             : !
      60             : ! !DEFINED PARAMETERS
      61             : !
      62             :   ! Parameter used for difference testing of floating points
      63             :   REAL(dp), PRIVATE, PARAMETER :: EPSILON = 1.0e-5_dp
      64             : 
      65             : CONTAINS
      66             : !EOC
      67             : #if !defined( ESMF_ )
      68             : !------------------------------------------------------------------------------
      69             : !                   Harmonized Emissions Component (HEMCO)                    !
      70             : !------------------------------------------------------------------------------
      71             : !BOP
      72             : !
      73             : ! !IROUTINE: Get_TimeIdx
      74             : !
      75             : ! !DESCRIPTION: Returns the lower and upper time slice index (tidx1
      76             : ! and tidx2, respectively) to be read. These values are determined
      77             : ! based upon the time slice information extracted from the netCDF file,
      78             : ! the time stamp settings set in the config. file, and the current
      79             : ! simulation date.
      80             : !\\
      81             : !\\
      82             : ! Return arguments wgt1 and wgt2 denote the weights to be given to
      83             : ! the two time slices. This is only of relevance for data that shall
      84             : ! be interpolated between two (not necessarily consecutive) time slices.
      85             : ! In all other cases, the returned weights are negative and will be
      86             : ! ignored.
      87             : !\\
      88             : !\\
      89             : ! Also returns the time slice year and month, as these values may be
      90             : ! used for unit conversion.
      91             : !\\
      92             : !\\
      93             : ! !INTERFACE:
      94             : !
      95           0 :   SUBROUTINE GET_TIMEIDX( HcoState,  Lct,               &
      96             :                           ncLun,     tidx1,    tidx2,   &
      97             :                           wgt1,      wgt2,     oYMDhm,  &
      98             :                           YMDhm,     YMDhm1,   RC,      &
      99             :                           Year )
     100             : !
     101             : ! !USES:
     102             : !
     103             :     USE HCO_Ncdf_Mod,  ONLY : NC_Read_Time_YYYYMMDDhhmm
     104             :     USE HCO_tIdx_Mod,  ONLY : HCO_GetPrefTimeAttr
     105             : !
     106             : ! !INPUT PARAMETERS:
     107             : !
     108             :     TYPE(HCO_State),  POINTER                  :: HcoState  ! HcoState object
     109             :     TYPE(ListCont),   POINTER                  :: Lct       ! List container
     110             :     INTEGER,          INTENT(IN   )            :: ncLun     ! open ncLun
     111             :     INTEGER,          INTENT(IN   ), OPTIONAL  :: Year      ! year to be used
     112             : !
     113             : ! !OUTPUT PARAMETERS:
     114             : !
     115             :     INTEGER,          INTENT(  OUT)            :: tidx1  ! lower time idx
     116             :     INTEGER,          INTENT(  OUT)            :: tidx2  ! upper time idx
     117             :     REAL(sp),         INTENT(  OUT)            :: wgt1   ! weight to tidx1
     118             :     REAL(sp),         INTENT(  OUT)            :: wgt2   ! weight to tidx2
     119             :     REAL(dp),         INTENT(  OUT)            :: oYMDhm ! preferred time slice
     120             :     REAL(dp),         INTENT(  OUT)            :: YMDhm  ! selected time slice
     121             :     REAL(dp),         INTENT(  OUT)            :: YMDhm1 ! 1st time slice in file
     122             : !
     123             : ! !INPUT/OUTPUT PARAMETERS:
     124             : !
     125             :     INTEGER,          INTENT(INOUT)            :: RC
     126             : !
     127             : ! !REVISION HISTORY:
     128             : !  13 Mar 2013 - C. Keller - Initial version
     129             : !  See https://github.com/geoschem/hemco for complete history
     130             : !EOP
     131             : !------------------------------------------------------------------------------
     132             : !BOC
     133             : !
     134             : ! !LOcAL VARIABLES:
     135             : !
     136             :     CHARACTER(LEN=255)    :: MSG, LOC
     137             :     CHARACTER(LEN=1023)   :: MSG_LONG
     138             :     INTEGER               :: tidx1a
     139             :     INTEGER               :: nTime,  T, CNT, NCRC
     140             :     INTEGER               :: prefYr, prefMt, prefDy, prefHr, prefMn
     141             :     INTEGER               :: refYear
     142             :     REAL(dp)              :: origYMDhm, prefYMDhm
     143           0 :     REAL(dp),   POINTER   :: availYMDhm(:)
     144             :     LOGICAL               :: ExitSearch
     145             :     LOGICAL               :: verb
     146             : 
     147             :     !=================================================================
     148             :     ! GET_TIMEIDX begins here
     149             :     !=================================================================
     150             : 
     151             :     ! Initialize
     152           0 :     LOC         = 'GET_TIMEIDX (HCOIO_UTIL_MOD.F90)'
     153             : 
     154             :     ! Officially enter Get_TimeIdx
     155           0 :     CALL HCO_ENTER( HcoState%Config%Err, LOC, RC )
     156           0 :     IF ( RC /= HCO_SUCCESS ) THEN
     157           0 :         CALL HCO_ERROR( 'ERROR 0', RC, THISLOC=LOC )
     158           0 :         RETURN
     159             :     ENDIF
     160           0 :     verb = HCO_IsVerb( HcoState%Config%Err )
     161             : 
     162             :     ! Initialize local variables for safety's sake
     163           0 :     nTime      =  0
     164           0 :     cnt        =  0
     165           0 :     prefYr     =  0
     166           0 :     prefMt     =  0
     167           0 :     prefDy     =  0
     168           0 :     prefHr     =  0
     169           0 :     prefMn     =  0
     170           0 :     refYear    =  0
     171           0 :     origYMDhm  =  0
     172           0 :     prefYMDhm  =  0
     173           0 :     tidx1      =  0
     174           0 :     tidx2      =  0
     175           0 :     tidx1a     =  0
     176           0 :     wgt1       = -1.0_sp
     177           0 :     wgt2       = -1.0_sp
     178           0 :     oYMDhm     =  0.0_dp
     179           0 :     YMDhm      =  0.0_dp
     180           0 :     YMDhm1     =  0.0_dp
     181           0 :     ExitSearch = .FALSE.
     182           0 :     availYMDhm => NULL()
     183             : 
     184             :     ! ----------------------------------------------------------------
     185             :     ! Extract netCDF time slices (YYYYMMDDhhmm)
     186             :     ! ----------------------------------------------------------------
     187             :     CALL NC_READ_TIME_YYYYMMDDhhmm( ncLun, nTime,    availYMDhm,  &
     188           0 :                                     refYear=refYear, RC=NCRC     )
     189           0 :     IF ( NCRC /= 0 ) THEN
     190           0 :        CALL HCO_ERROR( 'NC_READ_TIME_YYYYMMDDhhmm', RC )
     191           0 :        RETURN
     192             :     ENDIF
     193             : 
     194             :     ! Return warning if netCDF reference year prior to 1901: it seems
     195             :     ! like there are some problems with that and the time slices can be
     196             :     ! off by one day!
     197           0 :     IF ( (refYear <= 1900) .AND. (nTime > 0) ) THEN
     198             :        MSG = 'ncdf reference year is prior to 1901 - ' // &
     199           0 :             'time stamps may be wrong!'
     200           0 :        CALL HCO_WARNING ( HcoState%Config%Err, MSG, RC )
     201             :     ENDIF
     202             : 
     203             :     ! verbose mode
     204           0 :     IF ( verb ) THEN
     205           0 :        write(MSG,*) 'Number of time slices found: ', nTime
     206           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     207           0 :        IF ( nTime > 0 ) THEN
     208           0 :           write(MSG,*) 'Time slice range : ', &
     209           0 :                        availYMDhm(1), availYMDhm(nTime)
     210           0 :           CALL HCO_MSG(HcoState%Config%Err,MSG)
     211             :        ENDIF
     212             :     ENDIF
     213             : 
     214             :     ! ----------------------------------------------------------------
     215             :     ! Select time slices to read
     216             :     ! ----------------------------------------------------------------
     217             : 
     218             :     ! ----------------------------------------------------------------
     219             :     ! Get preferred time stamp to read based upon the specs set in the
     220             :     ! config. file.
     221             :     ! This can return value -1 for prefHr, indicating that all
     222             :     ! corresponding time slices shall be read.
     223             :     ! This call will return -1 for all date attributes if the
     224             :     ! simulation date is outside of the data range given in the
     225             :     ! configuration file.
     226             :     ! ----------------------------------------------------------------
     227             :     CALL HCO_GetPrefTimeAttr ( HcoState, Lct, &
     228           0 :                                prefYr, prefMt, prefDy, prefHr, prefMn, RC )
     229           0 :     IF ( RC /= HCO_SUCCESS ) THEN
     230             :        MSG = &
     231           0 :          'Error encountered in HCO_GetPrefTimeAttr for ' // TRIM(Lct%Dct%cName)
     232           0 :        CALL HCO_ERROR( MSG, RC )
     233           0 :        IF ( ASSOCIATED(availYMDhm) ) THEN
     234           0 :           DEALLOCATE(availYMDhm)
     235             :           availYMDhm => NULL()
     236             :        ENDIF
     237           0 :        RETURN
     238             :     ENDIF
     239             : 
     240             :     ! Eventually force preferred year to passed value
     241           0 :     IF ( PRESENT(Year) ) prefYr = Year
     242             : 
     243             :     ! Check if we are outside of provided range
     244           0 :     IF ( prefYr < 0 .OR. prefMt < 0 .OR. prefDy < 0 ) THEN
     245             : 
     246             :        ! This should only happen for 'range' data
     247           0 :        IF ( Lct%Dct%Dta%CycleFlag /= HCO_CFLAG_RANGE ) THEN
     248           0 :           MSG = 'Cannot get preferred datetime for ' // TRIM(Lct%Dct%cName)
     249           0 :           CALL HCO_ERROR( MSG, RC )
     250           0 :           IF ( ASSOCIATED(availYMDhm) ) THEN
     251           0 :              DEALLOCATE(availYMDhm)
     252             :              availYMDhm => NULL()
     253             :           ENDIF
     254           0 :           RETURN
     255             :        ENDIF
     256             : 
     257             :        ! If this part of the code gets executed, the data associated
     258             :        ! with this container shall not be used at the current date.
     259             :        ! To do so, set the time indeces to -1 and leave right here.
     260           0 :        tidx1 = -1
     261           0 :        tidx2 = -1
     262             : 
     263             :        ! Leave w/ success
     264           0 :        CALL HCO_LEAVE( HcoState%Config%Err,  RC )
     265           0 :        RETURN
     266             :     ENDIF
     267             : 
     268             :     ! origYMDhm is the preferred datetime. Store into shadow variable
     269             :     ! prefYMDhm. prefYMDhm may be adjusted if origYMDhm is outside of the
     270             :     ! netCDF datetime range.
     271             :     ! Now put origYMDhm, prefYMDhm in YYYYMMDDhhmm format (bmy, 4/10/17)
     272             :     origYMDhm = ( DBLE(      prefYr      ) * 1.0e8_dp ) + &
     273             :                 ( DBLE(      prefMt      ) * 1.0e6_dp ) + &
     274             :                 ( DBLE(      prefDy      ) * 1.0e4_dp ) + &
     275             :                 ( DBLE( MAX( prefHr, 0 ) ) * 1.0e2_dp ) + &
     276           0 :                 ( DBLE( MAX( prefMn, 0 ) )          )
     277           0 :     prefYMDhm = origYMDhm
     278             : 
     279             :     ! verbose mode
     280           0 :     IF ( verb ) THEN
     281           0 :        write(MSG,'(A30,f14.0)') 'preferred datetime: ', prefYMDhm
     282           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     283             :     ENDIF
     284             : 
     285             :     ! ================================================================
     286             :     ! Case 1: Only one time slice available.
     287             :     ! ================================================================
     288           0 :     IF ( nTime == 1 ) THEN
     289           0 :        tidx1 = 1
     290           0 :        tidx2 = 1
     291             : 
     292             :     ! ================================================================
     293             :     ! Case 2: More than one time slice available. Determine lower
     294             :     ! and upper time slice index from file & HEMCO settings.
     295             :     ! ================================================================
     296           0 :     ELSEIF ( nTime > 1 ) THEN
     297             : 
     298             :        ! Init
     299           0 :        tidx1   = -1
     300           0 :        tidx2   = -1
     301             : 
     302             :        ! -------------------------------------------------------------
     303             :        ! Check if preferred datetime prefYMDhm is within the range
     304             :        ! available time slices, e.g. it falls within the interval
     305             :        ! of availYMDhm. In this case, set tidx1 to the index of the
     306             :        ! closest time slice that is not in the future.
     307             :        ! -------------------------------------------------------------
     308           0 :        CALL Check_AvailYMDhm ( Lct, nTime, availYMDhm, prefYMDhm, tidx1a )
     309             : 
     310             :        ! -------------------------------------------------------------
     311             :        ! Check if we need to continue search. Even if the call above
     312             :        ! returned a time slice, it may be possible to continue looking
     313             :        ! for a better suited time stamp. This is only the case if
     314             :        ! there are discontinuities in the time stamps, e.g. if a file
     315             :        ! contains monthly data for 2005 and 2020. In that case, the
     316             :        ! call above would return the index for Dec 2005 for any
     317             :        ! simulation date between 2005 and 2010 (e.g. July 2010),
     318             :        ! whereas it makes more sense to use July 2005 (and eventually
     319             :        ! interpolate between the July 2005 and July 2020 data).
     320             :        ! The IsClosest command checks if there are any netCDF time
     321             :        ! stamps (prior to the selected one) that are closer to each
     322             :        ! other than the difference between the preferred time stamp
     323             :        ! prefYMDhm and the currently selected time stamp
     324             :        ! availYMDhm(tidx1a). In that case, it continues the search by
     325             :        ! updating prefYMDhm so that it falls within the range of the
     326             :        ! 'high-frequency' interval.
     327             :        ! -------------------------------------------------------------
     328           0 :        ExitSearch = .FALSE.
     329           0 :        IF ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_EXACT ) THEN
     330             :           ExitSearch = .TRUE.
     331           0 :        ELSE IF ( tidx1a > 0 ) THEN
     332           0 :           ExitSearch = IsClosest( prefYMDhm, availYMDhm, nTime, tidx1a )
     333             :        ENDIF
     334             : 
     335             :        ! When using the interpolation flag, use the first or last timestep
     336             :        ! when outside of the available date range
     337           0 :        IF ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_INTER .and. tidx1a < 0 ) THEN
     338           0 :           IF ( prefYMDhm < availYMDhm(1) ) THEN
     339           0 :              tidx1a = 1
     340           0 :           ELSE IF ( prefYMDhm > availYMDhm(nTime) ) THEN
     341           0 :              tidx1a = nTime
     342             :           ENDIF
     343             :        ENDIF
     344             : 
     345             :        ! Do not continue search if data is to be interpolated and is
     346             :        ! not discontinuous (mps, 10/23/19)
     347           0 :        IF ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_INTER .and. &
     348             :             .not. Lct%Dct%Dta%Discontinuous ) THEN
     349             :           ExitSearch = .TRUE.
     350             :        ENDIF
     351             : 
     352             :        ! Write to tidx1 if this is the best match.
     353           0 :        IF ( ExitSearch ) THEN
     354           0 :           tidx1 = tidx1a
     355             : 
     356             :        ! -------------------------------------------------------------
     357             :        ! If search shall be continued, adjust preferred year, then
     358             :        ! month, then day to the closest available year (month, day)
     359             :        ! in the time slices, and check if this is a better match.
     360             :        ! -------------------------------------------------------------
     361             :        ELSE
     362             : 
     363             :           ! Adjust year, month, and day (in this order).
     364           0 :           CNT  = 0
     365             :           DO
     366           0 :              CNT = CNT + 1
     367           0 :              IF ( ExitSearch .OR. CNT > 3 ) EXIT
     368             : 
     369             :              ! Adjust prefYMDhm at the given level (1=Y, 2=M, 3=D)
     370           0 :              CALL prefYMDhm_Adjust ( nTime, availYMDhm, prefYMDhm, CNT, tidx1a )
     371             : 
     372             :              ! verbose mode
     373           0 :              IF ( verb ) THEN
     374           0 :                 write(MSG,'(A30,f14.0)') 'adjusted preferred datetime: ', &
     375           0 :                      prefYMDhm
     376           0 :                 CALL HCO_MSG(HcoState%Config%Err,MSG)
     377             :              ENDIF
     378             : 
     379             :              ! check for time stamp with updated date/time
     380           0 :              CALL Check_AvailYMDhm ( Lct, nTime, availYMDhm, prefYMDhm, tidx1a )
     381             : 
     382             :              ! Can we leave now?
     383           0 :              ExitSearch = IsClosest( prefYMDhm, availYMDhm, nTime, tidx1a )
     384           0 :              IF ( ExitSearch ) tidx1 = tidx1a
     385             : 
     386             :           ENDDO
     387             :        ENDIF
     388             : 
     389             :        ! -------------------------------------------------------------
     390             :        ! If tidx1 still isn't defined, i.e. prefYMDhm is still
     391             :        ! outside the range of availYMDhm, set tidx1 to the closest
     392             :        ! available date. This must be 1 or nTime!
     393             :        ! -------------------------------------------------------------
     394           0 :        IF ( .NOT. ExitSearch ) THEN
     395           0 :           IF ( prefYMDhm < availYMDhm(1) ) THEN
     396           0 :              tidx1 = 1
     397             :           ELSE
     398           0 :              tidx1 = nTime
     399             :           ENDIF
     400             :        ENDIF
     401             : 
     402             :        ! -------------------------------------------------------------
     403             :        ! If we are dealing with 3-hourly or hourly data, select all timesteps
     404             :        ! -------------------------------------------------------------
     405             : 
     406             :        ! Hour flag is -1: wildcard
     407           0 :        IF ( Lct%Dct%Dta%ncHrs(1) == -1 .AND. nTime == 8 ) THEN
     408           0 :           tidx1 = 1
     409           0 :           tidx2 = nTime
     410             : 
     411             :           ! verbose mode
     412           0 :           IF ( verb ) THEN
     413           0 :              WRITE(MSG,*) 'Data is 3-hourly. Entire day will be read.'
     414           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     415             :           ENDIF
     416             :        ENDIF
     417           0 :        IF ( Lct%Dct%Dta%ncHrs(1) == -1 .AND. nTime == 24 ) THEN
     418           0 :           tidx1 = 1
     419           0 :           tidx2 = nTime
     420             : 
     421             :           ! verbose mode
     422           0 :           IF ( verb ) THEN
     423           0 :              WRITE(MSG,*) 'Data is hourly. Entire day will be read.'
     424           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     425             :           ENDIF
     426             :        ENDIF
     427             : 
     428             :        ! -------------------------------------------------------------
     429             :        ! If we are dealing with weekday data, pick the slice to be
     430             :        ! used based on the current day of week.
     431             :        ! The ncDys flag has been set in subroutine HCO_ExtractTime
     432             :        ! (hco_tidx_mod.F90) based upon the time attributes set in the
     433             :        ! configuration file. It can have the following values:
     434             :        ! >0  : specific days are given.
     435             :        ! -1  : wildcard (autodetect)
     436             :        ! -10 : WD (weekday).
     437             :        ! -999: determine from current simulation day.
     438             :        ! For specific days or if determined from the current datetime
     439             :        ! (flags >0 or -999), the weekday is not taken into account.
     440             :        ! If auto-detection is enabled, days are treated as weekday if
     441             :        ! (and only if) there are exactly 7 time slices. Otherwise, they
     442             :        ! are interpreted as 'regular' day data.
     443             :        ! If flag is set to -10, e.g. time attribute is 'WD', the current
     444             :        ! time index is assumed to hold Sunday data, with the following
     445             :        ! six slices being Mon, Tue, ..., Sat. For weekdaily data, all
     446             :        ! seven time slices will be read into memory so that at any given
     447             :        ! time, the local weekday can be taken (weekdaily data is always
     448             :        ! assumed to be in local time).
     449             :        ! -------------------------------------------------------------
     450             : 
     451             :        ! Day flag is -1: wildcard
     452           0 :        IF ( Lct%Dct%Dta%ncDys(1) == -1 .AND. nTime == 7 ) THEN
     453           0 :           tidx1 = 1
     454           0 :           tidx2 = nTime
     455             : 
     456             :           ! Make sure data is treated in local time
     457           0 :           Lct%Dct%Dta%IsLocTime = .TRUE.
     458             : 
     459             :        ! Day flag is -10: WD
     460           0 :        ELSEIF ( Lct%Dct%Dta%ncDys(1) == -10 ) THEN
     461             : 
     462             :           ! There must be at least 7 time slices
     463           0 :           IF ( nTime < 7 ) THEN
     464             :              MSG = 'Data must have exactly 7 time slices '// &
     465           0 :                    'if you set day attribute to WD: '//TRIM(Lct%Dct%cName)
     466           0 :              CALL HCO_ERROR( MSG, RC )
     467           0 :              IF ( ASSOCIATED(availYMDhm) ) THEN
     468           0 :                 DEALLOCATE(availYMDhm)
     469             :                 availYMDhm => NULL()
     470             :              ENDIF
     471           0 :              RETURN
     472             :           ENDIF
     473             : 
     474             :           ! If there are exactly seven time slices, interpret them as
     475             :           ! the seven weekdays.
     476           0 :           IF ( nTime == 7 ) THEN
     477           0 :              tidx1 = 1
     478           0 :              tidx2 = 7
     479             : 
     480             :           ! If there are more than 7 time slices, interpret the current
     481             :           ! selected index as sunday of the current time frame (e.g. sunday
     482             :           ! data of current month), and select the time slice index
     483             :           ! accordingly. This requires that there are at least 6 more time
     484             :           ! slices following the current one.
     485             :           ELSE
     486           0 :              IF ( tidx1 < 0 ) THEN
     487           0 :                 WRITE(MSG,*) 'Cannot get weekday slices for: ', &
     488           0 :                    TRIM(Lct%Dct%cName), '. Cannot find first time slice.'
     489           0 :                 CALL HCO_ERROR( MSG, RC )
     490           0 :                 IF ( ASSOCIATED(availYMDhm) ) THEN
     491           0 :                    DEALLOCATE(availYMDhm)
     492             :                    availYMDhm => NULL()
     493             :                 ENDIF
     494           0 :                 RETURN
     495             :              ENDIF
     496             : 
     497           0 :              IF ( (tidx1+6) > nTime ) THEN
     498           0 :                 WRITE(MSG,*) 'Cannot get weekday for: ',TRIM(Lct%Dct%cName), &
     499           0 :                    '. There are less than 6 additional time slices after ',  &
     500           0 :                    'selected start date ', availYMDhm(tidx1)
     501           0 :                 CALL HCO_ERROR( MSG, RC )
     502           0 :                 IF ( ASSOCIATED(availYMDhm) ) THEN
     503           0 :                    DEALLOCATE(availYMDhm)
     504             :                    availYMDhm => NULL()
     505             :                 ENDIF
     506           0 :                 RETURN
     507             :              ENDIF
     508           0 :              tidx2 = tidx1 + 6
     509             :           ENDIF
     510             : 
     511             :           ! Make sure data is treated in local time
     512           0 :           Lct%Dct%Dta%IsLocTime = .TRUE.
     513             : 
     514             :        ENDIF
     515             : 
     516             :        ! -------------------------------------------------------------
     517             :        ! Now need to set upper time slice index tidx2. This index
     518             :        ! is only different from tidx1 if:
     519             :        ! (1) We interpolate between two time slices, i.e. TimeCycle
     520             :        !     attribute is set to 'I'. In this case, we simply pick
     521             :        !     the next higher time slice index and calculate the
     522             :        !     weights for time1 and time2 based on the current time.
     523             :        ! (2) Multiple hourly slices are read (--> prefHr = -1 or -10,
     524             :        !     e.g. hour attribute in config. file was set to wildcard
     525             :        !     character or data is in local hours). In this case,
     526             :        !     check if there are multiple time slices for the selected
     527             :        !     date (y/m/d).
     528             :        ! tidx2 has already been set to proper value above if it's
     529             :        ! weekday data.
     530             :        ! -------------------------------------------------------------
     531           0 :        IF ( tidx2 < 0 ) THEN
     532             : 
     533             :           ! Interpolate between dates
     534           0 :           IF ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_INTER ) THEN
     535             : 
     536             :              CALL GetIndex2Interp( HcoState,   Lct,       nTime,      &
     537             :                                    availYMDhm, prefYMDhm, origYMDhm,  &
     538             :                                    tidx1,      tidx2,     wgt1,       &
     539           0 :                                    wgt2,       RC                   )
     540           0 :              IF ( RC /= HCO_SUCCESS ) THEN
     541             :                 MSG = 'Error encountered in GetIndex2Interp for: '        // &
     542           0 :                      TRIM(Lct%Dct%Cname)
     543           0 :                 CALL HCO_ERROR( MSG, RC )
     544           0 :                 IF ( ASSOCIATED(availYMDhm) ) THEN
     545           0 :                    DEALLOCATE(availYMDhm)
     546             :                    availYMDhm => NULL()
     547             :                 ENDIF
     548           0 :                 RETURN
     549             :              ENDIF
     550             : 
     551             :           ! Check for multiple hourly data
     552           0 :           ELSEIF ( tidx1 > 0 .AND. prefHr < 0 ) THEN
     553           0 :              CALL SET_TIDX2 ( nTime, availYMDhm, tidx1, tidx2 )
     554             : 
     555             :              ! Denote as local time if necessary
     556           0 :              IF ( Lct%Dct%Dta%ncHrs(1) == -10 ) THEN
     557           0 :                 Lct%Dct%Dta%IsLocTime = .TRUE.
     558             :              ENDIF
     559             :           ELSE
     560           0 :              tidx2 = tidx1
     561             :           ENDIF
     562             :        ENDIF
     563             : 
     564             :     ! ================================================================
     565             :     ! Case 3: No time slice available. Set both indeces to zero. Data
     566             :     ! with no time stamp must have CycleFlag 'Cycling'.
     567             :     ! ================================================================
     568             :     ELSE
     569           0 :        IF ( Lct%Dct%Dta%CycleFlag /= HCO_CFLAG_CYCLE ) THEN
     570             :           MSG = 'Field has no time/date variable - cycle flag must' // &
     571             :                 'be set to `C` in the HEMCO configuration file:'    // &
     572           0 :                 TRIM(Lct%Dct%cName)
     573           0 :           CALL HCO_ERROR( MSG, RC )
     574           0 :           IF ( ASSOCIATED(availYMDhm) ) THEN
     575           0 :              DEALLOCATE(availYMDhm)
     576             :              availYMDhm => NULL()
     577             :           ENDIF
     578           0 :           RETURN
     579             :        ENDIF
     580             : 
     581           0 :        tidx1 = 0
     582           0 :        tidx2 = 0
     583             :     ENDIF
     584             : 
     585             :     !-----------------------------------------------------------------
     586             :     ! Sanity check: if CycleFlag is set to 'Exact', the file time stamp
     587             :     ! must exactly match the current time.
     588             :     !-----------------------------------------------------------------
     589           0 :     IF ( (Lct%Dct%Dta%CycleFlag == HCO_CFLAG_EXACT) .AND. (tidx1 > 0) ) THEN
     590           0 :        IF ( availYMDhm(tidx1) /= prefYMDhm ) THEN
     591           0 :           tidx1 = -1
     592           0 :           tidx2 = -1
     593             :        ENDIF
     594             :     ENDIF
     595             : 
     596             :     !-----------------------------------------------------------------
     597             :     ! If multiple time slices are read, extract time interval between
     598             :     ! time slices in memory (in hours). This is to make sure that the
     599             :     ! cycling between the slices will be done at the correct rate
     600             :     ! (e.g. every hour, every 3 hours, ...).
     601             :     !-----------------------------------------------------------------
     602           0 :     IF ( (tidx2>tidx1) .AND. (Lct%Dct%Dta%CycleFlag/=HCO_CFLAG_INTER) ) THEN
     603           0 :        Lct%Dct%Dta%DeltaT = YMDhm2hrs( availYMDhm(tidx1+1) - availYMDhm(tidx1) )
     604             :     ELSE
     605           0 :        Lct%Dct%Dta%DeltaT = 0
     606             :     ENDIF
     607             : 
     608             :     ! verbose mode
     609           0 :     IF ( verb ) THEN
     610           0 :        WRITE(MSG,'(A30,I14)') 'selected tidx1: ', tidx1
     611           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     612           0 :        IF ( tidx1 > 0 ) THEN
     613           0 :           WRITE(MSG,'(A30,f14.0)') 'corresponding datetime 1: ', &
     614           0 :                availYMDhm(tidx1)
     615           0 :           CALL HCO_MSG(HcoState%Config%Err,MSG)
     616           0 :           IF ( wgt1 >= 0.0_sp ) THEN
     617           0 :              WRITE(MSG,*) 'weight1: ', wgt1
     618           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     619             :           ENDIF
     620             :        ENDIF
     621             : 
     622           0 :        IF ( (tidx2 /= tidx1) ) THEN
     623           0 :           WRITE(MSG,'(A30,I14)') 'selected tidx2: ', tidx2
     624           0 :           CALL HCO_MSG(HcoState%Config%Err,MSG)
     625           0 :           WRITE(MSG,'(A30,f14.0)') 'corresponding datetime 2: ', &
     626           0 :                availYMDhm(tidx2)
     627           0 :           CALL HCO_MSG(HcoState%Config%Err,MSG)
     628           0 :           IF ( wgt1 >= 0.0_sp ) THEN
     629           0 :              WRITE(MSG,*) 'weight2: ', wgt2
     630           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     631             :           ENDIF
     632             :        ENDIF
     633             : 
     634           0 :        WRITE(MSG,'(A30,I14)') 'assigned delta t [h]: ', Lct%Dct%Dta%DeltaT
     635           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     636           0 :        WRITE(MSG,*) 'local time? ', Lct%Dct%Dta%IsLocTime
     637           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
     638             :     ENDIF
     639             : 
     640             :     ! ----------------------------------------------------------------
     641             :     ! TODO: set time brackets
     642             :     ! --> In future, we may want to set time brackets denoting the
     643             :     ! previous and next time slice available in the netCDF file. This
     644             :     ! may become useful for temporal interpolations and more efficient
     645             :     ! data update calls (only update if new time slice is available).
     646             :     ! ----------------------------------------------------------------
     647             : 
     648             :     !-----------------------------------------------------------------
     649             :     ! Prepare output, cleanup and leave
     650             :     !-----------------------------------------------------------------
     651             : 
     652             :     ! ncYr and ncMt are the year and month fo the time slice to be
     653             :     ! used. These values may be required to convert units to 'per
     654             :     ! seconds'.
     655           0 :     IF ( tidx1 > 0 ) THEN
     656           0 :        YMDhm  = availYMDhm(tidx1)
     657           0 :        YMDhm1 = availYMDhm(1)
     658           0 :        oYMDhm = origYMDhm
     659             :     ENDIF
     660             : 
     661             :     ! Deallocate and nullify the pointer
     662           0 :     IF ( ASSOCIATED(availYMDhm) ) THEN
     663           0 :        DEALLOCATE(availYMDhm)
     664             :        availYMDhm => NULL()
     665             :     ENDIF
     666             : 
     667             :     ! Return w/ success
     668           0 :     CALL HCO_LEAVE ( HcoState%Config%Err,  RC )
     669             : 
     670           0 :   END SUBROUTINE GET_TIMEIDX
     671             : !EOC
     672             : !------------------------------------------------------------------------------
     673             : !                   Harmonized Emissions Component (HEMCO)                    !
     674             : !------------------------------------------------------------------------------
     675             : !BOP
     676             : !
     677             : ! !IROUTINE: Check_AvailYMDhm
     678             : !
     679             : ! !DESCRIPTION: Checks if prefYMDhm is within the range of availYMDhm
     680             : ! and returns the location of the closest vector element that is in
     681             : ! the past (--> tidx1). tidx1 is set to -1 otherwise.
     682             : !\\
     683             : !\\
     684             : ! !INTERFACE:
     685             : !
     686           0 :   SUBROUTINE Check_AvailYMDhm( Lct, N, availYMDhm, prefYMDhm, tidx1 )
     687             : !
     688             : ! !INPUT PARAMETERS:
     689             : !
     690             :     TYPE(ListCont),   POINTER      :: Lct
     691             :     INTEGER,          INTENT(IN)   :: N
     692             :     REAL(dp),         INTENT(IN)   :: availYMDhm(N)
     693             :     REAL(dp),         INTENT(IN)   :: prefYMDhm
     694             : !
     695             : ! !OUTPUT PARAMETERS:
     696             : !
     697             :     INTEGER,          INTENT(OUT)  :: tidx1
     698             : !
     699             : ! !REVISION HISTORY:
     700             : !  13 Mar 2013 - C. Keller   - Initial version
     701             : !  See https://github.com/geoschem/hemco for complete history
     702             : !EOP
     703             : !------------------------------------------------------------------------------
     704             : !BOC
     705             : !
     706             : ! !LOCAL VARIABLES:
     707             : !
     708             :     INTEGER :: I, nTime
     709             : 
     710             :     !=================================================================
     711             :     ! Check_availYMDhm begins here
     712             :     !=================================================================
     713             : 
     714             :     ! Init
     715           0 :     tidx1 = -1
     716             : 
     717             :     ! Return if preferred datetime not within the vector range
     718           0 :     IF ( prefYMDhm < availYMDhm(1) .OR. prefYMDhm > availYMDhm(N) ) RETURN
     719             : 
     720             :     ! To avoid out-of-bounds error in the loop below:
     721             :     ! (1) For interpolated data, the upper loop limit should be N;
     722             :     ! (2) Otherwise, the upper loop limit should be N-1.
     723             :     ! (bmy, 4/28/21)
     724           0 :     nTime = N - 1
     725           0 :     IF ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_INTER ) nTime = N
     726             : 
     727             :     ! Get closest index that is not in the future
     728           0 :     DO I = 1, nTime
     729             : 
     730             :        ! NOTE: Epsilon test is more robust than an equality test
     731             :        ! for double-precision variables (bmy, 4/11/17)
     732           0 :        IF ( ABS( availYMDhm(I) - prefYMDhm ) < EPSILON ) THEN
     733           0 :           tidx1 = I
     734           0 :           EXIT
     735             :        ENDIF
     736             : 
     737             :        ! Check if next time slice is in the future, in which case the
     738             :        ! current slice is selected. Don't do this for a CycleFlag of
     739             :        ! 3 (==> exact match).
     740           0 :        IF ( (availYMDhm(I+1)       >  prefYMDhm        ) .AND. &
     741           0 :             (Lct%Dct%Dta%CycleFlag /= HCO_CFLAG_EXACT) ) THEN
     742           0 :           tidx1 = I
     743           0 :           EXIT
     744             :        ENDIF
     745             :     ENDDO
     746             : 
     747             :   END SUBROUTINE Check_AvailYMDhm
     748             : !EOC
     749             : !------------------------------------------------------------------------------
     750             : !                   Harmonized Emissions Component (HEMCO)                    !
     751             : !------------------------------------------------------------------------------
     752             : !BOP
     753             : !
     754             : ! !IROUTINE: prefYMDhm_Adjust
     755             : !
     756             : ! !DESCRIPTION: Adjusts prefYMDhm to the closest available time attribute. Can
     757             : ! be adjusted for year (level=1), month (level=2), or day (level=3).
     758             : !\\
     759             : !\\
     760             : ! !INTERFACE:
     761             : !
     762           0 :   SUBROUTINE prefYMDhm_Adjust( N, availYMDhm, prefYMDhm, level, tidx1 )
     763             : !
     764             : ! !INPUT PARAMETERS:
     765             : !
     766             :     INTEGER   , INTENT(IN)     :: N
     767             :     REAL(dp)  , INTENT(IN)     :: availYMDhm(N)
     768             :     INTEGER   , INTENT(IN)     :: level
     769             :     INTEGER   , INTENT(IN)     :: tidx1
     770             : !
     771             : ! !INPUT/OUTPUT PARAMETERS:
     772             : !
     773             :     REAL(dp)  , INTENT(INOUT)  :: prefYMDhm
     774             : !
     775             : ! !REVISION HISTORY:
     776             : !  13 Mar 2013 - C. Keller   - Initial version
     777             : !  See https://github.com/geoschem/hemco for complete history
     778             : !EOP
     779             : !------------------------------------------------------------------------------
     780             : !BOC
     781             : !
     782             : ! !LOCAL VARIABLES:
     783             : !
     784             :     ! Scalars
     785             :     INTEGER          :: I, IMIN, IMAX
     786             :     REAL(dp)         :: origYr,  origMt,  origDy, origHr, origMi
     787             :     REAL(dp)         :: refAttr, tmpAttr, newAttr
     788             :     REAL(dp)         :: iDiff,   minDiff
     789             :     REAL(dp)         :: modVal
     790             :     REAL(dp)         :: div
     791             : 
     792             :     !=================================================================
     793             :     ! prefYMDhm_Adjust begins here!
     794             :     !=================================================================
     795             : 
     796             :     ! Get original Yr, Mt, Day, Hr, Mi
     797             :     ! Time values are now in YYYYMMDDhhmm format (bmy, 4/11/17)
     798           0 :     origYr = FLOOR( MOD( prefYMDhm, 1.0e12_dp ) / 1.0e8_dp )
     799           0 :     origMt = FLOOR( MOD( prefYMDhm, 1.0e8_dp  ) / 1.0e6_dp )
     800           0 :     origDy = FLOOR( MOD( prefYMDhm, 1.0e6_dp  ) / 1.0e4_dp )
     801           0 :     origHr = FLOOR( MOD( prefYMDhm, 1.0e4_dp  ) / 1.0e2_dp )
     802           0 :     origMi = FLOOR( MOD( prefYMDhm, 1.0e2_dp  )            )
     803             : 
     804             :     ! Extract new attribute from availYMDhm and insert into prefYMDhm. Pick
     805             :     ! closest available value.
     806           0 :     SELECT CASE ( level )
     807             :        ! --- Year
     808             :        CASE ( 1 )
     809             :           modVal  = 1.0e12_dp
     810             :           div     = 1.0e8_dp
     811           0 :           refAttr = origYr
     812             : 
     813             :        ! --- Month
     814             :        CASE ( 2 )
     815           0 :           modVal  = 1.0e8_dp
     816           0 :           div     = 1.0e6_dp
     817           0 :           refAttr = origMt
     818             : 
     819             :        ! --- Day
     820             :        CASE ( 3 )
     821           0 :           modVal  = 1.0e6_dp
     822           0 :           div     = 1.0e4_dp
     823           0 :           refAttr = origMt
     824             : 
     825             :        ! --- Hour
     826             :        CASE ( 4 )
     827           0 :           modval  = 1.0e4_dp
     828           0 :           div     = 1.0e2_dp
     829           0 :           refAttr = origHr
     830             : 
     831             :        ! --- Minute
     832             :        CASE ( 5 )
     833           0 :           modVal  = 1.0e2_dp
     834           0 :           div     = 1.0_dp
     835           0 :           refAttr = origMi
     836             : 
     837             :        CASE DEFAULT
     838           0 :           RETURN
     839             :     END SELECT
     840             : 
     841             :     ! Maximum loop number:
     842             :     ! If tidx1 is already set, only search values in the past.
     843           0 :     IF ( tidx1 > 0 ) THEN
     844             :        IMIN = 1
     845             :        IMAX = tidx1
     846             : 
     847             :     ! If tidx1 is not yet set, prefYMDhm must be outside the range of
     848             :     ! availYMDhm. Pick only the closest available time stamp.
     849             :     ELSE
     850           0 :        IF ( prefYMDhm > availYMDhm(1) ) THEN
     851           0 :           IMIN = N
     852           0 :           IMAX = N
     853             :        ELSE
     854             :           IMIN = 1
     855             :           IMAX = 1
     856             :        ENDIF
     857             :     ENDIF
     858             : 
     859             :     ! Select current minimum value
     860           0 :     minDiff = 10000000000000000.0_dp
     861           0 :     newAttr = -1d0
     862           0 :     DO I = IMIN, IMAX
     863           0 :        tmpAttr = FLOOR( MOD(availYMDhm(I),modVal) / div )
     864           0 :        iDiff   = ABS( tmpAttr - refAttr )
     865           0 :        IF ( iDiff < minDiff ) THEN
     866           0 :           newAttr = tmpAttr
     867           0 :           minDiff = iDiff
     868             :        ENDIF
     869             :     ENDDO
     870             : 
     871             :     ! Just reuse current value if no better value could be found
     872           0 :     IF ( newAttr < 0 ) THEN
     873           0 :        newAttr = refAttr
     874             :     ENDIF
     875             : 
     876             :     ! Update variable
     877             :     ! --- Year
     878           0 :     IF ( level == 1 ) THEN
     879             :        prefYMDhm = ( newAttr * 1.0e8_dp ) + &
     880             :                    ( origMt  * 1.0e6_dp ) + &
     881             :                    ( origDy  * 1.0e4_dp ) + &
     882             :                    ( origHr  * 1.0e2_dp ) + &
     883           0 :                    ( origMi          )
     884             : 
     885             :     ! --- Month
     886           0 :     ELSEIF ( level == 2 ) THEN
     887             :        prefYMDhm = ( origYr  * 1.0e8_dp ) + &
     888             :                    ( newAttr * 1.0e6_dp ) + &
     889             :                    ( origDy  * 1.0e4_dp ) + &
     890             :                    ( origHr  * 1.0e2_dp ) + &
     891           0 :                    ( origMi             )
     892             : 
     893             :     ! --- Day
     894           0 :     ELSEIF ( level == 3 ) THEN
     895             :        prefYMDhm = ( origYr  * 1.0e8_dp  ) + &
     896             :                    ( origMt  * 1.0e6_dp  ) + &
     897             :                    ( newAttr * 1.0e4_dp  ) + &
     898             :                    ( origHr  * 1.0e2_dp  ) + &
     899           0 :                    ( origMi              )
     900             : 
     901             :     ! --- Hour
     902           0 :     ELSEIF ( level == 4 ) THEN
     903             :        prefYMDhm = ( origYr  * 1.0e8_dp  ) + &
     904             :                    ( origMt  * 1.0e6_dp  ) + &
     905             :                    ( origDy  * 1.0e4_dp  ) + &
     906             :                    ( newAttr * 1.0e2_dp  ) + &
     907           0 :                    ( origMi              )
     908             :     ! --- Minute
     909           0 :     ELSEIF ( level == 5 ) THEN
     910             :        prefYMDhm = ( origYr  * 1.0e8_dp  ) + &
     911             :                    ( origMt  * 1.0e6_dp  ) + &
     912             :                    ( origDy  * 1.0e4_dp  ) + &
     913             :                    ( origHr  * 1.0e2_dp  ) + &
     914           0 :                    ( newAttr             )
     915             : 
     916             :     ENDIF
     917             : 
     918             :   END SUBROUTINE prefYMDhm_Adjust
     919             : !EOC
     920             : !------------------------------------------------------------------------------
     921             : !                   Harmonized Emissions Component (HEMCO)                    !
     922             : !------------------------------------------------------------------------------
     923             : !BOP
     924             : !
     925             : ! !IROUTINE: Set_tIdx2
     926             : !
     927             : ! !DESCRIPTION: sets the upper time slice index by selecting the range
     928             : ! of all elements in availYMDhm with the same date (year,month,day) as
     929             : ! availYMDh(tidx1).
     930             : !\\
     931             : !\\
     932             : ! !INTERFACE:
     933             : !
     934           0 :   SUBROUTINE Set_tIdx2( N, availYMDhm, tidx1, tidx2 )
     935             : !
     936             : ! !INPUT PARAMETERS:
     937             : !
     938             :     INTEGER,  INTENT(IN)  :: N               ! Number of times
     939             :     REAL(dp), INTENT(IN)  :: availYMDhm(N)   ! Time stamp vector
     940             :     INTEGER,  INTENT(IN)  :: tidx1           ! Lower time slice index
     941             : !
     942             : ! !INPUT/OUTPUT PARAMETERS:
     943             : !
     944             :     INTEGER,  INTENT(OUT) :: tidx2           ! Upper time slice index
     945             : !
     946             : ! !REVISION HISTORY:
     947             : !  13 Mar 2013 - C. Keller   - Initial version
     948             : !  See https://github.com/geoschem/hemco for complete history
     949             : !EOP
     950             : !------------------------------------------------------------------------------
     951             : !BOC
     952             : !
     953             : ! !LOCAL VARIABLES:
     954             : !
     955             :     INTEGER :: YMD, I, IYMD
     956             : 
     957             :     !=================================================================
     958             :     ! SET_TIDX2 begins here!
     959             :     !=================================================================
     960             : 
     961             :     ! Init
     962           0 :     tidx2 = tidx1
     963             : 
     964             :     ! Sanity check
     965           0 :     IF ( tidx1 == N ) RETURN
     966             : 
     967             :     ! Get wanted YMD
     968           0 :     YMD = floor(availYMDhm(tidx1) / 1.0e4_dp)
     969             : 
     970             :     ! See how many more tile slices with the same YMD exist from index
     971             :     ! tidx1 onwards.
     972           0 :     DO I = tidx1, N
     973           0 :        iYMD = floor(availYMDhm(I) / 1.0e4_dp)
     974           0 :        IF ( iYMD == YMD ) THEN
     975           0 :           tidx2 = I
     976           0 :        ELSEIF ( iYMD > YMD ) THEN
     977             :           EXIT
     978             :        ENDIF
     979             :     ENDDO
     980             : 
     981             :   END SUBROUTINE Set_tIdx2
     982             : !EOC
     983             : !------------------------------------------------------------------------------
     984             : !                   Harmonized Emissions Component (HEMCO)                    !
     985             : !------------------------------------------------------------------------------
     986             : !BOP
     987             : !
     988             : ! !IROUTINE: IsClosest
     989             : !
     990             : ! !DESCRIPTION: function IsClosest returns true if the selected time index
     991             : ! is the 'closest' one. It is defined as being closest if:
     992             : ! (a) the currently selected index exactly matches the preferred one.
     993             : ! (b) the time gap between the preferred time stamp and the currently selected
     994             : ! index is at least as small as any other gap of consecutive prior time stamps.
     995             : !\\
     996             : !\\
     997             : ! !INTERFACE:
     998             : !
     999           0 :   FUNCTION IsClosest ( prefYMDhm, availYMDhm, nTime, ctidx1 ) RESULT ( Closest )
    1000             : !
    1001             : ! !INPUT PARAMETERS:
    1002             : !
    1003             :     INTEGER,    INTENT(IN)  :: nTime
    1004             :     REAL(dp),   INTENT(IN)  :: prefYMDhm
    1005             :     REAL(dp),   INTENT(IN)  :: availYMDhm(nTime)
    1006             :     INTEGER,    INTENT(IN)  :: ctidx1
    1007             : !
    1008             : ! !OUTPUT PARAMETERS:
    1009             : !
    1010             :     LOGICAL              :: Closest
    1011             : !
    1012             : ! !REVISION HISTORY:
    1013             : !  03 Mar 2015 - C. Keller   - Initial version
    1014             : !  See https://github.com/geoschem/hemco for complete history
    1015             : !EOP
    1016             : !------------------------------------------------------------------------------
    1017             : !BOC
    1018             : !
    1019             : ! !LOCAL VARIABLES:
    1020             : !
    1021             :     INTEGER :: N
    1022             :     INTEGER :: diff, idiff
    1023             : 
    1024             :     !=================================================================
    1025             :     ! IsClosest begins here!
    1026             :     !=================================================================
    1027             : 
    1028             :     ! Init
    1029           0 :     Closest = .TRUE.
    1030             : 
    1031             :     ! It's not closest if index is not defined
    1032           0 :     IF ( ctidx1 <= 0 ) THEN
    1033           0 :        Closest = .FALSE.
    1034             :        RETURN
    1035             :     ENDIF
    1036             : 
    1037             :     ! It's closest if it is the first index
    1038           0 :     IF ( ctidx1 == 1 ) RETURN
    1039             : 
    1040             :     ! It's closest if it matches date exactly
    1041             :     ! NOTE: Epsilon test is more robust than an equality test
    1042             :     ! for double-precision variables (bmy, 4/11/17)
    1043           0 :     IF ( ABS( availYMDhm(ctidx1) - prefYMDhm ) < EPSILON ) RETURN
    1044             : 
    1045             :     ! It's closest if current select one is in the future
    1046           0 :     IF ( availYMDhm(ctidx1) > prefYMDhm ) RETURN
    1047             : 
    1048             :     ! Check if any of the time stamps in the past have closer intervals
    1049             :     ! than the current select time stamp to it's previous one
    1050           0 :     diff = prefYMDhm - availYMDhm(ctidx1)
    1051           0 :     DO N = 2, ctidx1
    1052           0 :        idiff = availYMDhm(N) - availYMDhm(N-1)
    1053           0 :        IF ( idiff < diff ) THEN
    1054           0 :           Closest = .FALSE.
    1055             :           RETURN
    1056             :        ENDIF
    1057             :     ENDDO
    1058             : 
    1059             :   END FUNCTION IsClosest
    1060             : !EOC
    1061             : !------------------------------------------------------------------------------
    1062             : !                   Harmonized Emissions Component (HEMCO)                    !
    1063             : !------------------------------------------------------------------------------
    1064             : !BOP
    1065             : !
    1066             : ! !IROUTINE: GetIndex2Interp
    1067             : !
    1068             : ! !DESCRIPTION: GetIndex2Interp
    1069             : !\\
    1070             : !\\
    1071             : ! !INTERFACE:
    1072             : !
    1073           0 :   SUBROUTINE GetIndex2Interp ( HcoState,  Lct,                   &
    1074           0 :                                nTime,     availYMDhm,            &
    1075             :                                prefYMDhm, origYMDhm,  tidx1,     &
    1076             :                                tidx2,     wgt1,       wgt2,  RC   )
    1077             : !
    1078             : ! !INPUT PARAMETERS:
    1079             : !
    1080             :     TYPE(HCO_State),  POINTER       :: HcoState
    1081             :     TYPE(ListCont),   POINTER       :: Lct
    1082             :     INTEGER,          INTENT(IN)    :: nTime
    1083             :     REAL(dp),         INTENT(IN)    :: availYMDhm(nTime)
    1084             :     REAL(dp),         INTENT(IN)    :: prefYMDhm
    1085             :     REAL(dp),         INTENT(IN)    :: origYMDhm
    1086             :     INTEGER,          INTENT(IN)    :: tidx1
    1087             : !
    1088             : ! !OUTPUT PARAMETERS:
    1089             : !
    1090             :     INTEGER,          INTENT(OUT)   :: tidx2
    1091             : !
    1092             : ! !INPUT/OUTPUT PARAMETERS:
    1093             : !
    1094             :     REAL(sp),         INTENT(INOUT) :: wgt1
    1095             :     REAL(sp),         INTENT(INOUT) :: wgt2
    1096             :     INTEGER,          INTENT(INOUT) :: RC
    1097             : !
    1098             : ! !REVISION HISTORY:
    1099             : !  02 Mar 2015 - C. Keller   - Initial version
    1100             : !  See https://github.com/geoschem/hemco for complete history
    1101             : !EOP
    1102             : !------------------------------------------------------------------------------
    1103             : !BOC
    1104             : !
    1105             : ! !LOCAL VARIABLES:
    1106             : !
    1107             :     ! Scalars
    1108             :     INTEGER             :: I
    1109             :     REAL(dp)            :: tmpYMDhm
    1110             :     LOGICAL             :: verb
    1111             : 
    1112             :     ! Strings
    1113             :     CHARACTER(LEN=255)  :: MSG
    1114             :     CHARACTER(LEN=255)  :: LOC = 'GetIndex2Interp (hcoio_util_mod.F90)'
    1115             : 
    1116             :     !=================================================================
    1117             :     ! GetIndex2Interp begins here
    1118             :     !=================================================================
    1119             : 
    1120             :     ! Verbose mode?
    1121             :     verb = HCO_IsVerb( HcoState%Config%Err )
    1122             : 
    1123             :     ! If the originally wanted datetime was below the available data
    1124             :     ! range, set all weights to the first index.
    1125           0 :     IF ( origYMDhm <= availYMDhm(1) ) THEN
    1126           0 :        tidx2 = tidx1
    1127           0 :        wgt1  = 1.0_sp
    1128           0 :        wgt2  = 0.0_sp
    1129             : 
    1130             :     ! If the originally wanted datetime is beyond the available data
    1131             :     ! range, set tidx2 to tidx1 but leave weights in their original
    1132             :     ! values (-1.0). The reason is that we will attempt to interpolate
    1133             :     ! between a second file, which is only done if the weights are
    1134             :     ! negative.
    1135           0 :     ELSEIF ( origYMDhm >= availYMDhm(nTime) ) THEN
    1136           0 :        tidx2 = tidx1
    1137             : 
    1138             :     ! No interpolation needed if there is a time slices that exactly
    1139             :     ! matches the (originally) preferred datetime.
    1140             :     ! NOTE: An Epsilon test is more robust than an equality test
    1141             :     ! for double-precision variables (bmy, 4/11/17)
    1142           0 :     ELSEIF ( ABS( origYMDhm - availYMDhm(tidx1) ) < EPSILON ) THEN
    1143           0 :        tidx2 = tidx1
    1144           0 :        wgt1  = 1.0_sp
    1145           0 :        wgt2  = 0.0_sp
    1146             : 
    1147             :     ! If we are inside the data range but none of the time slices
    1148             :     ! matches the preferred datetime, get the second time slices that
    1149             :     ! shall be used for data interpolation. This not necessarily needs
    1150             :     ! to be the consecutive time slice. For instance, imagine a data
    1151             :     ! set that contains montlhly data for years 2005 and 2010. For
    1152             :     ! Feb 2007, we would want to interpolate between Feb 2005 and Feb
    1153             :     ! 2010 data. The index tidx1 already points to Feb 2005, but the
    1154             :     ! upper index tidx2 needs to be set accordingly.
    1155             :     ELSE
    1156             : 
    1157             :        ! Init
    1158           0 :        tidx2 = -1
    1159             : 
    1160             :        ! Search for a time slice in the future that has the same
    1161             :        ! month/day/hour as currently selected time slice.
    1162             :        tmpYMDhm = availYMDhm(tidx1)
    1163             :        DO
    1164             :           ! Increase by one year
    1165           0 :           tmpYMDhm = tmpYMDhm + 1.0e8_dp
    1166             : 
    1167             :           ! Exit if we are beyond available dates
    1168           0 :           IF ( tmpYMDhm > availYMDhm(nTime) ) EXIT
    1169             : 
    1170             :           ! Check if there is a time slice with that date
    1171           0 :           DO I = tidx1,nTime
    1172           0 :              IF ( tmpYMDhm == availYMDhm(I) ) THEN
    1173           0 :                 tidx2 = I
    1174           0 :                 EXIT
    1175             :              ENDIF
    1176             :           ENDDO
    1177           0 :           IF ( tidx2 > 0 ) EXIT
    1178             :        ENDDO
    1179             : 
    1180             :        ! Repeat above but now only modify day
    1181           0 :        IF ( tidx2 < 0 ) THEN
    1182             :           tmpYMDhm = availYMDhm(tidx1)
    1183             :           DO
    1184             :              ! Increase by one day
    1185           0 :              tmpYMDhm = tmpYMDhm + 1.0e4_dp
    1186             : 
    1187             :              ! Exit if we are beyond available dates
    1188           0 :              IF ( tmpYMDhm > availYMDhm(nTime) ) EXIT
    1189             : 
    1190             :              ! Check if there is a time slice with that date
    1191           0 :              DO I = tidx1,nTime
    1192           0 :                 IF ( tmpYMDhm == availYMDhm(I) ) THEN
    1193           0 :                    tidx2 = I
    1194           0 :                    EXIT
    1195             :                 ENDIF
    1196             :              ENDDO
    1197           0 :              IF ( tidx2 > 0 ) EXIT
    1198             :           ENDDO
    1199             :        ENDIF
    1200             : 
    1201             :        ! If all of those tests failed, simply get the next time
    1202             :        ! slice.
    1203           0 :        IF ( tidx2 < 0 ) THEN
    1204           0 :           tidx2 = tidx1 + 1
    1205             : 
    1206             :           ! Make sure that tidx2 does not exceed nTime, which is
    1207             :           ! the number of time slices in the file. This can cause
    1208             :           ! an out-of-bounds error. (bmy, 3/7/19)
    1209           0 :           IF ( tidx2 > nTime ) tidx2 = nTime
    1210             : 
    1211             :           ! Prompt warning
    1212           0 :           WRITE(MSG,*) 'Having problems in finding the next time slice ', &
    1213           0 :                 'to interpolate from, just take the next available ',     &
    1214           0 :                 'slice. Interpolation will be performed from ',           &
    1215           0 :                 availYMDhm(tidx1), ' to ', availYMDhm(tidx2), '. Data ',    &
    1216           0 :                 'container: ', TRIM(Lct%Dct%cName)
    1217           0 :           CALL HCO_WARNING(HcoState%Config%Err, MSG, RC, THISLOC=LOC)
    1218             :        ENDIF
    1219             : 
    1220             :        ! Calculate weights wgt1 and wgt2 to be given to slice 1 and
    1221             :        ! slice2, respectively.
    1222           0 :        CALL GetWeights ( availYMDhm(tidx1), availYMDhm(tidx2), origYMDhm, &
    1223           0 :                          wgt1, wgt2 )
    1224             : 
    1225             :     ENDIF
    1226             : 
    1227             :     ! Return w/ success
    1228           0 :     RC = HCO_SUCCESS
    1229             : 
    1230           0 :   END SUBROUTINE GetIndex2Interp
    1231             : !EOC
    1232             : !------------------------------------------------------------------------------
    1233             : !                   Harmonized Emissions Component (HEMCO)                    !
    1234             : !------------------------------------------------------------------------------
    1235             : !BOP
    1236             : !
    1237             : ! !IROUTINE: GetWeights
    1238             : !
    1239             : ! !DESCRIPTION: Helper function to get the interpolation weights between
    1240             : ! two datetime intervals (int1, int2) and for a given time cur.
    1241             : !\\
    1242             : !\\
    1243             : ! !INTERFACE:
    1244             : !
    1245           0 :   SUBROUTINE GetWeights ( int1, int2, cur, wgt1, wgt2 )
    1246             : !
    1247             : ! !INPUT PARAMETERS:
    1248             : !
    1249             :     REAL(dp),         INTENT(IN   )   :: int1, int2, cur
    1250             : !
    1251             : ! !INPUT/OUTPUT PARAMETERS:
    1252             : !
    1253             :     REAL(sp),         INTENT(  OUT)   :: wgt1, wgt2
    1254             : !
    1255             : ! !REVISION HISTORY:
    1256             : !  04 Mar 2015 - C. Keller - Initial version
    1257             : !  See https://github.com/geoschem/hemco for complete history
    1258             : !EOP
    1259             : !------------------------------------------------------------------------------
    1260             : !BOC
    1261             : !
    1262             : ! !LOCAL VARIABLES:
    1263             : !
    1264             :     REAL(dp)              :: diff1, diff2
    1265             :     REAL(dp)              :: jdc, jd1, jd2
    1266             : 
    1267             :     !=================================================================
    1268             :     ! GetWeights begins here!
    1269             :     !=================================================================
    1270             : 
    1271             :     ! Convert dates to Julian dates
    1272           0 :     jdc = YMDhm2jd ( cur  )
    1273           0 :     jd1 = YMDhm2jd ( int1 )
    1274           0 :     jd2 = YMDhm2jd ( int2 )
    1275             : 
    1276             :     ! Check if outside of range
    1277           0 :     IF ( jdc <= jd1 ) THEN
    1278           0 :        wgt1 = 1.0_sp
    1279           0 :     ELSEIF ( jdc >= jd2 ) THEN
    1280           0 :        wgt1 = 0.0_sp
    1281             :     ELSE
    1282           0 :        diff1 = jd2 - jdc
    1283           0 :        diff2 = jd2 - jd1
    1284           0 :        wgt1  = diff1 / diff2
    1285             :     ENDIF
    1286             : 
    1287             :     ! second weight is just complement of wgt1
    1288           0 :     wgt2  = 1.0_sp - wgt1
    1289             : 
    1290           0 :   END SUBROUTINE GetWeights
    1291             : !EOC
    1292             : !------------------------------------------------------------------------------
    1293             : !                   Harmonized Emissions Component (HEMCO)                    !
    1294             : !------------------------------------------------------------------------------
    1295             : !BOP
    1296             : !
    1297             : ! !IROUTINE: YMDhm2jd
    1298             : !
    1299             : ! !DESCRIPTION: returns the julian date of element YMDhm.
    1300             : !\\
    1301             : !\\
    1302             : ! !INTERFACE:
    1303             : !
    1304           0 :   FUNCTION YMDhm2jd ( YMDhm ) RESULT ( jd )
    1305             : !
    1306             : ! !USES:
    1307             : !
    1308             :     USE HCO_Julday_Mod
    1309             : !
    1310             : ! !INPUT PARAMETERS:
    1311             : !
    1312             :     REAL(dp), INTENT(IN)  :: YMDhm
    1313             : !
    1314             : ! !INPUT/OUTPUT PARAMETERS:
    1315             : !
    1316             :     REAL(hp) :: jd
    1317             : !
    1318             : ! !REVISION HISTORY:
    1319             : !  24 Feb 2019 - C. Keller - Initial version
    1320             : !  See https://github.com/geoschem/hemco for complete history
    1321             : !EOP
    1322             : !------------------------------------------------------------------------------
    1323             : !BOC
    1324             : !
    1325             : ! !LOCAL VARIABLES:
    1326             : !
    1327             :     INTEGER               :: yr, mt, dy, hr, mn
    1328             :     REAL(dp)              :: utc, day
    1329             : 
    1330             :     !=================================================================
    1331             :     ! YMDh2jd begins here!
    1332             :     !=================================================================
    1333           0 :     yr  = FLOOR( MOD( YMDhm, 1.0e12_dp ) / 1.0e8_dp )
    1334           0 :     mt  = FLOOR( MOD( YMDhm, 1.0e8_dp  ) / 1.0e6_dp )
    1335           0 :     dy  = FLOOR( MOD( YMDhm, 1.0e6_dp  ) / 1.0e4_dp )
    1336           0 :     hr  = FLOOR( MOD( YMDhm, 1.0e4_dp  ) / 1.0e2_dp )
    1337           0 :     mn  = FLOOR( MOD( YMDhm, 1.0e2_dp  ) )
    1338             :     utc = ( REAL(hr,dp) / 24.0_dp    ) + &
    1339             :           ( REAL(mn,dp) / 1440.0_dp  ) + &
    1340           0 :           ( REAL(0 ,dp) / 86400.0_dp )
    1341           0 :     day = REAL(dy,dp) + utc
    1342           0 :     jd  = JULDAY( yr, mt, day )
    1343             : 
    1344           0 :   END FUNCTION YMDhm2jd
    1345             : !EOC
    1346             : !------------------------------------------------------------------------------
    1347             : !                   Harmonized Emissions Component (HEMCO)                    !
    1348             : !------------------------------------------------------------------------------
    1349             : !BOP
    1350             : !
    1351             : ! !IROUTINE: YMDhm2hrs
    1352             : !
    1353             : ! !DESCRIPTION: returns the hours of element YMDhm. For simplicity, 30 days are
    1354             : ! assigned to every month. At the moment, this routine is only called to
    1355             : ! determine the time interval between two emission time slices (DeltaT) and
    1356             : ! this approximation is good enough.
    1357             : !\\
    1358             : !\\
    1359             : ! !INTERFACE:
    1360             : !
    1361           0 :   FUNCTION YMDhm2hrs ( YMDhm ) RESULT ( hrs )
    1362             : !
    1363             : ! !INPUT PARAMETERS:
    1364             : !
    1365             :     REAL(dp), INTENT(IN)  :: YMDhm
    1366             : !
    1367             : ! !INPUT/OUTPUT PARAMETERS:
    1368             : !
    1369             :     INTEGER              :: hrs
    1370             : !
    1371             : ! !REVISION HISTORY:
    1372             : !  26 Jan 2015 - C. Keller - Initial version
    1373             : !  See https://github.com/geoschem/hemco for complete history
    1374             : !EOP
    1375             : !------------------------------------------------------------------------------
    1376             : !BOC
    1377             : 
    1378             :     !=================================================================
    1379             :     ! YMDh2hrs begins here!
    1380             :     !=================================================================
    1381             :     hrs = FLOOR( MOD( YMDhm, 1.0e12_dp ) / 1.0e8_dp ) * 8760 + &
    1382             :           FLOOR( MOD( YMDhm, 1.0e8_dp  ) / 1.0e6_dp ) * 720  + &
    1383             :           FLOOR( MOD( YMDhm, 1.0e6_dp  ) / 1.0e4_dp ) * 24   + &
    1384           0 :           FLOOR( MOD( YMDhm, 1.0e4_dp  ) / 1.0e2_dp )
    1385             : 
    1386           0 :   END FUNCTION YMDhm2hrs
    1387             : !EOC
    1388             : !------------------------------------------------------------------------------
    1389             : !                   Harmonized Emissions Component (HEMCO)                    !
    1390             : !------------------------------------------------------------------------------
    1391             : !BOP
    1392             : !
    1393             : ! !IROUTINE: Normalize_Area
    1394             : !
    1395             : ! !DESCRIPTION: Subroutine Normalize\_Area normalizes the given array
    1396             : ! by the surface area calculated from the given netCDF file.
    1397             : !\\
    1398             : !\\
    1399             : ! !INTERFACE:
    1400             : !
    1401           0 :   SUBROUTINE Normalize_Area( HcoState, Array, nlon, LatEdge, FN, RC )
    1402             : !
    1403             : ! !INPUT PARAMETERS:
    1404             : !
    1405             :     TYPE(HCO_State),  POINTER         :: HcoState    ! HEMCO state object
    1406             :     INTEGER,          INTENT(IN   )   :: nlon        ! # of lon midpoints
    1407             :     REAL(hp),         POINTER         :: LatEdge(:)  ! lat edges
    1408             :     CHARACTER(LEN=*), INTENT(IN   )   :: FN          ! filename
    1409             : !
    1410             : ! !INPUT/OUTPUT PARAMETERS:
    1411             : !
    1412             :     REAL(sp),         POINTER         :: Array(:,:,:,:) ! Data
    1413             :     INTEGER,          INTENT(INOUT)   :: RC             ! Return code
    1414             : !
    1415             : ! !REVISION HISTORY:
    1416             : !  13 Mar 2013 - C. Keller - Initial version
    1417             : !  See https://github.com/geoschem/hemco for complete history
    1418             : !EOP
    1419             : !------------------------------------------------------------------------------
    1420             : !BOC
    1421             : !
    1422             : ! !LOCAL VARIABLES:
    1423             : !
    1424             :     REAL(hp)              :: DLAT, AREA
    1425             :     INTEGER               :: NLAT, J
    1426             :     CHARACTER(LEN=255)    :: MSG, LOC
    1427             : 
    1428             :     !=================================================================
    1429             :     ! NORNALIZE_AREA begins here!
    1430             :     !=================================================================
    1431             : 
    1432             :     ! Initialize
    1433           0 :     LOC    = 'NORMALIZE_AREA (hcoio_util_mod.F90 )'
    1434             : 
    1435             :     ! Check array size
    1436           0 :     NLAT = SIZE(LatEdge,1) - 1
    1437             : 
    1438           0 :     IF ( SIZE(Array,1) /= nlon ) THEN
    1439           0 :        MSG = 'Array size does not agree with nlon: ' // TRIM(FN)
    1440           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    1441           0 :        RETURN
    1442             :     ENDIF
    1443           0 :     IF ( SIZE(Array,2) /= NLAT ) THEN
    1444           0 :        MSG = 'Array size does not agree with nlat: ' // TRIM(FN)
    1445           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    1446           0 :        RETURN
    1447             :     ENDIF
    1448             : 
    1449             :     ! Loop over all latitudes
    1450           0 :     DO J = 1, NLAT
    1451             :        ! get grid box area in m2 for grid box with lower and upper latitude
    1452             :        ! llat/ulat:  Area = 2 * PI * Re^2 * DLAT / nlon,
    1453             :        ! where DLAT = abs( sin(ulat) - sin(llat) )
    1454           0 :        DLAT = ABS( SIN(LatEdge(J+1)*HcoState%Phys%PI_180)  &
    1455           0 :                    - SIN(LatEdge(J)*HcoState%Phys%PI_180) )
    1456             :        AREA = ( 2_hp * HcoState%Phys%PI * DLAT * HcoState%Phys%Re**2 ) &
    1457           0 :               / REAL(nlon,hp)
    1458             : 
    1459             :        ! convert array data to m-2
    1460           0 :        ARRAY(:,J,:,:) = ARRAY(:,J,:,:) / AREA
    1461             :     ENDDO
    1462             : 
    1463             :     ! Prompt a warning
    1464           0 :     WRITE(MSG,*) 'No area unit found in ' // TRIM(FN) // ' - convert to m-2!'
    1465           0 :     CALL HCO_WARNING ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    1466             : 
    1467             :     ! Leave w/ success
    1468           0 :     RC = HCO_SUCCESS
    1469             : 
    1470             :   END SUBROUTINE Normalize_Area
    1471             : !EOC
    1472             : !------------------------------------------------------------------------------
    1473             : !                   Harmonized Emissions Component (HEMCO)                    !
    1474             : !------------------------------------------------------------------------------
    1475             : !BOP
    1476             : !
    1477             : ! !IROUTINE: SrcFile_Parse
    1478             : !
    1479             : ! !DESCRIPTION: Routine SrcFile\_Parse parses the source file name ('ncFile')
    1480             : ! of the provided list container Lct. In particular, it searches for tokens
    1481             : ! such as $ROOT, $YYYY, etc., within the file name and replaces those values
    1482             : ! with the intendend characters. The parsed file name is returned in string
    1483             : ! srcFile, while the original file name is retained in Lct.
    1484             : !\\
    1485             : !\\
    1486             : ! It now also checks if the file exists. If the file does not exist and the
    1487             : ! file name contains date tokens, it tries to adjust the file name to the
    1488             : ! closest available date in the past. The optional flag FUTURE can be used
    1489             : ! to denote that the next available file in the future shall be selected,
    1490             : ! even if there is a file that exactly matches the preferred date time. This
    1491             : ! is useful for interpolation between fields.
    1492             : !\\
    1493             : !\\
    1494             : ! !INTERFACE:
    1495             : !
    1496           0 :   SUBROUTINE SrcFile_Parse ( HcoState, Lct, srcFile, FOUND, RC, &
    1497             :                              Direction, Year )
    1498             : !
    1499             : ! !USES:
    1500             : !
    1501             :     USE HCO_TIDX_MOD,         ONLY : HCO_GetPrefTimeAttr
    1502             :     USE HCO_TIDX_MOD,         ONLY : tIDx_IsInRange
    1503             :     USE HCO_CLOCK_MOD,        ONLY : HcoClock_Get
    1504             :     USE HCO_CLOCK_MOD,        ONLY : Get_LastDayOfMonth
    1505             : !
    1506             : ! !INPUT PARAMETERS:
    1507             : !
    1508             :     TYPE(HCO_State),  POINTER                 :: HcoState   ! HEMCO state object
    1509             :     TYPE(ListCont),   POINTER                 :: Lct        ! HEMCO list
    1510             :     INTEGER,          INTENT(IN   ), OPTIONAL :: Direction  ! Look for file in
    1511             :                                                             ! future (+1) or
    1512             :                                                             ! past (-1)
    1513             :     INTEGER,          INTENT(IN   ), OPTIONAL :: Year       ! To use fixed year
    1514             : !
    1515             : ! !OUTPUT PARAMETERS:
    1516             : !
    1517             :     CHARACTER(LEN=*), INTENT(  OUT)           :: srcFile    ! output string
    1518             :     LOGICAL,          INTENT(  OUT)           :: FOUND      ! Does file exist?
    1519             : !
    1520             : ! !INPUT/OUTPUT PARAMETERS:
    1521             : !
    1522             :     INTEGER,          INTENT(INOUT)           :: RC         ! return code
    1523             : !
    1524             : ! !REVISION HISTORY:
    1525             : !  01 Oct 2014 - C. Keller - Initial version
    1526             : !  See https://github.com/geoschem/hemco for complete history
    1527             : !EOP
    1528             : !------------------------------------------------------------------------------
    1529             : !BOC
    1530             : !
    1531             : ! !LOCAL VARIABLES:
    1532             : !
    1533             :     INTEGER :: INC,     CNT,    TYPCNT, TYP,   NEWTYP
    1534             :     INTEGER :: prefYr,  prefMt, prefDy, prefHr, prefMn
    1535             :     INTEGER :: origYr,  origMt, origDy, origHr
    1536             :     LOGICAL :: hasFile, hasYr,  hasMt,  hasDy, hasHr
    1537             :     LOGICAL :: nextTyp
    1538             :     CHARACTER(LEN=1023) :: MSG, LOC
    1539             :     CHARACTER(LEN=1023) :: srcFileOrig
    1540             : 
    1541             :     ! maximum # of iterations for file search
    1542             :     INTEGER, PARAMETER :: MAXIT = 10000
    1543             : 
    1544             :     !=================================================================
    1545             :     ! SrcFile_Parse
    1546             :     !=================================================================
    1547             : 
    1548             :     ! Initialize
    1549           0 :     LOC     = 'SrcFile_Parse (HCOIO_UTIL_MOD.F90)'
    1550           0 :     RC      = HCO_SUCCESS
    1551           0 :     found   = .FALSE.
    1552           0 :     srcFile = Lct%Dct%Dta%ncFile
    1553             : 
    1554             :     ! verbose mode
    1555           0 :     IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    1556           0 :        WRITE(MSG,*) 'Parsing source file and replacing tokens'
    1557           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
    1558             :     ENDIF
    1559             : 
    1560             :     ! Get preferred dates (to be passed to parser)
    1561             :     CALL HCO_GetPrefTimeAttr ( HcoState, Lct, &
    1562           0 :                                prefYr, prefMt, prefDy, prefHr, prefMn, RC )
    1563           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    1564           0 :         CALL HCO_ERROR( 'ERROR 1', RC, THISLOC=LOC )
    1565           0 :         RETURN
    1566             :     ENDIF
    1567             : 
    1568             :     ! Make sure dates are not negative
    1569           0 :     IF ( prefYr <= 0 ) THEN
    1570           0 :        CALL HcoClock_Get( HcoState%Clock, cYYYY = prefYr, RC = RC )
    1571           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    1572           0 :            CALL HCO_ERROR( 'ERROR 2', RC, THISLOC=LOC )
    1573           0 :            RETURN
    1574             :        ENDIF
    1575             :     ENDIF
    1576           0 :     IF ( prefMt <= 0 ) THEN
    1577           0 :        CALL HcoClock_Get( HcoState%Clock, cMM   = prefMt, RC = RC )
    1578           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    1579           0 :            CALL HCO_ERROR( 'ERROR 3', RC, THISLOC=LOC )
    1580           0 :            RETURN
    1581             :        ENDIF
    1582             :     ENDIF
    1583           0 :     IF ( prefDy <= 0 ) THEN
    1584           0 :        CALL HcoClock_Get( HcoState%Clock, cDD   = prefDy, RC = RC )
    1585           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    1586           0 :            CALL HCO_ERROR( 'ERROR 4', RC, THISLOC=LOC )
    1587           0 :            RETURN
    1588             :        ENDIF
    1589             :     ENDIF
    1590           0 :     IF ( prefHr <  0 ) THEN
    1591           0 :        CALL HcoClock_Get( HcoState%Clock, cH    = prefHr, RC = RC )
    1592           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    1593           0 :            CALL HCO_ERROR( 'ERROR 5', RC, THISLOC=LOC )
    1594           0 :            RETURN
    1595             :        ENDIF
    1596             :     ENDIF
    1597             : 
    1598             :     ! Eventually replace default preferred year with specified one
    1599           0 :     IF ( PRESENT(Year) ) prefYr = Year
    1600             : 
    1601             :     ! Call the parser
    1602             :     CALL HCO_CharParse ( HcoState%Config, srcFile, prefYr, prefMt, &
    1603           0 :                          prefDy, prefHr, prefMn, RC )
    1604           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    1605           0 :         CALL HCO_ERROR( 'ERROR 6', RC, THISLOC=LOC )
    1606           0 :         RETURN
    1607             :     ENDIF
    1608           0 :     srcFileOrig = TRIM(srcFile)
    1609             : 
    1610             :     ! Check if file exists
    1611           0 :     INQUIRE( FILE=TRIM(srcFile), EXIST=HasFile )
    1612             : 
    1613             :     ! If the direction flag is on, force HasFile to be false.
    1614           0 :     IF ( PRESENT(Direction) ) THEN
    1615           0 :        IF ( Direction /= 0 ) HasFile = .FALSE.
    1616             :     ENDIF
    1617             : 
    1618             :     !-----------------------------------------------------------------------
    1619             :     ! If this is a HEMCO dry-run simulation, then do not enter the loop
    1620             :     ! where we will attempt to go back in time until a file is found.
    1621             :     ! For the dry-run we need to report all files, even missing.
    1622             :     ! This fixes Github issue geoschem/geos-chem #312. (bmy, 6/9/20)
    1623             :     !-----------------------------------------------------------------------
    1624           0 :     IF ( HcoState%Options%isDryRun ) THEN
    1625             : 
    1626             :        ! Make sure that the year is not 1, this indicates that the
    1627             :        ! preferred year is outside of the years specified in the
    1628             :        ! time range settings in the configuration file, and will
    1629             :        ! lead to files with a year of "0001" in the path.
    1630             :        ! (bmy, 6/9/20)
    1631           0 :        IF ( prefyr == 1 ) THEN
    1632             :           MSG = 'Cannot find file for current simulation time: ' // &
    1633             :                TRIM(srcFile) // ' - Cannot get field ' // &
    1634             :                TRIM(Lct%Dct%cName) // '. Please check file name ' // &
    1635           0 :                'and time (incl. time range flag) in the config. file'
    1636           0 :           CALL HCO_ERROR( MSG, RC )
    1637           0 :           RETURN
    1638             :        ENDIF
    1639             : 
    1640             :        ! Otherwise return with success
    1641           0 :        RC    = HCO_SUCCESS
    1642           0 :        Found = HasFile
    1643           0 :        RETURN
    1644             :     ENDIF
    1645             : 
    1646             :     ! If file does not exist, check if we can adjust prefYr, prefMt, etc.
    1647           0 :     IF ( .NOT. HasFile .AND. Lct%Dct%DctType /= HCO_CFLAG_EXACT ) THEN
    1648             : 
    1649             :        ! Check if any token exist
    1650           0 :        HasYr = ( INDEX(TRIM(Lct%Dct%Dta%ncFile),'YYYY') > 0 )
    1651           0 :        HasMt = ( INDEX(TRIM(Lct%Dct%Dta%ncFile),'MM'  ) > 0 )
    1652           0 :        HasDy = ( INDEX(TRIM(Lct%Dct%Dta%ncFile),'DD'  ) > 0 )
    1653           0 :        HasHr = ( INDEX(TRIM(Lct%Dct%Dta%ncFile),'HH'  ) > 0 )
    1654             : 
    1655             :        ! Search for file
    1656           0 :        IF ( HasYr .OR. HasMt .OR. HasDy .OR. HasHr ) THEN
    1657             : 
    1658             :           ! Date increments
    1659           0 :           INC = -1
    1660           0 :           IF ( PRESENT(Direction) ) THEN
    1661           0 :              INC = Direction
    1662             :           ENDIF
    1663             : 
    1664             :           ! Initialize counters
    1665           0 :           CNT = 0
    1666             : 
    1667             :           ! Type is the update type (see below)
    1668           0 :           TYP = 0
    1669             : 
    1670             :           ! Mirror preferred variables
    1671           0 :           origYr = prefYr
    1672           0 :           origMt = prefMt
    1673           0 :           origDy = prefDy
    1674           0 :           origHr = prefHr
    1675             : 
    1676             :           ! Do until file is found or counter exceeds threshold
    1677           0 :           DO WHILE ( .NOT. HasFile )
    1678             : 
    1679             :              ! Inrease counter
    1680           0 :              CNT = CNT + 1
    1681           0 :              IF ( CNT > MAXIT ) EXIT
    1682             : 
    1683             :              ! Increase update type if needed:
    1684           0 :              nextTyp = .FALSE.
    1685             : 
    1686             :              ! Type 0: Initialization
    1687           0 :              IF ( TYP == 0 ) THEN
    1688             :                 nextTyp = .TRUE.
    1689             :              ! Type 1: update hour only
    1690           0 :              ELSEIF ( TYP == 1 .AND. TYPCNT > 24 ) THEN
    1691             :                 nextTyp = .TRUE.
    1692             :              ! Type 2: update day only
    1693           0 :              ELSEIF ( TYP == 2 .AND. TYPCNT > 31 ) THEN
    1694             :                 nextTyp = .TRUE.
    1695             :              ! Type 3: update month only
    1696           0 :              ELSEIF ( TYP == 3 .AND. TYPCNT > 12 ) THEN
    1697             :                 nextTyp = .TRUE.
    1698             :              ! Type 4: update year only
    1699           0 :              ELSEIF ( TYP == 4 .AND. TYPCNT > 300 ) THEN
    1700             :                 nextTyp = .TRUE.
    1701             :              ! Type 5: update hour and day
    1702           0 :              ELSEIF ( TYP == 5 .AND. TYPCNT > 744 ) THEN
    1703             :                 nextTyp = .TRUE.
    1704             :              ! Type 6: update day and month
    1705           0 :              ELSEIF ( TYP == 6 .AND. TYPCNT > 372 ) THEN
    1706             :                 nextTyp = .TRUE.
    1707             :              ! Type 7: update month and year
    1708           0 :              ELSEIF ( TYP == 7 .AND. TYPCNT > 3600 ) THEN
    1709             :                 EXIT
    1710             :              ENDIF
    1711             : 
    1712             :              ! Get next type
    1713             :              IF ( nextTyp ) THEN
    1714           0 :                 NEWTYP = -1
    1715           0 :                 IF     ( hasHr .AND. TYP < 1 ) THEN
    1716             :                    NEWTYP = 1
    1717           0 :                 ELSEIF ( hasDy .AND. TYP < 2 ) THEN
    1718             :                    NEWTYP = 2
    1719           0 :                 ELSEIF ( hasMt .AND. TYP < 3 ) THEN
    1720             :                    NEWTYP = 3
    1721           0 :                 ELSEIF ( hasYr .AND. TYP < 4 ) THEN
    1722             :                    NEWTYP = 4
    1723             :                 ELSEIF ( hasDy .AND. TYP < 2 ) THEN
    1724             :                    NEWTYP = 5
    1725             :                 ELSEIF ( hasDy .AND. TYP < 2 ) THEN
    1726             :                    NEWTYP = 6
    1727             :                 ELSEIF ( hasDy .AND. TYP < 2 ) THEN
    1728             :                    NEWTYP = 7
    1729             :                 ENDIF
    1730             : 
    1731             :                 ! Exit if no other type found
    1732             :                 IF ( NEWTYP < 0 ) EXIT
    1733             : 
    1734             :                 ! This is the new type, reset type counter
    1735           0 :                 TYP    = NEWTYP
    1736           0 :                 TYPCNT = 0
    1737             : 
    1738             :                 ! Make sure we reset all values
    1739           0 :                 prefYr = origYr
    1740           0 :                 prefMt = origMt
    1741           0 :                 prefDy = origDy
    1742           0 :                 prefHr = origHr
    1743             : 
    1744             :              ENDIF
    1745             : 
    1746             :              ! Update preferred datetimes
    1747           0 :              SELECT CASE ( TYP )
    1748             :                 ! Adjust hour only
    1749             :                 CASE ( 1 )
    1750           0 :                    prefHr = prefHr + INC
    1751             :                 ! Adjust day only
    1752             :                 CASE ( 2 )
    1753           0 :                    prefDy = prefDy + INC
    1754             :                 ! Adjust month only
    1755             :                 CASE ( 3 )
    1756           0 :                    prefMt = prefMt + INC
    1757             :                 ! Adjust year only
    1758             :                 CASE ( 4 )
    1759           0 :                    prefYr = prefYr + INC
    1760             :                 ! Adjust hour and day
    1761             :                 CASE ( 5 )
    1762           0 :                    prefHr = prefHr + INC
    1763           0 :                    IF ( MOD(TYPCNT,24) == 0 ) prefDy = prefDy + INC
    1764             :                 ! Adjust day and month
    1765             :                 CASE ( 6 )
    1766           0 :                    prefDy = prefDy + INC
    1767           0 :                    IF ( MOD(TYPCNT,31) == 0 ) prefMt = prefMt + INC
    1768             :                 ! Adjust month and year
    1769             :                 CASE ( 7 )
    1770           0 :                    prefMt = prefMt + INC
    1771           0 :                    IF ( MOD(TYPCNT,12) == 0 ) prefYr = prefYr + INC
    1772             :                 CASE DEFAULT
    1773           0 :                    EXIT
    1774             :              END SELECT
    1775             : 
    1776             :              ! Check if we need to adjust a year/month/day/hour
    1777           0 :              IF ( prefHr < 0 ) THEN
    1778           0 :                 prefHr = 23
    1779           0 :                 prefDy = prefDy - 1
    1780             :              ENDIF
    1781           0 :              IF ( prefHr > 23 ) THEN
    1782           0 :                 prefHr = 0
    1783           0 :                 prefDy = prefDy + 1
    1784             :              ENDIF
    1785           0 :              IF ( prefDy < 1  ) THEN
    1786           0 :                 prefDy = 31
    1787           0 :                 prefMt = prefMt - 1
    1788             :              ENDIF
    1789           0 :              IF ( prefDy > 31 ) THEN
    1790           0 :                 prefDy = 1
    1791           0 :                 prefMt = prefMt + 1
    1792             :              ENDIF
    1793           0 :              IF ( prefMt < 1  ) THEN
    1794           0 :                 prefMt = 12
    1795           0 :                 prefYr = prefYr - 1
    1796             :              ENDIF
    1797           0 :              IF ( prefMt > 12 ) THEN
    1798           0 :                 prefMt = 1
    1799           0 :                 prefYr = prefYr + 1
    1800             :              ENDIF
    1801             : 
    1802             :              ! Make sure day does not exceed max. number of days in this month
    1803           0 :              prefDy = MIN( prefDy, Get_LastDayOfMonth( prefMt, prefYr ) )
    1804             : 
    1805             :              ! Mirror original file
    1806           0 :              srcFile = Lct%Dct%Dta%ncFile
    1807             : 
    1808             :              ! Call the parser with adjusted values
    1809             :              CALL HCO_CharParse ( HcoState%Config, srcFile, prefYr, &
    1810           0 :                                   prefMt, prefDy, prefHr, prefMn, RC )
    1811           0 :              IF ( RC /= HCO_SUCCESS ) THEN
    1812           0 :                  CALL HCO_ERROR( 'ERROR 7', RC, THISLOC=LOC )
    1813           0 :                  RETURN
    1814             :              ENDIF
    1815             : 
    1816             :              ! Check if this file exists
    1817           0 :              INQUIRE( FILE=TRIM(srcFile), EXIST=HasFile )
    1818             : 
    1819             :              ! Update counter
    1820           0 :              TYPCNT = TYPCNT + 1
    1821             :           ENDDO
    1822             :        ENDIF
    1823             :     ENDIF
    1824             : 
    1825             :     ! Additional check for data with a given range: make sure that the selected
    1826             :     ! field is not outside of the given range
    1827           0 :     IF ( HasFile .AND. ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_RANGE ) ) THEN
    1828           0 :        HasFile = TIDX_IsInRange ( Lct, prefYr, prefMt, prefDy, prefHr )
    1829             :     ENDIF
    1830             : 
    1831             :     ! Restore original source file name and date to avoid confusion in log file
    1832           0 :     IF ( .not. HasFile ) THEN
    1833           0 :        srcFile = Trim(srcFileOrig)
    1834             :     ENDIF
    1835             : 
    1836             :     ! Return variable
    1837           0 :     FOUND = HasFile
    1838             : 
    1839             :     ! Return w/ success
    1840           0 :     RC = HCO_SUCCESS
    1841             : 
    1842           0 :   END SUBROUTINE SrcFile_Parse
    1843             : !EOC
    1844             : !------------------------------------------------------------------------------
    1845             : !                   Harmonized Emissions Component (HEMCO)                    !
    1846             : !------------------------------------------------------------------------------
    1847             : !BOP
    1848             : !
    1849             : ! !IROUTINE: SigmaMidToEdges
    1850             : !
    1851             : ! !DESCRIPTION: Helper routine to interpolate sigma mid point values to edges.
    1852             : ! A simple linear interpolation is performed.
    1853             : !\\
    1854             : !\\
    1855             : ! !INTERFACE:
    1856             : !
    1857           0 :   SUBROUTINE SigmaMidToEdges ( HcoState, SigMid, SigEdge, RC )
    1858             : !
    1859             : ! !INPUT PARAMETERS:
    1860             : !
    1861             :     TYPE(HCO_State),  POINTER                 :: HcoState        ! HEMCO state
    1862             :     REAL(hp),         POINTER                 :: SigMid(:,:,:)   ! sigma levels
    1863             : !
    1864             : ! !OUTPUT PARAMETERS:
    1865             : !
    1866             :     REAL(hp),         POINTER                 :: SigEdge(:,:,:)  ! sigma edges
    1867             :     INTEGER,          INTENT(  OUT)           :: RC              ! return code
    1868             : !
    1869             : ! !REVISION HISTORY:
    1870             : !  03 Oct 2013 - C. Keller - Initial version
    1871             : !  See https://github.com/geoschem/hemco for complete history
    1872             : !EOP
    1873             : !------------------------------------------------------------------------------
    1874             : !BOC
    1875             : !
    1876             : ! !LOCAL VARIABLES:
    1877             : !
    1878             :     INTEGER            :: L, AS
    1879             :     INTEGER            :: nx, ny, nz
    1880             :     CHARACTER(LEN=255) :: MSG
    1881             :     CHARACTER(LEN=255) :: LOC = 'SigmaMidToEdges (hcoio_util_mod.F90)'
    1882             : 
    1883             :     !=================================================================
    1884             :     ! SigmaMidToEdges begins here!
    1885             :     !=================================================================
    1886             : 
    1887             :     ! Allocate space as required
    1888           0 :     nx = SIZE(SigMid,1)
    1889           0 :     ny = SIZE(SigMid,2)
    1890           0 :     nz = SIZE(SigMid,3)
    1891           0 :     IF ( ASSOCIATED(SigEdge) ) DEALLOCATE(SigEdge)
    1892           0 :     ALLOCATE(SigEdge(nx,ny,nz+1),STAT=AS)
    1893           0 :     IF ( AS/=0 ) THEN
    1894             :        CALL HCO_ERROR( 'Allocate SigEdge', RC, &
    1895           0 :                        THISLOC=LOC )
    1896           0 :        RETURN
    1897             :     ENDIF
    1898           0 :     SigEdge = 0.0_hp
    1899             : 
    1900             :     ! Calculate sigma edges by linear interpolation (symmetric mid-points)
    1901           0 :     DO L = 1, nz-1
    1902           0 :        SigEdge(:,:,L+1) = ( SigMid(:,:,L) + SigMid(:,:,L+1) ) / 2.0_hp
    1903             :     ENDDO
    1904             : 
    1905             :     ! Get outermost values:
    1906           0 :     SigEdge(:,:,1   ) = SigMid(:,:,1 ) - ( SigEdge(:,:,2) - SigMid(:,:,1)   )
    1907           0 :     SigEdge(:,:,nz+1) = SigMid(:,:,nz) + ( SigMid(:,:,nz) - SigEdge(:,:,nz) )
    1908             : 
    1909             :     ! Return w/ success
    1910           0 :     RC = HCO_SUCCESS
    1911             : 
    1912             :   END SUBROUTINE SigmaMidToEdges
    1913             : !EOC
    1914             : !------------------------------------------------------------------------------
    1915             : !                   Harmonized Emissions Component (HEMCO)                    !
    1916             : !------------------------------------------------------------------------------
    1917             : !BOP
    1918             : !
    1919             : ! !IROUTINE: CheckMissVal
    1920             : !
    1921             : ! !DESCRIPTION: Checks for missing values in the passed array. Missing values
    1922             : ! of base emissions and masks are set to 0, missing values of scale factors
    1923             : ! are set to 1.
    1924             : !\\
    1925             : ! !INTERFACE:
    1926             : !
    1927           0 :   SUBROUTINE CheckMissVal ( Lct, Arr )
    1928             : !
    1929             : ! !INPUT PARAMETERS:
    1930             : !
    1931             :     TYPE(ListCont),   POINTER                 :: Lct
    1932             :     REAL(sp),         POINTER                 :: Arr(:,:,:,:)
    1933             : !
    1934             : ! !REVISION HISTORY:
    1935             : !  04 Mar 2015 - C. Keller - Initial version
    1936             : !  See https://github.com/geoschem/hemco for complete history
    1937             : !EOP
    1938             : !------------------------------------------------------------------------------
    1939             : !BOC
    1940             : !
    1941             : ! !LOCAL VARIABLES:
    1942             : !
    1943             :     !=================================================================
    1944             :     ! CheckMissVal begins here!
    1945             :     !=================================================================
    1946             : 
    1947             :     ! Error trap
    1948           0 :     IF ( .NOT. ASSOCIATED(Arr) ) RETURN
    1949             : 
    1950           0 :     IF ( ANY(Arr == HCO_MISSVAL) ) THEN
    1951             :        ! Base emissions
    1952           0 :        IF ( Lct%Dct%DctType == HCO_DCTTYPE_BASE ) THEN
    1953           0 :           WHERE(Arr == HCO_MISSVAL) Arr = 0.0_sp
    1954             :        ! Scale factor
    1955           0 :        ELSEIF ( Lct%Dct%DctType == HCO_DCTTYPE_SCAL ) THEN
    1956           0 :           WHERE(Arr == HCO_MISSVAL) Arr = 1.0_sp
    1957             :        ! Mask
    1958           0 :        ELSEIF ( Lct%Dct%DctType == HCO_DCTTYPE_MASK ) THEN
    1959           0 :           WHERE(Arr == HCO_MISSVAL) Arr = 0.0_sp
    1960             :        ENDIF
    1961             :     ENDIF
    1962             : 
    1963             :   END SUBROUTINE CheckMissVal
    1964             : !EOC
    1965             : !------------------------------------------------------------------------------
    1966             : !                   Harmonized Emissions Component (HEMCO)                    !
    1967             : !------------------------------------------------------------------------------
    1968             : !BOP
    1969             : !
    1970             : ! !IROUTINE: GetArbDimIndex
    1971             : !
    1972             : ! !DESCRIPTION: Subroutine GetArbDimIndex returns the index of the arbitrary
    1973             : ! file dimension. -1 if no such dimension is defined.
    1974             : !\\
    1975             : ! !INTERFACE:
    1976             : !
    1977           0 :   SUBROUTINE GetArbDimIndex( HcoState, Lun, Lct, ArbIdx, RC )
    1978             : !
    1979             : ! !USES:
    1980             : !
    1981             :     USE HCO_m_netcdf_io_checks
    1982             :     USE HCO_m_netcdf_io_get_dimlen
    1983             :     USE HCO_ExtList_Mod,    ONLY : GetExtOpt
    1984             : !
    1985             : ! !INPUT PARAMETERS:
    1986             : !
    1987             :     TYPE(HCO_State),  POINTER                 :: HcoState
    1988             :     INTEGER,          INTENT(IN   )           :: Lun
    1989             :     TYPE(ListCont),   POINTER                 :: Lct
    1990             : !
    1991             : ! !OUTPUT PARAMETERS:
    1992             : !
    1993             :     INTEGER,          INTENT(  OUT)           :: ArbIdx
    1994             :     INTEGER,          INTENT(  OUT)           :: RC
    1995             : !
    1996             : ! !REVISION HISTORY:
    1997             : !  22 Sep 2015 - C. Keller - Initial version
    1998             : !  See https://github.com/geoschem/hemco for complete history
    1999             : !EOP
    2000             : !------------------------------------------------------------------------------
    2001             : !BOC
    2002             : !
    2003             : ! !LOCAL VARIABLES:
    2004             : !
    2005             :     INTEGER             :: TargetVal, nVal
    2006             :     LOGICAL             :: Found
    2007             :     CHARACTER(LEN=255)  :: ArbDimVal
    2008             :     CHARACTER(LEN=511)  :: MSG
    2009             :     CHARACTER(LEN=255)  :: LOC = 'GetArbDimIndex (hcoio_util_mod.F90)'
    2010             : 
    2011             :     !=================================================================
    2012             :     ! GetArbDimIndex
    2013             :     !=================================================================
    2014             : 
    2015             :     ! Assume success until otherwise
    2016           0 :     RC = HCO_SUCCESS
    2017             : 
    2018             :     ! Init
    2019           0 :     ArbIdx = -1
    2020           0 :     IF ( TRIM(Lct%Dct%Dta%ArbDimName) == 'none' ) RETURN
    2021             : 
    2022             :     ! Check if variable exists
    2023           0 :     Found = Ncdoes_Dim_Exist ( Lun, TRIM(Lct%Dct%Dta%ArbDimName) )
    2024           0 :     IF ( .NOT. Found ) THEN
    2025             :        MSG = 'Cannot read dimension ' // TRIM(Lct%Dct%Dta%ArbDimName) &
    2026             :              // ' from file ' // &
    2027           0 :              TRIM(Lct%Dct%Dta%ncFile)
    2028           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2029           0 :        RETURN
    2030             :     ENDIF
    2031             : 
    2032             :     ! Get dimension length
    2033           0 :     CALL Ncget_Dimlen ( Lun, TRIM(Lct%Dct%Dta%ArbDimName), nVal )
    2034             : 
    2035             :     ! Get value to look for. This is archived in variable ArbDimVal.
    2036             :     ! Eventually need to extract value from HEMCO settings
    2037           0 :     ArbDimVal = TRIM(Lct%Dct%Dta%ArbDimVal)
    2038             : 
    2039             :     ! If string starts with a number, evaluate value directly
    2040             :     IF ( ArbDimVal(1:1) == '0' .OR. &
    2041             :          ArbDimVal(1:1) == '1' .OR. &
    2042             :          ArbDimVal(1:1) == '2' .OR. &
    2043             :          ArbDimVal(1:1) == '3' .OR. &
    2044             :          ArbDimVal(1:1) == '4' .OR. &
    2045             :          ArbDimVal(1:1) == '5' .OR. &
    2046             :          ArbDimVal(1:1) == '6' .OR. &
    2047             :          ArbDimVal(1:1) == '7' .OR. &
    2048           0 :          ArbDimVal(1:1) == '8' .OR. &
    2049             :          ArbDimVal(1:1) == '9'       ) THEN
    2050           0 :        READ(ArbDimVal,*) TargetVal
    2051             : 
    2052             :     ! Otherwise, assume this is a HEMCO option (including a token)
    2053             :     ELSE
    2054           0 :        IF ( ArbDimVal(1:1) == '$' ) ArbDimVal = ArbDimVal(2:LEN(ArbDimVal))
    2055             :        CALL GetExtOpt ( HcoState%Config, ExtNr=-999, &
    2056             :                         OptName=TRIM(ArbDimVal), &
    2057           0 :                         OptValInt=TargetVal, FOUND=Found, RC=RC )
    2058           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2059           0 :            CALL HCO_ERROR( 'ERROR 8', RC, THISLOC=LOC )
    2060           0 :            RETURN
    2061             :        ENDIF
    2062           0 :        IF ( .NOT. Found ) THEN
    2063           0 :           WRITE(MSG,*) 'Cannot evaluate additional dimension value ', &
    2064           0 :              TRIM(ArbDimVal), '. This does not seem to be a number nor ', &
    2065           0 :              'a HEMCO token/setting. This error happened when evaluating ', &
    2066           0 :              'dimension ', TRIM(Lct%Dct%Dta%ArbDimName), ' belonging to ', &
    2067           0 :              'file ', TRIM(Lct%Dct%Dta%ncFile)
    2068           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2069           0 :           RETURN
    2070             :        ENDIF
    2071             :     ENDIF
    2072             : 
    2073           0 :     IF ( TargetVal > nVal ) THEN
    2074           0 :        WRITE(MSG,*) 'Desired dimension value ', TargetVal, &
    2075           0 :           ' exceeds corresponding dimension length on that file: ', nVal, &
    2076           0 :           'This error happened when evaluating ', &
    2077           0 :           'dimension ', TRIM(Lct%Dct%Dta%ArbDimName), ' belonging to ', &
    2078           0 :           'file ', TRIM(Lct%Dct%Dta%ncFile)
    2079           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2080           0 :        RETURN
    2081             : 
    2082             :     ELSE
    2083           0 :        ArbIdx = TargetVal
    2084             :     ENDIF
    2085             : 
    2086             :     ! Verbose
    2087           0 :     IF ( HcoState%amIRoot .AND. HCO_IsVerb( HcoState%Config%Err ) ) THEN
    2088           0 :        WRITE(MSG,*) 'Additional dimension ', TRIM(Lct%Dct%Dta%ArbDimName), &
    2089           0 :                     ' in ', TRIM(Lct%Dct%Dta%ncFile), ': use index ',      &
    2090           0 :                     ArbIdx, ' (set: ', Lct%Dct%Dta%ArbDimVal, ')'
    2091           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
    2092             :     ENDIF
    2093             : 
    2094             :     ! Return w/ success
    2095           0 :     RC = HCO_SUCCESS
    2096             : 
    2097             :   END SUBROUTINE GetArbDimIndex
    2098             : !EOC
    2099             : #endif
    2100             : !------------------------------------------------------------------------------
    2101             : !                   Harmonized Emissions Component (HEMCO)                    !
    2102             : !------------------------------------------------------------------------------
    2103             : !BOP
    2104             : !
    2105             : ! !IROUTINE: HCOIO_ReadOther
    2106             : !
    2107             : ! !DESCRIPTION: Subroutine HCOIO\_ReadOther is a wrapper routine to
    2108             : ! read data from sources other than netCDF.
    2109             : !\\
    2110             : !\\
    2111             : ! If a file name is given (ending with '.txt'), the data are assumed
    2112             : ! to hold country-specific values (e.g. diurnal scale factors). In all
    2113             : ! other cases, the data is directly read from the configuration file
    2114             : ! (scalars).
    2115             : !\\
    2116             : !\\
    2117             : ! !INTERFACE:
    2118             : !
    2119           0 :   SUBROUTINE HCOIO_ReadOther( HcoState, Lct, RC )
    2120             : !
    2121             : ! !USES:
    2122             : !
    2123             : !
    2124             : ! !INPUT PARAMTERS:
    2125             : !
    2126             :     TYPE(HCO_State), POINTER          :: HcoState    ! HEMCO state
    2127             : !
    2128             : ! !INPUT/OUTPUT PARAMETERS:
    2129             : !
    2130             :     TYPE(ListCont),   POINTER         :: Lct
    2131             :     INTEGER,          INTENT(INOUT)   :: RC
    2132             : !
    2133             : ! !REVISION HISTORY:
    2134             : !  22 Dec 2014 - C. Keller: Initial version
    2135             : !  See https://github.com/geoschem/hemco for complete history
    2136             : !EOP
    2137             : !------------------------------------------------------------------------------
    2138             : !BOC
    2139             : !
    2140             : ! !LOCAL VARIABLES:
    2141             : !
    2142             :     CHARACTER(LEN=255) :: MSG, LOC
    2143             : 
    2144             :     !======================================================================
    2145             :     ! HCOIO_ReadOther begins here
    2146             :     !======================================================================
    2147           0 :     LOC = 'HCOIO_ReadOther (HCOIO_UTIL_MOD.F90)'
    2148             : 
    2149             :     ! Error check: data must be in local time
    2150           0 :     IF ( .NOT. Lct%Dct%Dta%IsLocTime ) THEN
    2151             :        MSG = 'Cannot read data from file that is not in local time: ' // &
    2152           0 :              TRIM(Lct%Dct%cName)
    2153           0 :        CALL HCO_ERROR( MSG, RC, THISLOC='HCOIO_ReadOther (hcoio_dataread_mod.F90)' )
    2154           0 :        RETURN
    2155             :     ENDIF
    2156             : 
    2157             :     ! Read an ASCII file as country values
    2158           0 :     IF ( INDEX( TRIM(Lct%Dct%Dta%ncFile), '.txt' ) > 0 ) THEN
    2159           0 :        CALL HCOIO_ReadCountryValues( HcoState, Lct, RC )
    2160           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2161           0 :            CALL HCO_ERROR( 'ERROR 9', RC, THISLOC=LOC )
    2162           0 :            RETURN
    2163             :        ENDIF
    2164             : 
    2165             :     ! Directly read from configuration file otherwise
    2166             :     ELSE
    2167           0 :        CALL HCOIO_ReadFromConfig( HcoState, Lct, RC )
    2168           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2169           0 :            CALL HCO_ERROR( 'ERROR 10', RC, THISLOC=LOC )
    2170           0 :            RETURN
    2171             :        ENDIF
    2172             :     ENDIF
    2173             : 
    2174             :     ! Return w/ success
    2175           0 :     RC = HCO_SUCCESS
    2176             : 
    2177             :   END SUBROUTINE HCOIO_ReadOther
    2178             : !EOC
    2179             : !------------------------------------------------------------------------------
    2180             : !                   Harmonized Emissions Component (HEMCO)                    !
    2181             : !------------------------------------------------------------------------------
    2182             : !BOP
    2183             : !
    2184             : ! !IROUTINE: HCOIO_ReadCountryValues
    2185             : !
    2186             : ! !DESCRIPTION: Subroutine HCOIO\_ReadCountryValues
    2187             : !\\
    2188             : !\\
    2189             : ! !INTERFACE:
    2190             : !
    2191           0 :   SUBROUTINE HCOIO_ReadCountryValues ( HcoState, Lct, RC )
    2192             : !
    2193             : ! !USES:
    2194             : !
    2195             :     USE HCO_inquireMod,     ONLY : findFreeLUN
    2196             :     USE HCO_CHARTOOLS_MOD,  ONLY : HCO_CMT, HCO_SPC, NextCharPos
    2197             :     USE HCO_EmisList_Mod,   ONLY : HCO_GetPtr
    2198             :     USE HCO_FileData_Mod,   ONLY : FileData_ArrCheck
    2199             : !
    2200             : ! !INPUT PARAMTERS:
    2201             : !
    2202             :     TYPE(HCO_State), POINTER          :: HcoState    ! HEMCO state
    2203             : !
    2204             : ! !INPUT/OUTPUT PARAMETERS:
    2205             : !
    2206             :     TYPE(ListCont),   POINTER         :: Lct
    2207             :     INTEGER,          INTENT(INOUT)   :: RC
    2208             : !
    2209             : ! !REVISION HISTORY:
    2210             : !  22 Dec 2014 - C. Keller: Initial version
    2211             : !  See https://github.com/geoschem/hemco for complete history
    2212             : !EOP
    2213             : !------------------------------------------------------------------------------
    2214             : !BOC
    2215             : !
    2216             : ! !LOCAL VARIABLES:
    2217             : !
    2218             :     INTEGER               :: IUFILE, IOS
    2219             :     INTEGER               :: ID1, ID2, I, NT, CID, NLINE
    2220           0 :     REAL(sp), POINTER     :: CNTR(:,:)
    2221           0 :     INTEGER,  ALLOCATABLE :: CIDS(:,:)
    2222           0 :     REAL(hp), POINTER     :: Vals(:)
    2223             :     LOGICAL               :: Verb
    2224             :     CHARACTER(LEN=2047)   :: LINE
    2225             :     CHARACTER(LEN=255)    :: MSG, DUM, CNT
    2226             :     CHARACTER(LEN=255)    :: LOC = 'HCOIO_ReadCountryValues (hcoio_util_mod.F90)'
    2227             : 
    2228             :     !======================================================================
    2229             :     ! HCOIO_ReadCountryValues begins here
    2230             :     !======================================================================
    2231             : 
    2232             :     ! Init
    2233           0 :     CNTR => NULL()
    2234           0 :     Vals => NULL()
    2235             : 
    2236             :     ! verbose mode?
    2237           0 :     Verb = HCO_IsVerb( HcoState%Config%Err )
    2238             : 
    2239             :     ! Verbose
    2240           0 :     IF ( Verb ) THEN
    2241           0 :        MSG = 'Use country-specific values for ' // TRIM(Lct%Dct%cName)
    2242           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
    2243           0 :        MSG = '- Source file: ' // TRIM(Lct%Dct%Dta%ncFile)
    2244           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
    2245             :     ENDIF
    2246             : 
    2247             :     ! Open file
    2248           0 :     IUFILE = FindFreeLun()
    2249           0 :     OPEN ( IUFILE, FILE=TRIM( Lct%Dct%Dta%ncFile ), STATUS='OLD', IOSTAT=IOS )
    2250           0 :     IF ( IOS /= 0 ) THEN
    2251           0 :        MSG = 'Cannot open ' // TRIM(Lct%Dct%Dta%ncFile)
    2252           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2253           0 :        RETURN
    2254             :     ENDIF
    2255             : 
    2256             :     ! Repeat for every line
    2257             :     NLINE = 0
    2258             :     DO
    2259             : 
    2260             :        ! Read line
    2261           0 :        READ( IUFILE, '(a)', IOSTAT=IOS ) LINE
    2262             : 
    2263             :        ! End of file?
    2264           0 :        IF ( IOS < 0 ) EXIT
    2265             : 
    2266             :        ! Error?
    2267           0 :        IF ( IOS > 0 ) THEN
    2268           0 :           MSG = 'Error reading ' // TRIM(Lct%Dct%Dta%ncFile)
    2269           0 :           MSG = TRIM(MSG) // ' - last valid line: ' // TRIM(LINE)
    2270           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2271           0 :           RETURN
    2272             :        ENDIF
    2273             : 
    2274             :        ! Skip commented lines and/or empty lines
    2275           0 :        IF ( TRIM(LINE) == ''      ) CYCLE
    2276           0 :        IF ( LINE(1:1)  == HCO_CMT ) CYCLE
    2277             : 
    2278             :        ! First (valid) line holds the name of the mask container
    2279           0 :        IF ( NLINE == 0 ) THEN
    2280             : 
    2281             :           ! Get pointer to mask. Convert to integer
    2282           0 :           CALL HCO_GetPtr( HcoState, TRIM(LINE), CNTR, RC )
    2283           0 :           IF ( RC /= HCO_SUCCESS ) THEN
    2284           0 :               CALL HCO_ERROR( 'ERROR 11', RC, THISLOC=LOC )
    2285           0 :               RETURN
    2286             :           ENDIF
    2287           0 :           ALLOCATE( CIDS(HcoState%NX, HcoState%NY), STAT=IOS )
    2288           0 :           IF ( IOS /= 0 ) THEN
    2289           0 :              CALL HCO_ERROR( 'Cannot allocate CIDS', RC, THISLOC=LOC )
    2290           0 :              RETURN
    2291             :           ENDIF
    2292           0 :           CIDS = NINT(CNTR)
    2293             : 
    2294             :           ! Verbose
    2295           0 :           IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    2296           0 :              MSG = '- Use ID mask ' // TRIM(LINE)
    2297           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    2298             :           ENDIF
    2299             : 
    2300             :           ! Go to next line
    2301           0 :           NLINE = NLINE + 1
    2302           0 :           CYCLE
    2303             :        ENDIF
    2304             : 
    2305             :        ! Get first space character to skip country name.
    2306             :        ! We assume here that a country name is given right at the
    2307             :        ! beginning of the line, e.g. 'USA 744 1.05/1.02/...'
    2308           0 :        ID1 = NextCharPos( LINE, HCO_SPC )
    2309           0 :        CNT = LINE(1:ID1)
    2310             : 
    2311             :        ! Get country ID
    2312           0 :        DO I = ID1, LEN(LINE)
    2313           0 :           IF ( LINE(I:I) /= HCO_SPC ) EXIT
    2314             :        ENDDO
    2315           0 :        ID1 = I
    2316           0 :        ID2 = NextCharPos( LINE, HCO_SPC, START=ID1 )
    2317             : 
    2318           0 :        IF ( ID2 >= LEN(LINE) .OR. ID2 < 0 ) THEN
    2319           0 :           MSG = 'Cannot extract country ID from: ' // TRIM(LINE)
    2320           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2321           0 :           RETURN
    2322             :        ENDIF
    2323           0 :        DUM = LINE(ID1:ID2)
    2324           0 :        READ( DUM, * ) CID
    2325             : 
    2326             :        ! Extract data values
    2327           0 :        ID1  = ID2+1
    2328           0 :        ID2  = LEN(LINE)
    2329           0 :        LINE = LINE(ID1:ID2)
    2330           0 :        CALL GetDataVals( HcoState, Lct, LINE, Vals, RC )
    2331           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2332           0 :            CALL HCO_ERROR( 'ERROR 12', RC, THISLOC=LOC )
    2333           0 :            RETURN
    2334             :        ENDIF
    2335             : 
    2336             :        ! Check data / array dimensions
    2337           0 :        NT = SIZE(Vals,1)
    2338             :        CALL FileData_ArrCheck( HcoState%Config, Lct%Dct%Dta, &
    2339           0 :                                HcoState%NX, HcoState%NY, NT, RC )
    2340           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2341           0 :            CALL HCO_ERROR( 'ERROR 13', RC, THISLOC=LOC )
    2342           0 :            RETURN
    2343             :        ENDIF
    2344             : 
    2345             :        ! Pass to data array. If the country ID is larger than zero, fill
    2346             :        ! only those grid boxes. Otherwise, fill all grid boxes that have
    2347             :        ! not yet been filled.
    2348           0 :        DO I = 1, NT
    2349           0 :           IF ( CID == 0 ) THEN
    2350           0 :              WHERE ( Lct%Dct%Dta%V2(I)%Val <= 0.0_sp )
    2351           0 :                 Lct%Dct%Dta%V2(I)%Val = Vals(I)
    2352             :              ENDWHERE
    2353             :           ELSE
    2354           0 :              WHERE ( CIDS == CID )
    2355           0 :                 Lct%Dct%Dta%V2(I)%Val = Vals(I)
    2356             :              ENDWHERE
    2357             :           ENDIF
    2358             :        ENDDO
    2359             : 
    2360             :        ! Verbose
    2361           0 :        IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    2362           0 :           WRITE(MSG,*) '- Obtained values for ',TRIM(CNT),' ==> ID:', CID
    2363           0 :           CALL HCO_MSG(HcoState%Config%Err,MSG)
    2364             :        ENDIF
    2365             : 
    2366             :        ! Cleanup
    2367           0 :        IF ( ASSOCIATED(Vals) ) DEALLOCATE( Vals )
    2368           0 :        Vals => NULL()
    2369             : 
    2370             :        ! Update # of read lines
    2371           0 :        NLINE = NLINE + 1
    2372             :     ENDDO
    2373             : 
    2374             :     ! Close file
    2375           0 :     CLOSE ( IUFILE )
    2376             : 
    2377             :     ! Data is 2D
    2378           0 :     Lct%Dct%Dta%SpaceDim  = 2
    2379             : 
    2380             :     ! Make sure data is in local time
    2381           0 :     IF ( .NOT. Lct%Dct%Dta%IsLocTime ) THEN
    2382           0 :        Lct%Dct%Dta%IsLocTime = .TRUE.
    2383             :        MSG = 'Data assigned to mask regions will be treated in local time: '//&
    2384           0 :               TRIM(Lct%Dct%cName)
    2385           0 :        CALL HCO_WARNING( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2386             :     ENDIF
    2387             : 
    2388             :     ! Cleanup
    2389           0 :     Cntr => NULL()
    2390           0 :     IF ( ALLOCATED(CIDS) ) DEALLOCATE ( CIDS )
    2391             : 
    2392             :     ! Return w/ success
    2393           0 :     RC = HCO_SUCCESS
    2394             : 
    2395           0 :   END SUBROUTINE HCOIO_ReadCountryValues
    2396             : !EOC
    2397             : !------------------------------------------------------------------------------
    2398             : !                   Harmonized Emissions Component (HEMCO)                    !
    2399             : !------------------------------------------------------------------------------
    2400             : !BOP
    2401             : !
    2402             : ! !IROUTINE: HCOIO_ReadFromConfig
    2403             : !
    2404             : ! !DESCRIPTION: Subroutine HCOIO\_ReadFromConfig reads data directly from
    2405             : ! the configuration file (instead of reading it from a netCDF file).
    2406             : ! These data is always assumed to be spatially uniform, but it is possible
    2407             : ! to specify multiple time slices by separating the individual time slice
    2408             : ! values by the HEMCO separator sign ('/' by default). The time dimension
    2409             : ! of these data is either determined from the srcTime attribute or estimated
    2410             : ! from the number of time slices provided. For example, if no srcTime is
    2411             : ! specified and 24 time slices are provided, data is assumed to represent
    2412             : ! hourly data. Similarly, data is assumed to represent weekdaily or monthly
    2413             : ! data for 7 or 12 time slices, respectively.
    2414             : !\\
    2415             : !\\
    2416             : ! If the srcTime attribute is defined, the time slices are determined from
    2417             : ! this attribute. Only one time dimension (year, month, day, or hour) can
    2418             : ! be defined for scalar fields!
    2419             : !\\
    2420             : !\\
    2421             : ! !INTERFACE:
    2422             : !
    2423           0 :   SUBROUTINE HCOIO_ReadFromConfig( HcoState, Lct, RC )
    2424             : !
    2425             : ! !USES:
    2426             : !
    2427             :     USE HCO_FILEDATA_MOD,   ONLY : FileData_ArrCheck
    2428             : !
    2429             : ! !INPUT PARAMTERS:
    2430             : !
    2431             :     TYPE(HCO_State), POINTER          :: HcoState    ! HEMCO state
    2432             : !
    2433             : ! !INPUT/OUTPUT PARAMETERS:
    2434             : !
    2435             :     TYPE(ListCont),   POINTER         :: Lct
    2436             :     INTEGER,          INTENT(INOUT)   :: RC
    2437             : !
    2438             : ! !REVISION HISTORY:
    2439             : !  24 Jul 2014 - C. Keller: Initial version
    2440             : !  See https://github.com/geoschem/hemco for complete history
    2441             : !EOP
    2442             : !------------------------------------------------------------------------------
    2443             : !BOC
    2444             : !
    2445             : ! !LOCAL VARIABLES:
    2446             : !
    2447             :     INTEGER            :: I, NT
    2448           0 :     REAL(hp), POINTER  :: Vals(:)
    2449             :     CHARACTER(LEN=255) :: MSG
    2450             :     CHARACTER(LEN=255) :: LOC = 'HCOIO_ReadFromConfig (hcoio_util_mod.F90)'
    2451             : 
    2452             :     !======================================================================
    2453             :     ! HCOIO_ReadFromConfig begins here
    2454             :     !======================================================================
    2455             : 
    2456             :     ! Init
    2457           0 :     Vals => NULL()
    2458             : 
    2459             :     ! Verbose
    2460           0 :     IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    2461           0 :        WRITE(MSG, *) 'Read from config file: ', TRIM(Lct%Dct%cName)
    2462           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
    2463             :     ENDIF
    2464             : 
    2465             :     !-------------------------------------------------------------------
    2466             :     ! Get data values for this time step.
    2467             :     !-------------------------------------------------------------------
    2468           0 :     CALL GetDataVals( HcoState, Lct, Lct%Dct%Dta%ncFile, Vals, RC )
    2469           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    2470           0 :         CALL HCO_ERROR( 'ERROR 14', RC, THISLOC=LOC )
    2471           0 :         RETURN
    2472             :     ENDIF
    2473             : 
    2474             :     !-------------------------------------------------------------------
    2475             :     ! Copy data into array.
    2476             :     !-------------------------------------------------------------------
    2477             : 
    2478             :     ! Number of values
    2479           0 :     NT = SIZE(Vals,1)
    2480             : 
    2481             :     ! For masks, interpret data as mask corners (lon1/lat1/lon2/lat2)
    2482             :     ! with no time dimension
    2483           0 :     IF ( Lct%Dct%DctType == HCO_DCTTYPE_MASK ) THEN
    2484             : 
    2485             :        ! Make sure data is allocated
    2486             :        CALL FileData_ArrCheck( HcoState%Config, Lct%Dct%Dta, &
    2487           0 :                                HcoState%NX, HcoState%NY, 1, RC )
    2488           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2489           0 :            CALL HCO_ERROR( 'ERROR 15', RC, THISLOC=LOC )
    2490           0 :            RETURN
    2491             :        ENDIF
    2492             : 
    2493             :        ! Fill array: 1.0 within grid box, 0.0 outside.
    2494           0 :        CALL FillMaskBox( HcoState, Lct, Vals, RC )
    2495           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2496           0 :            CALL HCO_ERROR( 'ERROR 16', RC, THISLOC=LOC )
    2497           0 :            RETURN
    2498             :        ENDIF
    2499             : 
    2500             :        ! Data is 2D
    2501           0 :        Lct%Dct%Dta%SpaceDim = 2
    2502             : 
    2503             :     ! For base emissions and scale factors, interpret data as scalar
    2504             :     ! values with a time dimension.
    2505             :     ELSE
    2506             : 
    2507           0 :        CALL FileData_ArrCheck( HcoState%Config, Lct%Dct%Dta, 1, 1, NT, RC )
    2508           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2509           0 :            CALL HCO_ERROR( 'ERROR 17', RC, THISLOC=LOC )
    2510           0 :            RETURN
    2511             :        ENDIF
    2512           0 :        DO I = 1, NT
    2513           0 :           Lct%Dct%Dta%V2(I)%Val(1,1) = Vals(I)
    2514             : !==============================================================================
    2515             : ! KLUDGE BY BOB YANTOSCA (05 Jan 2016)
    2516             : !
    2517             : ! This WRITE statement avoids a seg fault in some Intel Fortran Compiler
    2518             : ! versions, such as ifort 12 and ifort 13.  The ADVANCE="no" prevents
    2519             : ! carriage returns from being added to the log file, and the '' character
    2520             : ! will prevent text from creeping across the screen.
    2521             : !
    2522             : ! NOTE: This section only gets executed during the initialization phase,
    2523             : ! when we save data not read from netCDF files into the HEMCO data structure.
    2524             : ! This type of data includes scale factors and mask data specified as vectors
    2525             : ! in the HEMCO configuration file.  Therefore, this section will only get
    2526             : ! executed at startup, so the WRITE statment should not add significant
    2527             : ! overhead to the simulation.
    2528             : !
    2529             : ! The root issue seems to be an optimization bug in the compiler.
    2530             : !==============================================================================
    2531             : #if defined( LINUX_IFORT )
    2532             :           WRITE( 6, '(a)', ADVANCE='no' ) ''
    2533             : #endif
    2534             : 
    2535             :        ENDDO
    2536             : 
    2537             :        ! Data is 1D
    2538           0 :        Lct%Dct%Dta%SpaceDim  = 1
    2539             : 
    2540             :        ! Make sure data is in local time
    2541           0 :        IF ( .NOT. Lct%Dct%Dta%IsLocTime ) THEN
    2542           0 :           Lct%Dct%Dta%IsLocTime = .TRUE.
    2543             :           MSG = 'Scale factors read from file are treated as local time: '// &
    2544           0 :                  TRIM(Lct%Dct%cName)
    2545           0 :           CALL HCO_WARNING( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2546             :        ENDIF
    2547             : 
    2548             :     ENDIF
    2549             : 
    2550             :     ! Cleanup
    2551           0 :     IF ( ASSOCIATED(Vals) ) DEALLOCATE(Vals)
    2552             : 
    2553             :     ! Return w/ success
    2554           0 :     RC = HCO_SUCCESS
    2555             : 
    2556           0 :   END SUBROUTINE HCOIO_ReadFromConfig
    2557             : !EOC
    2558             : !------------------------------------------------------------------------------
    2559             : !                   Harmonized Emissions Component (HEMCO)                    !
    2560             : !------------------------------------------------------------------------------
    2561             : !BOP
    2562             : !
    2563             : ! !IROUTINE: GetSliceIdx
    2564             : !
    2565             : ! !DESCRIPTION: gets the time slice index to be used for data directly
    2566             : ! read from the HEMCO configuration file. prefDt denotes the preferred
    2567             : ! time attribute (year, month, or day). DtType is used to identify the
    2568             : ! time attribute type (1=year, 2=month, 3=day). The time slice index will
    2569             : ! be selected based upon those two variables. IDX is the selected time
    2570             : ! slice index. It will be set to -1 if the current simulation date
    2571             : ! is outside of the specified time range and the time cycle attribute is
    2572             : ! not enabled for this field.
    2573             : !\\
    2574             : !\\
    2575             : ! !INTERFACE:
    2576             : !
    2577           0 :   SUBROUTINE GetSliceIdx ( HcoState, Lct, DtType, prefDt, IDX, RC )
    2578             : !
    2579             : ! !INPUT PARAMETERS:
    2580             : !
    2581             :     TYPE(HCO_State),  POINTER                 :: HcoState
    2582             :     TYPE(ListCont),   POINTER                 :: Lct
    2583             :     INTEGER,          INTENT(IN   )           :: DtType
    2584             :     INTEGER,          INTENT(IN   )           :: prefDt
    2585             : !
    2586             : ! !INPUT/OUTPUT PARAMETERS:
    2587             : !
    2588             :     INTEGER,          INTENT(INOUT)           :: IDX
    2589             :     INTEGER,          INTENT(INOUT)           :: RC
    2590             : !
    2591             : ! !REVISION HISTORY:
    2592             : !  13 Mar 2013 - C. Keller - Initial version
    2593             : !  See https://github.com/geoschem/hemco for complete history
    2594             : !EOP
    2595             : !------------------------------------------------------------------------------
    2596             : !BOC
    2597             : !
    2598             : ! !LOCAL VARIABLES:
    2599             : !
    2600             :     INTEGER            :: lowDt, uppDt
    2601             :     CHARACTER(LEN=255) :: MSG
    2602             :     CHARACTER(LEN=255) :: LOC = 'GetSliceIdx (hcoio_util_mod.F90)'
    2603             : 
    2604             :     !=================================================================
    2605             :     ! GetSliceIdx begins here!
    2606             :     !=================================================================
    2607             : 
    2608             :     ! Init
    2609           0 :     RC = HCO_SUCCESS
    2610             : 
    2611             :     ! Get upper and lower time range
    2612           0 :     IF ( DtType == 1 ) THEN
    2613           0 :        lowDt = Lct%Dct%Dta%ncYrs(1)
    2614           0 :        uppDt = Lct%Dct%Dta%ncYrs(2)
    2615           0 :     ELSEIF ( DtType == 2 ) THEN
    2616           0 :        lowDt = Lct%Dct%Dta%ncMts(1)
    2617           0 :        uppDt = Lct%Dct%Dta%ncMts(2)
    2618           0 :     ELSEIF ( DtType == 3 ) THEN
    2619           0 :        lowDt = Lct%Dct%Dta%ncDys(1)
    2620           0 :        uppDt = Lct%Dct%Dta%ncDys(2)
    2621             :     ELSE
    2622           0 :        WRITE(MSG,*) "DtType must be one of 1, 2, 3: ", DtType
    2623           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2624           0 :        RETURN
    2625             :     ENDIF
    2626             : 
    2627             :     ! Check for cycle flags:
    2628             : 
    2629             :     ! Data cycle set to range or exact date: in these cases, the
    2630             :     ! the preferred date will be equal to the current date, so
    2631             :     ! check if the preferred date is indeed within the available
    2632             :     ! range (lowDt, uppDt).
    2633             :     ! For data only to be used within the specified range, set
    2634             :     ! index to -1. This will force the scale factors to be set to
    2635             :     ! zero!
    2636           0 :     IF ( prefDt < lowDt .OR. prefDt > uppDt ) THEN
    2637           0 :        IF ( ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_EXACT ) .OR.      &
    2638             :             ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_RANGE )     ) THEN
    2639           0 :           IDX = -1
    2640           0 :           RETURN
    2641             :        ELSE
    2642             :           ! this here should never happen, since for a cycle flag of 1,
    2643             :           ! the preferred date should always be restricted to the range
    2644             :           ! of available time stamps.
    2645           0 :           MSG = 'preferred date is outside of range: ' // TRIM(Lct%Dct%cName)
    2646           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2647           0 :           RETURN
    2648             :        ENDIF
    2649             :     ENDIF
    2650             : 
    2651             :     ! If the code makes it to here, prefDt is within the available data range
    2652             :     ! and we simply get the wanted index from the current index and the lowest
    2653             :     ! available index.
    2654           0 :     IDX = prefDt - lowDt + 1
    2655             : 
    2656             :   END SUBROUTINE GetSliceIdx
    2657             : !EOC
    2658             : !------------------------------------------------------------------------------
    2659             : !                   Harmonized Emissions Component (HEMCO)                    !
    2660             : !------------------------------------------------------------------------------
    2661             : !BOP
    2662             : !
    2663             : ! !IROUTINE: GetDataVals
    2664             : !
    2665             : ! !DESCRIPTION: Subroutine GetDataVals extracts the data values from ValStr
    2666             : ! and writes them into vector Vals. ValStr is typically a character string
    2667             : ! read from an external ASCII file or directly from the HEMCO configuration
    2668             : ! file. Depending on the time specifications provided in the configuration
    2669             : ! file, Vals will be filled with only a subset of the values of ValStr.
    2670             : !\\
    2671             : !\\
    2672             : ! !INTERFACE:
    2673             : !
    2674           0 :   SUBROUTINE GetDataVals ( HcoState, Lct, ValStr, Vals, RC )
    2675             : !
    2676             : ! !USES:
    2677             : !
    2678             :     USE HCO_CHARTOOLS_MOD,  ONLY : HCO_CharSplit
    2679             :     USE HCO_EXTLIST_MOD,    ONLY : HCO_GetOpt
    2680             :     USE HCO_UNIT_MOD,       ONLY : HCO_Unit_Change
    2681             :     USE HCO_tIdx_Mod,       ONLY : HCO_GetPrefTimeAttr
    2682             :     USE HCO_CLOCK_MOD,      ONLY : HcoClock_Get
    2683             : !
    2684             : ! !INPUT PARAMTERS:
    2685             : !
    2686             :     TYPE(HCO_State),  POINTER         :: HcoState    ! HEMCO state
    2687             :     CHARACTER(LEN=*), INTENT(IN   )   :: ValStr
    2688             : !
    2689             : ! !INPUT/OUTPUT PARAMETERS:
    2690             : !
    2691             :     TYPE(ListCont),   POINTER         :: Lct
    2692             :     INTEGER,          INTENT(INOUT)   :: RC
    2693             : !
    2694             : ! !OUTPUT PARAMETERS:
    2695             : !
    2696             :     REAL(hp),         POINTER         :: Vals(:)
    2697             : !
    2698             : ! !REVISION HISTORY:
    2699             : !  22 Dec 2014 - C. Keller: Initial version
    2700             : !  See https://github.com/geoschem/hemco for complete history
    2701             : !EOP
    2702             : !------------------------------------------------------------------------------
    2703             : !BOC
    2704             : !
    2705             : ! !LOCAL VARIABLES:
    2706             : !
    2707             :     INTEGER            :: HcoID
    2708             :     INTEGER            :: I, N, NUSE, AS
    2709             :     INTEGER            :: IDX1, IDX2
    2710             :     INTEGER            :: AreaFlag, TimeFlag, Check
    2711             :     INTEGER            :: prefYr, prefMt, prefDy, prefHr, prefMn
    2712             :     INTEGER            :: cYr,    cMt,    cDy,    cHr
    2713             :     REAL(hp)           :: MW_g
    2714             :     REAL(hp)           :: UnitFactor
    2715             :     REAL(hp)           :: FileVals(100)
    2716           0 :     REAL(hp), POINTER  :: FileArr(:,:,:,:)
    2717             :     LOGICAL            :: IsPerArea
    2718             :     LOGICAL            :: IsMath
    2719             :     CHARACTER(LEN=255) :: MSG
    2720             :     CHARACTER(LEN=255) :: LOC = 'GetDataVals (hcoio_util_mod.F90)'
    2721             : 
    2722             :     !======================================================================
    2723             :     ! GetDataVals begins here
    2724             :     !======================================================================
    2725             : 
    2726             :     ! Initialize
    2727           0 :     FileArr => NULL()
    2728             : 
    2729             :     ! Shadow species properties needed for unit conversion
    2730           0 :     HcoID = Lct%Dct%HcoID
    2731           0 :     IF ( HcoID > 0 ) THEN
    2732           0 :        MW_g = HcoState%Spc(HcoID)%MW_g
    2733             :     ELSE
    2734           0 :        MW_g = -999.0_hp
    2735             :     ENDIF
    2736             : 
    2737             :     ! Is this a math expression?
    2738           0 :     IsMath = .FALSE.
    2739           0 :     IF ( LEN(ValStr) > 5 ) THEN
    2740           0 :        IF ( ValStr(1:5)=='MATH:' ) IsMath = .TRUE.
    2741             :     ENDIF
    2742             : 
    2743             :     ! Evaluate math expression if string starts with 'MATH:'
    2744             :     IF ( IsMath ) THEN
    2745           0 :        CALL ReadMath ( HcoState, Lct, ValStr, FileVals, N, RC )
    2746           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2747           0 :            CALL HCO_ERROR( 'ERROR 18', RC, THISLOC=LOC )
    2748           0 :            RETURN
    2749             :        ENDIF
    2750             : 
    2751             :     ! Use regular string parser otherwise
    2752             :     ELSE
    2753             :        CALL HCO_CharSplit ( ValStr, &
    2754             :                             HCO_GetOpt(HcoState%Config%ExtList,'Separator'), &
    2755             :                             HCO_GetOpt(HcoState%Config%ExtList,'Wildcard'), &
    2756           0 :                             FileVals, N, RC )
    2757           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2758           0 :            CALL HCO_ERROR( 'ERROR 19', RC, THISLOC=LOC )
    2759           0 :            RETURN
    2760             :        ENDIF
    2761             :     ENDIF
    2762             : 
    2763             :     ! Return w/ error if no scale factor defined
    2764           0 :     IF ( N == 0 ) THEN
    2765             :        MSG = 'Cannot read data: ' // TRIM(Lct%Dct%cName) // &
    2766           0 :              ': ' // TRIM(ValStr)
    2767           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC)
    2768           0 :        RETURN
    2769             :     ENDIF
    2770             : 
    2771             :     ! Get the preferred times, i.e. the preferred year, month, day,
    2772             :     ! or hour (as specified in the configuration file).
    2773             :     CALL HCO_GetPrefTimeAttr( HcoState, Lct, &
    2774           0 :                               prefYr, prefMt, prefDy, prefHr, prefMn, RC )
    2775           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    2776           0 :         CALL HCO_ERROR( 'ERROR 20', RC, THISLOC=LOC )
    2777           0 :         RETURN
    2778             :     ENDIF
    2779             : 
    2780             :     ! ----------------------------------------------------------------
    2781             :     ! For masks, assume that values represent the corners of the mask
    2782             :     ! box, e.g. there must be four values. Masks are time-independent
    2783             :     ! and unitless
    2784             :     ! ----------------------------------------------------------------
    2785           0 :     IF ( Lct%Dct%DctType == HCO_DCTTYPE_MASK ) THEN
    2786             : 
    2787             :        ! There must be exactly four values
    2788           0 :        IF ( N /= 4 ) THEN
    2789             :           MSG = 'Mask values are not lon1/lat1/lon2/lat2: ' // &
    2790           0 :                 TRIM(ValStr) // ' --> ' // TRIM(Lct%Dct%cName)
    2791           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2792           0 :           RETURN
    2793             :        ENDIF
    2794             : 
    2795             :        ! Pass to FileArr array (will be used below)
    2796           0 :        NUSE = 4
    2797           0 :        ALLOCATE( FileArr(1,1,1,NUSE), STAT=AS )
    2798             :        IF ( AS /= 0 ) THEN
    2799           0 :           MSG = 'Cannot allocate FileArr'
    2800           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2801           0 :           RETURN
    2802             :        ENDIF
    2803           0 :        FileArr(1,1,1,:) = FileVals(1:NUSE)
    2804             : 
    2805             :     ! ----------------------------------------------------------------
    2806             :     ! For non-masks, the data is interpreted as uniform values with
    2807             :     ! a time dimension. Need to select the time slices to be used at
    2808             :     ! this time (depending on the provided time attributes), as well
    2809             :     ! as to ensure that values are in the correct units.
    2810             :     ! Use all time slices unless a time interval is provided in
    2811             :     ! attribute srcTime of the configuration file.
    2812             :     ! ----------------------------------------------------------------
    2813             :     ELSE
    2814             : 
    2815             :        ! If there is only one value use this one and ignore any time
    2816             :        ! preferences.
    2817           0 :        IF ( N == 1 ) THEN
    2818           0 :           NUSE = 1
    2819           0 :           IDX1 = 1
    2820           0 :           IDX2 = 1
    2821             : 
    2822             :        ! If it's a math expression use all passed values
    2823           0 :        ELSEIF ( IsMath ) THEN
    2824           0 :           NUSE = N
    2825           0 :           IDX1 = 1
    2826           0 :           IDX2 = N
    2827             : 
    2828             :        ELSE
    2829             :           ! Currently, data read directly from the configuration file can only
    2830             :           ! represent one time dimension, i.e. it can only be yearly, monthly,
    2831             :           ! daily (or hourly data, but this is read all at the same time).
    2832             : 
    2833             :           ! Annual data
    2834           0 :           IF ( Lct%Dct%Dta%ncYrs(1) /= Lct%Dct%Dta%ncYrs(2) ) THEN
    2835             :              ! Error check
    2836             :              IF ( Lct%Dct%Dta%ncMts(1) /= Lct%Dct%Dta%ncMts(2) .OR. &
    2837           0 :                   Lct%Dct%Dta%ncDys(1) /= Lct%Dct%Dta%ncDys(2) .OR. &
    2838             :                   Lct%Dct%Dta%ncHrs(1) /= Lct%Dct%Dta%ncHrs(2)       ) THEN
    2839             :                 MSG = 'Data must not have more than one time dimension: ' // &
    2840           0 :                        TRIM(Lct%Dct%cName)
    2841           0 :                 CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2842           0 :                 RETURN
    2843             :              ENDIF
    2844             : 
    2845           0 :              CALL GetSliceIdx ( HcoState, Lct, 1, prefYr, IDX1, RC )
    2846           0 :              IF ( RC /= HCO_SUCCESS ) THEN
    2847           0 :                  CALL HCO_ERROR( 'ERROR 21', RC, THISLOC=LOC )
    2848           0 :                  RETURN
    2849             :              ENDIF
    2850           0 :              IDX2 = IDX1
    2851           0 :              NUSE = 1
    2852             : 
    2853             :           ! Monthly data
    2854           0 :           ELSEIF ( Lct%Dct%Dta%ncMts(1) /= Lct%Dct%Dta%ncMts(2) ) THEN
    2855             :              ! Error check
    2856           0 :              IF ( Lct%Dct%Dta%ncDys(1) /= Lct%Dct%Dta%ncDys(2) .OR. &
    2857             :                   Lct%Dct%Dta%ncHrs(1) /= Lct%Dct%Dta%ncHrs(2)       ) THEN
    2858             :                 MSG = 'Data must only have one time dimension: ' // &
    2859           0 :                       TRIM(Lct%Dct%cName)
    2860           0 :                 CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2861           0 :                 RETURN
    2862             :              ENDIF
    2863             : 
    2864           0 :              CALL GetSliceIdx ( HcoState, Lct, 2, prefMt, IDX1, RC )
    2865           0 :              IF ( RC /= HCO_SUCCESS ) THEN
    2866           0 :                  CALL HCO_ERROR( 'ERROR 22', RC, THISLOC=LOC )
    2867           0 :                  RETURN
    2868             :              ENDIF
    2869           0 :              IDX2 = IDX1
    2870           0 :              NUSE = 1
    2871             : 
    2872             :           ! Daily data
    2873           0 :           ELSEIF ( Lct%Dct%Dta%ncDys(1) /= Lct%Dct%Dta%ncDys(2) ) THEN
    2874             :              ! Error check
    2875           0 :              IF ( Lct%Dct%Dta%ncHrs(1) /= Lct%Dct%Dta%ncHrs(2) ) THEN
    2876             :                 MSG = 'Data must only have one time dimension: ' // &
    2877           0 :                       TRIM(Lct%Dct%cName)
    2878           0 :                 CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2879           0 :                 RETURN
    2880             :              ENDIF
    2881             : 
    2882           0 :              CALL GetSliceIdx ( HcoState, Lct, 3, prefDy, IDX1, RC )
    2883           0 :              IF ( RC /= HCO_SUCCESS ) THEN
    2884           0 :                  CALL HCO_ERROR( 'ERROR 23', RC, THISLOC=LOC )
    2885           0 :                  RETURN
    2886             :              ENDIF
    2887           0 :              IDX2 = IDX1
    2888           0 :              NUSE = 1
    2889             : 
    2890             :           ! All other cases (incl. hourly data): read all time slices).
    2891             :           ELSE
    2892           0 :              IDX1 = 1
    2893           0 :              IDX2 = N
    2894           0 :              NUSE = N
    2895             :           ENDIF
    2896             :        ENDIF
    2897             : 
    2898             :        ! ----------------------------------------------------------------
    2899             :        ! Read selected time slice(s) into data array
    2900             :        ! ----------------------------------------------------------------
    2901           0 :        IF ( IDX2 > N ) THEN
    2902           0 :           WRITE(MSG,*) 'Index ', IDX2, ' is larger than number of ', &
    2903           0 :                        'values found: ', TRIM(Lct%Dct%cName)
    2904           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2905           0 :           RETURN
    2906             :        ENDIF
    2907             : 
    2908           0 :        ALLOCATE( FileArr(1,1,1,NUSE), STAT=AS )
    2909             :        IF ( AS /= 0 ) THEN
    2910           0 :           MSG = 'Cannot allocate FileArr'
    2911           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    2912           0 :           RETURN
    2913             :        ENDIF
    2914             : 
    2915             :        ! Check for range/exact flag
    2916             :        ! If range is given, the preferred Yr/Mt/Dy/Hr will be negative
    2917             :        ! if we are outside the desired range.
    2918           0 :        IF ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_RANGE ) THEN
    2919           0 :           IF ( prefYr == -1 .OR. prefMt == -1 .OR. prefDy == -1 ) IDX1 = -1
    2920           0 :           IF ( Lct%Dct%Dta%ncHrs(1) >= 0 .AND. prefHr == -1 )     IDX1 = -1
    2921             : 
    2922             :        ! If flag is exact, the preferred date must be equal to the current
    2923             :        ! simulation date.
    2924           0 :        ELSEIF ( Lct%Dct%Dta%CycleFlag == HCO_CFLAG_EXACT ) THEN
    2925           0 :           IF ( Lct%Dct%Dta%ncYrs(1) > 0 ) THEN
    2926           0 :              IF ( prefYr < Lct%Dct%Dta%ncYrs(1) .OR. &
    2927           0 :                   prefYr > Lct%Dct%Dta%ncYrs(2) ) IDX1 = -1
    2928             :           ENDIF
    2929           0 :           IF ( Lct%Dct%Dta%ncMts(1) > 0 ) THEN
    2930           0 :              IF ( prefMt < Lct%Dct%Dta%ncMts(1) .OR. &
    2931           0 :                   prefMt > Lct%Dct%Dta%ncMts(2) ) IDX1 = -1
    2932             :           ENDIF
    2933           0 :           IF ( Lct%Dct%Dta%ncDys(1) > 0 ) THEN
    2934           0 :              IF ( prefDy < Lct%Dct%Dta%ncDys(1) .OR. &
    2935           0 :                   prefDy > Lct%Dct%Dta%ncDys(2) ) IDX1 = -1
    2936             :           ENDIF
    2937           0 :           IF ( Lct%Dct%Dta%ncHrs(1) >= 0 ) THEN
    2938           0 :              IF ( prefHr < Lct%Dct%Dta%ncHrs(1) .OR. &
    2939           0 :                   prefHr > Lct%Dct%Dta%ncHrs(2) ) IDX1 = -1
    2940             :           ENDIF
    2941             :        ENDIF
    2942             : 
    2943             :        ! IDX1 becomes -1 for data that is outside of the valid range
    2944             :        ! (and no time cycling enabled). In this case, make sure that
    2945             :        ! scale factor is set to zero.
    2946           0 :        IF ( IDX1 < 0 ) THEN
    2947           0 :           IF ( Lct%Dct%DctType == HCO_DCTTYPE_BASE ) THEN
    2948           0 :              FileArr(1,1,1,:) = 0.0_hp
    2949             :              MSG = 'Base field outside of range - set to zero: ' // &
    2950           0 :                    TRIM(Lct%Dct%cName)
    2951           0 :              CALL HCO_WARNING ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2952             : #if defined( MODEL_GEOS )
    2953             :           ELSEIF ( Lct%Dct%DctType == HCO_DCTTYPE_MASK ) THEN
    2954             :              FileArr(1,1,1,:) = 0.0_hp
    2955             :              MSG = 'Mask outside of range - set to zero: ' // &
    2956             :                    TRIM(Lct%Dct%cName)
    2957             :              CALL HCO_WARNING ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2958             : #endif
    2959             :           ELSE
    2960           0 :              FileArr(1,1,1,:) = 1.0_hp
    2961             :              MSG = 'Scale factor outside of range - set to one: ' // &
    2962           0 :                    TRIM(Lct%Dct%cName)
    2963           0 :              CALL HCO_WARNING ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2964             :           ENDIF
    2965             :        ELSE
    2966           0 :           FileArr(1,1,1,:) = FileVals(IDX1:IDX2)
    2967             :        ENDIF
    2968             : 
    2969             :        ! ----------------------------------------------------------------
    2970             :        ! Convert data to HEMCO units
    2971             :        ! ----------------------------------------------------------------
    2972             :        CALL HCO_UNIT_CHANGE( HcoConfig     = HcoState%Config,            &
    2973             :                              Array         = FileArr,                    &
    2974             :                              Units         = TRIM(Lct%Dct%Dta%OrigUnit), &
    2975             :                              MW            = MW_g,                       &
    2976             :                              YYYY          = -999,                       &
    2977             :                              MM            = -999,                       &
    2978             :                              AreaFlag      = AreaFlag,                   &
    2979             :                              TimeFlag      = TimeFlag,                   &
    2980             :                              FACT          = UnitFactor,                 &
    2981           0 :                              RC            = RC                           )
    2982           0 :        IF ( RC /= HCO_SUCCESS ) THEN
    2983           0 :            CALL HCO_ERROR( 'ERROR 24', RC, THISLOC=LOC )
    2984           0 :            RETURN
    2985             :        ENDIF
    2986             : 
    2987             :        ! Verbose mode
    2988           0 :        IF ( UnitFactor /= 1.0_hp ) THEN
    2989           0 :           IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    2990           0 :              WRITE(MSG,*) 'Data was in units of ', TRIM(Lct%Dct%Dta%OrigUnit), &
    2991           0 :                           ' - converted to HEMCO units by applying ', &
    2992           0 :                           'scale factor ', UnitFactor
    2993           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    2994             :           ENDIF
    2995             :        ELSE
    2996           0 :           IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    2997           0 :              WRITE(MSG,*) 'Data was in units of ', TRIM(Lct%Dct%Dta%OrigUnit), &
    2998           0 :                           ' - unit conversion factor is ', UnitFactor
    2999           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3000             :           ENDIF
    3001             :        ENDIF
    3002             : 
    3003             :        ! Data must be ...
    3004             :        ! ... concentration ...
    3005           0 :        IF ( AreaFlag == 3 .AND. TimeFlag == 0 ) THEN
    3006           0 :           Lct%Dct%Dta%IsConc = .TRUE.
    3007             : 
    3008           0 :        ELSEIF ( AreaFlag == 3 .AND. TimeFlag == 1 ) THEN
    3009           0 :           Lct%Dct%Dta%IsConc = .TRUE.
    3010           0 :           FileArr = FileArr * HcoState%TS_EMIS
    3011             :           MSG = 'Data converted from kg/m3/s to kg/m3: ' // &
    3012           0 :                 TRIM(Lct%Dct%cName) // ': ' // TRIM(Lct%Dct%Dta%OrigUnit)
    3013           0 :           CALL HCO_WARNING ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    3014             : 
    3015             :        ! ... emissions or unitless ...
    3016           0 :        ELSEIF ( (AreaFlag == -1 .AND. TimeFlag == -1) .OR. &
    3017             :                 (AreaFlag ==  2 .AND. TimeFlag ==  1)       ) THEN
    3018           0 :           Lct%Dct%Dta%IsConc = .FALSE.
    3019             : 
    3020             :        ! ... invalid otherwise:
    3021             :        ELSE
    3022             :           MSG = 'Unit must be unitless, emission or concentration: ' // &
    3023           0 :                 TRIM(Lct%Dct%cName) // ': ' // TRIM(Lct%Dct%Dta%OrigUnit)
    3024           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    3025           0 :           RETURN
    3026             :        ENDIF
    3027             : 
    3028             :        ! Auto-detect delta t [in hours] between time slices.
    3029             :        ! Scale factors can be:
    3030             :        ! length 1 : constant
    3031             :        ! length 7 : weekday factors: Sun, Mon, ..., Sat
    3032             :        ! length 12: monthly factors: Jan, Feb, ..., Dec
    3033             :        ! length 24: hourly  factors: 12am, 1am, ... 11pm
    3034           0 :        IF ( NUSE == 1 ) THEN
    3035           0 :           Lct%Dct%Dta%DeltaT = 0
    3036           0 :        ELSEIF ( NUSE == 7 ) THEN
    3037           0 :           Lct%Dct%Dta%DeltaT = 24
    3038           0 :        ELSEIF ( NUSE == 12 ) THEN
    3039           0 :           Lct%Dct%Dta%DeltaT = 720
    3040           0 :        ELSEIF ( NUSE == 24 ) THEN
    3041           0 :           Lct%Dct%Dta%DeltaT = 1
    3042             :        ELSE
    3043             :           MSG = 'Factor must be of length 1, 7, 12, or 24!' // &
    3044           0 :                  TRIM(Lct%Dct%cName)
    3045           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC)
    3046           0 :           RETURN
    3047             :        ENDIF
    3048             : 
    3049             :     ENDIF ! Masks vs. non-masks
    3050             : 
    3051             :     ! Copy data into output array.
    3052           0 :     IF ( ASSOCIATED(Vals) ) DEALLOCATE( Vals )
    3053           0 :     ALLOCATE( Vals(NUSE), STAT=AS )
    3054             :     IF ( AS /= 0 ) THEN
    3055           0 :        MSG = 'Cannot allocate Vals'
    3056           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    3057           0 :        RETURN
    3058             :     ENDIF
    3059           0 :     Vals(:) = FileArr(1,1,1,:)
    3060             : 
    3061             :     ! Cleanup
    3062           0 :     IF ( ASSOCIATED(FileArr) ) DEALLOCATE(FileArr)
    3063           0 :     FileArr => NULL()
    3064             : 
    3065             :     ! Return w/ success
    3066           0 :     RC = HCO_SUCCESS
    3067             : 
    3068           0 :   END SUBROUTINE GetDataVals
    3069             : !EOC
    3070             : !------------------------------------------------------------------------------
    3071             : !                   Harmonized Emissions Component (HEMCO)                    !
    3072             : !------------------------------------------------------------------------------
    3073             : !BOP
    3074             : !
    3075             : ! !IROUTINE: FillMaskBox
    3076             : !
    3077             : ! !DESCRIPTION: Subroutine FillMaskBox fills the data array of the passed list
    3078             : ! container Lct according to the mask region provided in Vals. Vals contains
    3079             : ! the mask region of interest, denoted by the lower left and upper right grid
    3080             : ! box corners: lon1, lat1, lon2, lat2. The data array of Lct is filled such
    3081             : ! that all grid boxes are set to 1 whose mid-point is inside of the given box
    3082             : ! range.
    3083             : !\\
    3084             : !\\
    3085             : ! !INTERFACE:
    3086             : !
    3087           0 :   SUBROUTINE FillMaskBox ( HcoState, Lct, Vals, RC )
    3088             : !
    3089             : ! !USES:
    3090             : !
    3091             : !
    3092             : ! !INPUT PARAMTERS:
    3093             : !
    3094             :     TYPE(HCO_State),  POINTER         :: HcoState    ! HEMCO state
    3095             :     REAL(hp)        , POINTER         :: Vals(:)
    3096             : !
    3097             : ! !INPUT/OUTPUT PARAMETERS:
    3098             : !
    3099             :     TYPE(ListCont),   POINTER         :: Lct
    3100             :     INTEGER,          INTENT(INOUT)   :: RC
    3101             : !
    3102             : ! !REVISION HISTORY:
    3103             : !  29 Dec 2014 - C. Keller - Initial version
    3104             : !  See https://github.com/geoschem/hemco for complete history
    3105             : !EOP
    3106             : !------------------------------------------------------------------------------
    3107             : !BOC
    3108             : !
    3109             : ! !LOCAL VARIABLES:
    3110             : !
    3111             :     LOGICAL            :: GridPoint
    3112             :     INTEGER            :: I, J
    3113             :     REAL(hp)           :: LON1, LON2, LAT1, LAT2
    3114             :     REAL(hp)           :: XDG1, XDG2, YDG1, YDG2
    3115             :     REAL(hp)           :: ILON, ILAT
    3116             :     CHARACTER(LEN=255) :: MSG
    3117             :     CHARACTER(LEN=255) :: LOC = 'FillMaskBox (hcoio_util_mod.F90)'
    3118             : 
    3119             :     !=================================================================
    3120             :     ! FillMaskBox begins here!
    3121             :     !=================================================================
    3122             : 
    3123             :     ! Extract lon1, lon2, lat1, lat2
    3124           0 :     LON1 = VALS(1)
    3125           0 :     LAT1 = VALS(2)
    3126           0 :     LON2 = VALS(3)
    3127           0 :     LAT2 = VALS(4)
    3128             : 
    3129             :     ! Check if this is mask is a point. In this case, we need the grid
    3130             :     ! box edges being defined.
    3131           0 :     GridPoint = .FALSE.
    3132           0 :     IF ( ( LON1 == LON2 ) .AND. ( LAT1 == LAT2 ) ) THEN
    3133           0 :        IF ( .NOT. ASSOCIATED(HcoState%Grid%XEDGE%Val) .OR. &
    3134             :             .NOT. ASSOCIATED(HcoState%Grid%YEDGE%Val)       ) THEN
    3135             :           MSG = 'Cannot evaluate grid point mask - need grid box '   // &
    3136             :                 'edges for this. This error occurs if a mask covers '// &
    3137             :                 'a fixed grid point (e.g. lon1=lon2 and lat1=lat2) ' // &
    3138           0 :                 'but HEMCO grid edges are not defined.'
    3139           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    3140           0 :           RETURN
    3141             :        ENDIF
    3142             :        GridPoint = .TRUE.
    3143             :     ENDIF
    3144             : 
    3145             :     ! Check for every grid box if mid point is within mask region.
    3146             :     ! Set to 1.0 if this is the case.
    3147             : !$OMP PARALLEL DO                        &
    3148             : !$OMP DEFAULT( SHARED                 )  &
    3149             : !$OMP PRIVATE( I, J, ILON, ILAT       )  &
    3150             : !$OMP PRIVATE( XDG1, XDG2, YDG1, YDG2 )  &
    3151             : !$OMP SCHEDULE( DYNAMIC               )
    3152           0 :     DO J = 1, HcoState%NY
    3153           0 :     DO I = 1, HcoState%NX
    3154             : 
    3155             :        ! If it's a grid point, check if it's within this
    3156             :        ! grid box
    3157           0 :        IF ( GridPoint ) THEN
    3158           0 :           XDG1 = HcoState%Grid%XEDGE%Val(I  ,J  )
    3159           0 :           XDG2 = HcoState%Grid%XEDGE%Val(I+1,J  )
    3160           0 :           YDG1 = HcoState%Grid%YEDGE%Val(I  ,J  )
    3161           0 :           YDG2 = HcoState%Grid%YEDGE%Val(I  ,J+1)
    3162           0 :           IF ( XDG1 >= 180.0_hp ) XDG1 = XDG1 - 360.0_hp
    3163           0 :           IF ( XDG2 >= 180.0_hp ) XDG2 = XDG2 - 360.0_hp
    3164             : 
    3165             :           IF ( LON1 >= XDG1 .AND. LON1 <= XDG2 .AND. &
    3166           0 :                LAT1 >= YDG1 .AND. LAT1 <= YDG2        ) THEN
    3167           0 :              Lct%Dct%Dta%V2(1)%Val(I,J) = 1.0_sp
    3168             :           ENDIF
    3169             : 
    3170             :        ! Check if mid point is within mask region
    3171             :        ELSE
    3172             :           ! Get longitude and latitude at this grid box
    3173           0 :           ILON = HcoState%Grid%XMID%Val(I,J)
    3174           0 :           ILAT = HcoState%Grid%YMID%Val(I,J)
    3175           0 :           IF ( ILON >= 180.0_hp ) ILON = ILON - 360.0_hp
    3176             : 
    3177             :           IF ( ILON >= LON1 .AND. ILON <= LON2 .AND. &
    3178           0 :                ILAT >= LAT1 .AND. ILAT <= LAT2        ) THEN
    3179           0 :              Lct%Dct%Dta%V2(1)%Val(I,J) = 1.0_sp
    3180             :           ENDIF
    3181             :        ENDIF
    3182             : 
    3183             :     ENDDO
    3184             :     ENDDO
    3185             : !$OMP END PARALLEL DO
    3186             : 
    3187             :     ! Return w/ success
    3188           0 :     RC = HCO_SUCCESS
    3189             : 
    3190             :   END SUBROUTINE FillMaskBox
    3191             : !EOC
    3192             : !------------------------------------------------------------------------------
    3193             : !                   Harmonized Emissions Component (HEMCO)                    !
    3194             : !------------------------------------------------------------------------------
    3195             : !BOP
    3196             : !
    3197             : ! !IROUTINE: ReadMath
    3198             : !
    3199             : ! !DESCRIPTION: Subroutine ReadMath reads and evaluates a mathematical
    3200             : ! expression. Mathematical expressions can combine time-stamps with
    3201             : ! mathematical functions, e.g. to yield the sine of current simulation hour.
    3202             : ! Mathematical expressions must start with the identifier 'MATH:', followed
    3203             : ! by the actual expression. Each expression must include at least one
    3204             : ! variable (evaluated at runtime). The following variables are currently
    3205             : ! supported: YYYY (year), MM (month), DD (day), HH (hour), LH (local hour),
    3206             : ! NN (minute), SS (second), WD (weekday), LWD (local weekday),
    3207             : ! DOY (day of year), ELH (elapsed hours), ELS (elapsed seconds).
    3208             : ! In addition, the following variables can be used: PI (3.141...), DOM
    3209             : ! (\# of days of current month).
    3210             : ! For example, the following expression would yield a continuous sine
    3211             : ! curve as function of hour of day: 'MATH:sin(HH/24*PI*2)'.
    3212             : !\\
    3213             : !\\
    3214             : ! For a full list of valid mathematical expressions, see module interpreter.F90.
    3215             : !\\
    3216             : !\\
    3217             : ! !INTERFACE:
    3218             : !
    3219           0 :   SUBROUTINE ReadMath( HcoState, Lct, ValStr, Vals, N, RC )
    3220             : !
    3221             : ! !USES:
    3222             : !
    3223             :     USE HCO_CLOCK_MOD,      ONLY : HcoClock_Get
    3224             :     USE HCO_tIdx_Mod,       ONLY : HCO_GetPrefTimeAttr
    3225             :     USE INTERPRETER
    3226             : !
    3227             : ! !INPUT PARAMTERS:
    3228             : !
    3229             :     TYPE(HCO_State),  POINTER         :: HcoState    ! HEMCO state
    3230             :     TYPE(ListCont),   POINTER         :: Lct
    3231             :     CHARACTER(LEN=*), INTENT(IN   )   :: ValStr
    3232             : !
    3233             : ! !INPUT/OUTPUT PARAMETERS:
    3234             : !
    3235             :     REAL(hp),         INTENT(INOUT)   :: Vals(:)
    3236             :     INTEGER,          INTENT(INOUT)   :: RC
    3237             : !
    3238             : ! !OUTPUT PARAMETERS:
    3239             : !
    3240             :     INTEGER,          INTENT(  OUT)   :: N
    3241             : !
    3242             : ! !REVISION HISTORY:
    3243             : !  11 May 2017 - C. Keller - Initial version
    3244             : !  See https://github.com/geoschem/hemco for complete history
    3245             : !EOP
    3246             : !------------------------------------------------------------------------------
    3247             : !BOC
    3248             : !
    3249             : ! !LOCAL VARIABLES:
    3250             : !
    3251             :     LOGICAL            :: EOS
    3252             :     INTEGER            :: STRL
    3253             :     INTEGER            :: I, NVAL, LHIDX, LWDIDX
    3254             :     INTEGER            :: prefYr, prefMt, prefDy, prefHr, prefMn
    3255             :     INTEGER            :: prefWD, prefDOY, prefS, LMD, cHr
    3256             :     INTEGER            :: nSteps
    3257             :     REAL(hp)           :: ELH, ELS
    3258             :     REAL(hp)           :: Val
    3259             :     CHARACTER(LEN=255) :: MSG
    3260             :     CHARACTER(LEN=255) :: LOC = 'ReadMath (hcoio_util_mod.F90)'
    3261             : 
    3262             :     ! Variables used by the evaluator to build and to determine the value
    3263             :     ! of the expressions
    3264             :     character(len = 10) :: all_variables(12)
    3265             :     real(hp)            :: all_variablesvalues(12)
    3266             : 
    3267             :     !String variable that will store the function that the evaluator will build
    3268             :     character (len = 275)  :: func
    3269             : 
    3270             :     !String variable that will return the building of the expression result
    3271             :     !If everything was ok then statusflag = 'ok', otherwise statusflag = 'error'
    3272             :     character (len = 5)  :: statusflag
    3273             : 
    3274             :     !======================================================================
    3275             :     ! ReadMath begins here
    3276             :     !======================================================================
    3277             : 
    3278             :     ! Substring (without flag 'MATH:')
    3279           0 :     STRL = LEN(ValStr)
    3280           0 :     IF ( STRL < 6 ) THEN
    3281             :        MSG = 'Math expression is too short - expected `MATH:<expr>`: ' &
    3282           0 :              //TRIM(ValStr)
    3283           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    3284           0 :        RETURN
    3285             :     ENDIF
    3286           0 :     func = ValStr(6:STRL)
    3287             : 
    3288             :     ! Get preferred time stamps
    3289             :     CALL HCO_GetPrefTimeAttr( HcoState, Lct, &
    3290           0 :                               prefYr, prefMt, prefDy, prefHr, prefMn, RC )
    3291           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    3292           0 :         CALL HCO_ERROR( 'ERROR 25', RC, THISLOC=LOC )
    3293           0 :         RETURN
    3294             :     ENDIF
    3295             : 
    3296             :     ! Get some other current time stamps
    3297             :     CALL HcoClock_Get( HcoState%Clock,  cS=prefS,     cH=cHr, &
    3298             :                        cWEEKDAY=prefWD, cDOY=prefDOY, LMD=LMD,      &
    3299           0 :                        nSteps=nSteps,   RC=RC )
    3300           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    3301           0 :         CALL HCO_ERROR( 'ERROR 26', RC, THISLOC=LOC )
    3302           0 :         RETURN
    3303             :     ENDIF
    3304             : 
    3305             :     ! GetPrefTimeAttr can return -999 for hour. In this case set to current
    3306             :     ! simulation hour
    3307           0 :     IF ( prefHr < 0 ) prefHr = cHr
    3308             : 
    3309             :     ! Parse function. This will replace any tokens in the function with the
    3310             :     ! actual token values. (ckeller, 7/7/17)
    3311             :     CALL HCO_CharParse ( HcoState%Config, func, &
    3312           0 :                          prefYr, prefMt, prefDy, prefHr, prefMn, RC )
    3313           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    3314           0 :         CALL HCO_ERROR( 'ERROR 27', RC, THISLOC=LOC )
    3315           0 :         RETURN
    3316             :     ENDIF
    3317             : 
    3318             :     ! Elapsed hours and seconds since start time
    3319           0 :     ELS = HcoState%TS_DYN * nSteps
    3320           0 :     ELH = ELS / 3600.0_hp
    3321             : 
    3322             :     ! Check which variables are in string.
    3323             :     ! Possible variables are YYYY, MM, DD, WD, HH, NN, SS, DOY, ELH, ELS
    3324           0 :     NVAL   = 0
    3325           0 :     LHIDX  = -1
    3326           0 :     LWDIDX = -1
    3327             : 
    3328           0 :     IF ( INDEX(func,'YYYY') > 0 ) THEN
    3329           0 :        NVAL                      = NVAL + 1
    3330           0 :        all_variables(NVAL)       = 'yyyy'
    3331           0 :        all_variablesvalues(NVAL) = prefYr
    3332             :     ENDIF
    3333           0 :     IF ( INDEX(func,'MM') > 0 ) THEN
    3334           0 :        NVAL                      = NVAL + 1
    3335           0 :        all_variables(NVAL)       = 'mm'
    3336           0 :        all_variablesvalues(NVAL) = prefMt
    3337             :     ENDIF
    3338           0 :     IF ( INDEX(func,'DD') > 0 ) THEN
    3339           0 :        NVAL                      = NVAL + 1
    3340           0 :        all_variables(NVAL)       = 'dd'
    3341           0 :        all_variablesvalues(NVAL) = prefDy
    3342             :     ENDIF
    3343           0 :     IF ( INDEX(func,'WD') > 0 ) THEN
    3344           0 :        NVAL                      = NVAL + 1
    3345           0 :        all_variables(NVAL)       = 'wd'
    3346           0 :        all_variablesvalues(NVAL) = prefWD
    3347             :     ENDIF
    3348           0 :     IF ( INDEX(func,'LWD') > 0 ) THEN
    3349           0 :        NVAL                      = NVAL + 1
    3350           0 :        all_variables(NVAL)       = 'lwd'
    3351           0 :        all_variablesvalues(NVAL) = prefWD
    3352           0 :        LWDIDX                    = NVAL
    3353             :     ENDIF
    3354           0 :     IF ( INDEX(func,'HH') > 0 ) THEN
    3355           0 :        NVAL                      = NVAL + 1
    3356           0 :        all_variables(NVAL)       = 'hh'
    3357           0 :        all_variablesvalues(NVAL) = prefHr
    3358             :     ENDIF
    3359           0 :     IF ( INDEX(func,'LH') > 0 ) THEN
    3360           0 :        NVAL                      = NVAL + 1
    3361           0 :        all_variables(NVAL)       = 'lh'
    3362           0 :        all_variablesvalues(NVAL) = prefHr
    3363           0 :        LHIDX                     = NVAL
    3364             :     ENDIF
    3365           0 :     IF ( INDEX(func,'NN') > 0 ) THEN
    3366           0 :        NVAL                      = NVAL + 1
    3367           0 :        all_variables(NVAL)       = 'nn'
    3368           0 :        all_variablesvalues(NVAL) = prefMn
    3369             :     ENDIF
    3370           0 :     IF ( INDEX(func,'SS') > 0 ) THEN
    3371           0 :        NVAL                      = NVAL + 1
    3372           0 :        all_variables(NVAL)       = 'ss'
    3373           0 :        all_variablesvalues(NVAL) = prefS
    3374             :     ENDIF
    3375           0 :     IF ( INDEX(func,'DOY') > 0 ) THEN
    3376           0 :        NVAL                      = NVAL + 1
    3377           0 :        all_variables(NVAL)       = 'doy'
    3378           0 :        all_variablesvalues(NVAL) = prefDOY
    3379             :     ENDIF
    3380           0 :     IF ( INDEX(func,'PI') > 0 ) THEN
    3381           0 :        NVAL                      = NVAL + 1
    3382           0 :        all_variables(NVAL)       = 'pi'
    3383           0 :        all_variablesvalues(NVAL) = HcoState%Phys%PI
    3384             :     ENDIF
    3385           0 :     IF ( INDEX(func,'DOM') > 0 ) THEN
    3386           0 :        NVAL                      = NVAL + 1
    3387           0 :        all_variables(NVAL)       = 'dom'
    3388           0 :        all_variablesvalues(NVAL) = LMD
    3389             :     ENDIF
    3390           0 :     IF ( INDEX(func,'ELH') > 0 ) THEN
    3391           0 :        NVAL                      = NVAL + 1
    3392           0 :        all_variables(NVAL)       = 'elh'
    3393           0 :        all_variablesvalues(NVAL) = ELH
    3394             :     ENDIF
    3395           0 :     IF ( INDEX(func,'ELS') > 0 ) THEN
    3396           0 :        NVAL                      = NVAL + 1
    3397           0 :        all_variables(NVAL)       = 'els'
    3398           0 :        all_variablesvalues(NVAL) = ELS
    3399             :     ENDIF
    3400             : 
    3401             :     ! Error trap: cannot have local hour and local weekday in
    3402             :     ! same expression
    3403           0 :     IF ( LHIDX > 0 .AND. LWDIDX > 0 ) THEN
    3404             :        MSG = 'Cannot have local hour and local weekday in '//&
    3405           0 :              'same expression: '//TRIM(func)
    3406           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    3407           0 :        RETURN
    3408             :     ENDIF
    3409             : 
    3410             :     ! N is the number of expressions.
    3411           0 :     Vals(:) = -999.0_hp
    3412           0 :     IF ( LHIDX > 0 ) THEN
    3413           0 :        N = 24
    3414           0 :     ELSEIF ( LWDIDX > 0 ) THEN
    3415           0 :        N = 7
    3416             :     ELSE
    3417           0 :        N = 1
    3418             :     ENDIF
    3419             : 
    3420             :     ! Evaluate expression
    3421             :     !Initialize function
    3422           0 :     call init (func, all_variables(1:NVAL), statusflag)
    3423           0 :     IF(statusflag == 'ok') THEN
    3424           0 :        DO I=1,N
    3425           0 :           IF ( LHIDX  > 0 ) all_variablesvalues(LHIDX)  = I-1
    3426           0 :           IF ( LWDIDX > 0 ) all_variablesvalues(LWDIDX) = I-1
    3427           0 :           Val = evaluate( all_variablesvalues(1:NVAL) )
    3428           0 :           Vals(I) = Val
    3429             : 
    3430             :           ! Verbose
    3431           0 :           IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    3432           0 :              WRITE(MSG,*) 'Evaluated function: ',TRIM(func),' --> ', Val
    3433           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3434             :           ENDIF
    3435             :        ENDDO
    3436             :     ELSE
    3437           0 :        MSG = 'Error evaluation function: '//TRIM(func)
    3438           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    3439           0 :        RETURN
    3440             :     ENDIF
    3441           0 :     call destroyfunc()
    3442             : 
    3443             :     ! Return w/ success
    3444           0 :     RC = HCO_SUCCESS
    3445             : 
    3446             :   END SUBROUTINE ReadMath
    3447             : !EOC
    3448             : END MODULE HCOIO_Util_Mod

Generated by: LCOV version 1.14