LCOV - code coverage report
Current view: top level - hemco/HEMCO/src/Shared/NcdfUtil - hco_ncdf_mod.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1042 0.0 %
Date: 2024-12-17 17:57:11 Functions: 0 44 0.0 %

          Line data    Source code
       1             : !------------------------------------------------------------------------------
       2             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
       3             : !                      and NASA/GFSC, SIVO, Code 610.3                        !
       4             : !------------------------------------------------------------------------------
       5             : !BOP
       6             : !
       7             : ! !MODULE: HCO_ncdf_mod.F90
       8             : !
       9             : ! !DESCRIPTION: Module HCO\_NCDF\_MOD contains routines to read data from
      10             : ! netCDF files.
      11             : !\\
      12             : !\\
      13             : ! !INTERFACE:
      14             : !
      15             : MODULE HCO_NCDF_MOD
      16             : !
      17             : ! !USES:
      18             : !
      19             :   ! Modules for netCDF read
      20             :   USE netCDF
      21             :   USE HCO_m_netcdf_io_open
      22             :   USE HCO_m_netcdf_io_get_dimlen
      23             :   USE HCO_m_netcdf_io_read
      24             :   USE HCO_m_netcdf_io_readattr
      25             :   USE HCO_m_netcdf_io_close
      26             :   USE HCO_m_netcdf_io_create
      27             :   USE HCO_m_netcdf_io_define
      28             :   USE HCO_m_netcdf_io_write
      29             :   USE HCO_m_netcdf_io_checks
      30             :   USE HCO_PRECISION_MOD, ONLY : SP => f4, DP => f8
      31             : 
      32             :   IMPLICIT NONE
      33             :   PRIVATE
      34             : !
      35             : ! !PUBLIC MEMBER FUNCTIONS:
      36             : !
      37             :   PUBLIC  :: NC_OPEN
      38             :   PUBLIC  :: NC_APPEND
      39             :   PUBLIC  :: NC_CREATE
      40             :   PUBLIC  :: NC_SET_DEFMODE
      41             :   PUBLIC  :: NC_VAR_DEF
      42             :   PUBLIC  :: NC_VAR_CHUNK
      43             :   PUBLIC  :: NC_VAR_WRITE
      44             :   PUBLIC  :: NC_CLOSE
      45             :   PUBLIC  :: NC_READ_TIME
      46             :   PUBLIC  :: NC_READ_TIME_YYYYMMDDhhmm
      47             :   PUBLIC  :: NC_READ_VAR
      48             :   PUBLIC  :: NC_READ_ARR
      49             :   PUBLIC  :: NC_GET_REFDATETIME
      50             :   PUBLIC  :: NC_GET_GRID_EDGES
      51             :   PUBLIC  :: NC_GET_SIGMA_LEVELS
      52             :   PUBLIC  :: NC_WRITE
      53             :   PUBLIC  :: GET_TAU0
      54             : !
      55             : ! !PRIVATE MEMBER FUNCTIONS:
      56             : !
      57             :   PRIVATE :: GET_TIDX
      58             :   PRIVATE :: TIMEUNIT_CHECK
      59             :   PRIVATE :: NC_WRITE_3D
      60             :   PRIVATE :: NC_WRITE_4D
      61             :   PRIVATE :: NC_VAR_WRITE_INT_1D
      62             :   PRIVATE :: NC_VAR_WRITE_INT_2D
      63             :   PRIVATE :: NC_VAR_WRITE_INT_3D
      64             :   PRIVATE :: NC_VAR_WRITE_INT_4D
      65             :   PRIVATE :: NC_VAR_WRITE_R4_1D
      66             :   PRIVATE :: NC_VAR_WRITE_R4_2D
      67             :   PRIVATE :: NC_VAR_WRITE_R4_3D
      68             :   PRIVATE :: NC_VAR_WRITE_R4_4D
      69             :   PRIVATE :: NC_VAR_WRITE_R8_0D
      70             :   PRIVATE :: NC_VAR_WRITE_R8_1D
      71             :   PRIVATE :: NC_VAR_WRITE_R8_2D
      72             :   PRIVATE :: NC_VAR_WRITE_R8_3D
      73             :   PRIVATE :: NC_VAR_WRITE_R8_4D
      74             :   PRIVATE :: NC_READ_VAR_SP
      75             :   PRIVATE :: NC_READ_VAR_DP
      76             :   PRIVATE :: NC_GET_GRID_EDGES_SP
      77             :   PRIVATE :: NC_GET_GRID_EDGES_DP
      78             :   PRIVATE :: NC_GET_GRID_EDGES_C
      79             :   PRIVATE :: NC_GET_SIGMA_LEVELS_SP
      80             :   PRIVATE :: NC_GET_SIGMA_LEVELS_DP
      81             :   PRIVATE :: NC_GET_SIGMA_LEVELS_C
      82             :   PRIVATE :: NC_GET_SIG_FROM_HYBRID
      83             :   PRIVATE :: NC_READ_VAR_CORE
      84             : !
      85             : ! !REVISION HISTORY:
      86             : !  See https://github.com/geoschem/hemco for complete history
      87             : !EOP
      88             : !------------------------------------------------------------------------------
      89             : !BOC
      90             : !
      91             : ! !MODULE INTERFACES:
      92             : !
      93             :   INTERFACE NC_WRITE
      94             :      MODULE PROCEDURE NC_WRITE_3D
      95             :      MODULE PROCEDURE NC_WRITE_4D
      96             :   END INTERFACE NC_WRITE
      97             : 
      98             :   INTERFACE NC_READ_VAR
      99             :      MODULE PROCEDURE NC_READ_VAR_SP
     100             :      MODULE PROCEDURE NC_READ_VAR_DP
     101             :   END INTERFACE NC_READ_VAR
     102             : 
     103             :   INTERFACE NC_GET_GRID_EDGES
     104             :      MODULE PROCEDURE NC_GET_GRID_EDGES_SP
     105             :      MODULE PROCEDURE NC_GET_GRID_EDGES_DP
     106             :   END INTERFACE NC_GET_GRID_EDGES
     107             : 
     108             :   INTERFACE NC_GET_SIGMA_LEVELS
     109             :      MODULE PROCEDURE NC_GET_SIGMA_LEVELS_SP
     110             :      MODULE PROCEDURE NC_GET_SIGMA_LEVELS_DP
     111             :   END INTERFACE NC_GET_SIGMA_LEVELS
     112             : 
     113             :   INTERFACE NC_VAR_WRITE
     114             :      MODULE PROCEDURE NC_VAR_WRITE_INT_0D
     115             :      MODULE PROCEDURE NC_VAR_WRITE_INT_1D
     116             :      MODULE PROCEDURE NC_VAR_WRITE_INT_2D
     117             :      MODULE PROCEDURE NC_VAR_WRITE_INT_3D
     118             :      MODULE PROCEDURE NC_VAR_WRITE_INT_4D
     119             :      MODULE PROCEDURE NC_VAR_WRITE_R4_0D
     120             :      MODULE PROCEDURE NC_VAR_WRITE_R4_1D
     121             :      MODULE PROCEDURE NC_VAR_WRITE_R4_2D
     122             :      MODULE PROCEDURE NC_VAR_WRITE_R4_3D
     123             :      MODULE PROCEDURE NC_VAR_WRITE_R4_4D
     124             :      MODULE PROCEDURE NC_VAR_WRITE_R8_0D
     125             :      MODULE PROCEDURE NC_VAR_WRITE_R8_1D
     126             :      MODULE PROCEDURE NC_VAR_WRITE_R8_2D
     127             :      MODULE PROCEDURE NC_VAR_WRITE_R8_3D
     128             :      MODULE PROCEDURE NC_VAR_WRITE_R8_4D
     129             :   END INTERFACE NC_VAR_WRITE
     130             : 
     131             : CONTAINS
     132             : !EOC
     133             : !------------------------------------------------------------------------------
     134             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     135             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     136             : !------------------------------------------------------------------------------
     137             : !BOP
     138             : !
     139             : ! !IROUTINE: Nc_Open
     140             : !
     141             : ! !DESCRIPTION: Simple wrapper routine to open the given netCDF file.
     142             : !\\
     143             : !\\
     144             : ! !INTERFACE:
     145             : !
     146           0 :   SUBROUTINE NC_OPEN( FileName, fID )
     147             : !
     148             : ! !INPUT PARAMETERS:
     149             : !
     150             :     CHARACTER(LEN=*), INTENT(IN)  :: FileName
     151             : !
     152             : ! !OUTPUT PARAMETERS:
     153             : !
     154             :     INTEGER,          INTENT(OUT) :: fID
     155             : !
     156             : ! !REVISION HISTORY:
     157             : !  See https://github.com/geoschem/hemco for complete history
     158             : !EOP
     159             : !------------------------------------------------------------------------------
     160             : !BOC
     161             :     !=================================================================
     162             :     ! NC_OPEN begins here
     163             :     !=================================================================
     164             : 
     165             :     ! Open netCDF file
     166           0 :     CALL Ncop_Rd( fId, TRIM( FileName ) )
     167             : 
     168           0 :   END SUBROUTINE NC_OPEN
     169             : !EOC
     170             : !------------------------------------------------------------------------------
     171             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     172             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     173             : !------------------------------------------------------------------------------
     174             : !BOP
     175             : !
     176             : ! !IROUTINE: Nc_Append
     177             : !
     178             : ! !DESCRIPTION: Simple wrapper routine to open the given netCDF file.
     179             : !  for appending extra values along a record dimension.
     180             : !\\
     181             : !\\
     182             : ! !INTERFACE:
     183             : !
     184           0 :   SUBROUTINE NC_APPEND( FileName, fID, nTime )
     185             : !
     186             : ! !INPUT PARAMETERS:
     187             : !
     188             :     CHARACTER(LEN=*), INTENT(IN)  :: FileName
     189             : !
     190             : ! !OUTPUT PARAMETERS:
     191             : !
     192             :     INTEGER,          INTENT(OUT) :: fID
     193             :     INTEGER,          OPTIONAL    :: nTime
     194             : !
     195             : ! !REVISION HISTORY:
     196             : !  See https://github.com/geoschem/hemco for complete history
     197             : !EOP
     198             : !------------------------------------------------------------------------------
     199             : !BOC
     200             : !
     201             : ! !LOCAL VARIABLES:
     202             : !
     203             :     INTEGER :: RC, vId
     204             : 
     205             :     !=================================================================
     206             :     ! NC_APPEND begins here
     207             :     !=================================================================
     208             : 
     209             :     ! Open netCDF file
     210           0 :     CALL Ncop_Wr( fId, TRIM(FileName) )
     211             : 
     212             :     ! Also return the number of time slices so that we can
     213             :     ! append to an existing file w/o clobbering any data
     214           0 :     IF ( PRESENT( nTime ) ) THEN
     215           0 :        CALL Ncget_Unlim_Dimlen( fId, nTime )
     216             :     ENDIF
     217             : 
     218           0 :   END SUBROUTINE NC_APPEND
     219             : !EOC
     220             : !------------------------------------------------------------------------------
     221             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     222             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     223             : !------------------------------------------------------------------------------
     224             : !BOP
     225             : !
     226             : ! !IROUTINE: Nc_Close
     227             : !
     228             : ! !DESCRIPTION: Simple wrapper routine to close the given lun.
     229             : !\\
     230             : !\\
     231             : ! !INTERFACE:
     232             : !
     233           0 :   SUBROUTINE NC_CLOSE( fID )
     234             : !
     235             : ! !INPUT PARAMETERS:
     236             : !
     237             :     INTEGER, INTENT(IN   ) :: fID
     238             : !
     239             : ! !REVISION HISTORY:
     240             : !  See https://github.com/geoschem/hemco for complete history
     241             : !EOP
     242             : !------------------------------------------------------------------------------
     243             : !BOC
     244             : 
     245             :     !=================================================================
     246             :     ! NC_CLOSE begins here
     247             :     !=================================================================
     248             : 
     249           0 :     CALL NcCl( fID )
     250             : 
     251           0 :   END SUBROUTINE NC_CLOSE
     252             : !EOC
     253             : !------------------------------------------------------------------------------
     254             : !                  GEOS-Chem Global Chemical Transport Model                  !
     255             : !------------------------------------------------------------------------------
     256             : !BOP
     257             : !
     258             : ! !IROUTINE: Nc_Set_DefMode
     259             : !
     260             : ! !DESCRIPTION: Toggles netCDF define mode on or off.
     261             : !\\
     262             : !\\
     263             : ! !INTERFACE:
     264             : !
     265           0 :   SUBROUTINE Nc_Set_DefMode( fId, On, Off )
     266             : !
     267             : ! !INPUT PARAMETERS:
     268             : !
     269             :     INTEGER, INTENT(IN) :: fId   ! netCDF file ID
     270             :     LOGICAL, OPTIONAL   :: On    ! On=T   will turn on  netCDF define mode
     271             :     LOGICAL, OPTIONAL   :: Off   ! Off=T  will turn off netCDF define mdoe
     272             : !
     273             : ! !REMARKS:
     274             : !  This is a convenience wrapper for routines NcBegin_Def and NcEnd_Def in
     275             : !  NcdfUtil module m_netcdf_define_mod.F90.
     276             : !
     277             : ! !REVISION HISTORY:
     278             : !  See https://github.com/geoschem/hemco for complete history
     279             : !EOP
     280             : !------------------------------------------------------------------------------
     281             : !BOC
     282             : 
     283             :     ! If the ON switch is passed then ...
     284           0 :     IF ( PRESENT( On ) ) THEN
     285           0 :        IF ( On ) THEN
     286           0 :           CALL NcBegin_Def( fId )  ! Turn define mode on
     287           0 :           RETURN
     288             :        ELSE
     289           0 :           CALL NcEnd_Def( fId )    ! Turn define mode off
     290           0 :           RETURN
     291             :        ENDIF
     292             :     ENDIF
     293             : 
     294             :     ! If the OFF switch is passed then ,,,
     295           0 :     IF ( PRESENT( Off ) ) THEN
     296           0 :        IF ( Off ) THEN
     297           0 :           CALL NcEnd_Def( fId )      ! Turn define mode off
     298           0 :           RETURN
     299             :        ELSE
     300           0 :           CALL NcBegin_Def( fId )    ! Turn define mode on
     301           0 :           RETURN
     302             :        ENDIF
     303             :     ENDIF
     304             : 
     305             : 
     306             :   END SUBROUTINE Nc_Set_DefMode
     307             : !EOC
     308             : !------------------------------------------------------------------------------
     309             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     310             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     311             : !------------------------------------------------------------------------------
     312             : !BOP
     313             : !
     314             : ! !IROUTINE: Nc_Read_Time
     315             : !
     316             : ! !DESCRIPTION: Subroutine NC\_READ\_TIME reads the time variable of the
     317             : ! given fID and returns the time slices and unit.
     318             : !\\
     319             : !\\
     320             : ! !INTERFACE:
     321             : !
     322           0 :   SUBROUTINE NC_READ_TIME( fID,     nTime,        timeUnit, &
     323             :                            timeVec, timeCalendar, RC       )
     324             : !
     325             : ! !INPUT PARAMETERS:
     326             : !
     327             :     INTEGER,          INTENT(IN   )            :: fID
     328             : !
     329             : ! !OUTPUT PARAMETERS:
     330             : !
     331             :     INTEGER,          INTENT(  OUT)            :: nTime
     332             :     CHARACTER(LEN=*), INTENT(  OUT)            :: timeUnit
     333             :     REAL*8,           POINTER,       OPTIONAL  :: timeVec(:)
     334             :     CHARACTER(LEN=*), INTENT(  OUT), OPTIONAL  :: timeCalendar
     335             : !
     336             : ! !INPUT/OUTPUT PARAMETERS:
     337             : !
     338             :     INTEGER,          INTENT(INOUT)            :: RC
     339             : !
     340             : ! !REVISION HISTORY:
     341             : !  See https://github.com/geoschem/hemco for complete history
     342             : !EOP
     343             : !------------------------------------------------------------------------------
     344             : !BOC
     345             : !
     346             : ! !LOCAL VARIABLES:
     347             : !
     348             :     ! Scalars
     349             :     LOGICAL                :: hasTime
     350             :     CHARACTER(LEN=255)     :: v_name             ! netCDF variable name
     351             :     CHARACTER(LEN=255)     :: a_name             ! netCDF attribute name
     352             :     CHARACTER(LEN=255)     :: a_val              ! netCDF attribute value
     353             :     INTEGER                :: st1d(1), ct1d(1)   ! For 1D arrays
     354             : 
     355             :     ! Arrays
     356           0 :     REAL*8 , ALLOCATABLE   :: tmpTime(:)
     357             : 
     358             :     !=================================================================
     359             :     ! NC_READ_TIME begins here
     360             :     !=================================================================
     361             : 
     362             :     ! Init
     363           0 :     RC      = 0
     364           0 :     nTime   = 0
     365           0 :     hasTime = .FALSE.
     366             : 
     367             :     ! Variable name
     368           0 :     v_name = "time"
     369             : 
     370             :     ! Check if dimension "time" exist
     371           0 :     hasTime = Ncdoes_Dim_Exist ( fID, TRIM(v_name) )
     372             : 
     373             :     ! If time dim not found, also check for dimension "date"
     374           0 :     IF ( .NOT. hasTime ) THEN
     375           0 :        v_name   = "date"
     376           0 :        hasTime = Ncdoes_Dim_Exist ( fID, TRIM(v_name) )
     377             :     ENDIF
     378             : 
     379             :     ! Return here if no time variable defined
     380           0 :     IF ( .NOT. hasTime ) RETURN
     381             : 
     382             :     ! Get dimension length
     383           0 :     CALL Ncget_Dimlen ( fID, TRIM(v_name), nTime )
     384             : 
     385             :     ! Read time/date units attribute
     386           0 :     a_name = "units"
     387             :     CALL NcGet_Var_Attributes( fID,          TRIM(v_name), &
     388           0 :                                TRIM(a_name), timeUnit     )
     389             : 
     390             :     ! Read time vector from file.
     391           0 :     IF ( PRESENT(timeVec) ) THEN
     392           0 :        IF ( ASSOCIATED(timeVec) ) DEALLOCATE ( timeVec)
     393           0 :        ALLOCATE ( tmpTime(nTime) )
     394           0 :        ALLOCATE ( timeVec(nTime) )
     395           0 :        st1d = (/ 1     /)
     396           0 :        ct1d = (/ nTime /)
     397           0 :        CALL NcRd( tmpTime, fID, TRIM(v_name), st1d, ct1d )
     398           0 :        timevec(:) = tmpTime
     399           0 :        DEALLOCATE(tmpTime)
     400             :     ENDIF
     401             : 
     402             :     ! Read calendar attribute
     403           0 :     IF ( PRESENT( timeCalendar ) ) THEN
     404             : 
     405             :        ! We now get the status variable RC.  This will allow program
     406             :        ! flow to continue if the "time:calendar" attribute is not found.
     407           0 :        CALL NcGet_Var_Attributes( fId, v_name, 'calendar', timeCalendar, RC )
     408             : 
     409             :        ! If "time:calendar" is found, then throw an error for
     410             :        ! climatological calendars without leap years.
     411           0 :        IF ( RC == 0 ) THEN
     412           0 :         SELECT CASE( TRIM( v_name ) )
     413             :           CASE( '360_day', '365_day', '366_day', 'all_leap',                 &
     414             :                 'allleap', 'no_leap', 'noleap'                              )
     415           0 :              WRITE( 6, '(/,a)' ) REPEAT( '=', 79 )
     416             :              WRITE( 6, '(a  )' ) 'HEMCO does not support calendar type '  // &
     417           0 :                                  TRIM( v_name )
     418           0 :              WRITE( 6, '(/,a)' )  'HEMCO supports the following calendars:'
     419           0 :              WRITE( 6, '(a)'   )  ' - standard (i.e. mixed gregorian/julian)'
     420           0 :              WRITE( 6, '(a)'   )  ' - gregorian'
     421           0 :              WRITE( 6, '(a,/)' ) REPEAT( '=', 79 )
     422           0 :              RC = -1
     423             :           CASE DEFAULT
     424             :              ! Do nothing
     425             :         END SELECT
     426             :        ENDIF
     427             : 
     428             :        ! Reset RC so that we won't halt execution elsewhere
     429           0 :        RC = 0
     430             :     ENDIF
     431             : 
     432           0 :   END SUBROUTINE NC_READ_TIME
     433             : !EOC
     434             : !------------------------------------------------------------------------------
     435             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     436             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     437             : !------------------------------------------------------------------------------
     438             : !BOP
     439             : !
     440             : ! !IROUTINE: Nc_Read_Var_Sp
     441             : !
     442             : ! !DESCRIPTION: Subroutine NC\_READ\_VAR\_SP reads the given variable from the
     443             : ! given fID and returns the corresponding variable values and units.
     444             : !\\
     445             : !\\
     446             : ! !INTERFACE:
     447             : !
     448           0 :   SUBROUTINE NC_READ_VAR_SP( fID, Var, nVar, varUnit, varVec, RC )
     449             : !
     450             : ! !INPUT PARAMETERS:
     451             : !
     452             :     INTEGER,          INTENT(IN   )            :: fID
     453             :     CHARACTER(LEN=*), INTENT(IN   )            :: var
     454             : !
     455             : ! !OUTPUT PARAMETERS:
     456             : !
     457             :     INTEGER,          INTENT(  OUT)            :: nVar
     458             :     CHARACTER(LEN=*), INTENT(  OUT)            :: varUnit
     459             :     REAL*4,           POINTER                  :: varVec(:)
     460             : !
     461             : ! !INPUT/OUTPUT PARAMETERS:
     462             : !
     463             :     INTEGER,          INTENT(INOUT)            :: RC
     464             : !
     465             : ! !REVISION HISTORY:
     466             : !  See https://github.com/geoschem/hemco for complete history
     467             : !EOP
     468             : !------------------------------------------------------------------------------
     469             : !BOC
     470             : 
     471           0 :     CALL NC_READ_VAR_CORE( fID, Var, nVar, varUnit, varVecSp=varVec, RC=RC )
     472             : 
     473           0 :   END SUBROUTINE NC_READ_VAR_SP
     474             : !EOC
     475             : !------------------------------------------------------------------------------
     476             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     477             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     478             : !------------------------------------------------------------------------------
     479             : !BOP
     480             : !
     481             : ! !IROUTINE: Nc_Read_Var_Dp
     482             : !
     483             : ! !DESCRIPTION: Subroutine NC\_READ\_VAR\_DP reads the given variable from the
     484             : ! given fID and returns the corresponding variable values and units.
     485             : !\\
     486             : !\\
     487             : ! !INTERFACE:
     488             : !
     489           0 :   SUBROUTINE NC_READ_VAR_DP( fID, Var, nVar, varUnit, varVec, RC )
     490             : !
     491             : ! !INPUT PARAMETERS:
     492             : !
     493             :     INTEGER,          INTENT(IN   )            :: fID
     494             :     CHARACTER(LEN=*), INTENT(IN   )            :: var
     495             : !
     496             : ! !OUTPUT PARAMETERS:
     497             : !
     498             :     INTEGER,          INTENT(  OUT)            :: nVar
     499             :     CHARACTER(LEN=*), INTENT(  OUT)            :: varUnit
     500             :     REAL*8,           POINTER                  :: varVec(:)
     501             : !
     502             : ! !INPUT/OUTPUT PARAMETERS:
     503             : !
     504             :     INTEGER,          INTENT(INOUT)            :: RC
     505             : !
     506             : ! !REVISION HISTORY:
     507             : !  See https://github.com/geoschem/hemco for complete history
     508             : !EOP
     509             : !------------------------------------------------------------------------------
     510             : !BOC
     511             : 
     512           0 :     CALL NC_READ_VAR_CORE( fID, Var, nVar, varUnit, varVecDp=varVec, RC=RC )
     513             : 
     514           0 :   END SUBROUTINE NC_READ_VAR_DP
     515             : !EOC
     516             : !------------------------------------------------------------------------------
     517             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     518             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     519             : !------------------------------------------------------------------------------
     520             : !BOP
     521             : !
     522             : ! !IROUTINE: Nc_Read_Var_Core
     523             : !
     524             : ! !DESCRIPTION: Subroutine NC\_READ\_VAR\_CORE reads the given variable from the
     525             : ! given fID and returns the corresponding variable values and units.
     526             : !\\
     527             : !\\
     528             : ! !INTERFACE:
     529             : !
     530           0 :   SUBROUTINE NC_READ_VAR_CORE( fID, Var, nVar, varUnit, varVecDp, varVecSp, RC )
     531             : !
     532             : ! !INPUT PARAMETERS:
     533             : !
     534             :     INTEGER,          INTENT(IN   )            :: fID
     535             :     CHARACTER(LEN=*), INTENT(IN   )            :: var
     536             : !
     537             : ! !OUTPUT PARAMETERS:
     538             : !
     539             :     INTEGER,          INTENT(  OUT)            :: nVar
     540             :     CHARACTER(LEN=*), INTENT(  OUT)            :: varUnit
     541             :     REAL*4,           POINTER,       OPTIONAL  :: varVecSp(:)
     542             :     REAL*8,           POINTER,       OPTIONAL  :: varVecDp(:)
     543             : !
     544             : ! !INPUT/OUTPUT PARAMETERS:
     545             : !
     546             :     INTEGER,          INTENT(INOUT)            :: RC
     547             : !
     548             : ! !REVISION HISTORY:
     549             : !  See https://github.com/geoschem/hemco for complete history
     550             : !EOP
     551             : !------------------------------------------------------------------------------
     552             : !BOC
     553             : !
     554             : ! !LOCAL VARIABLES:
     555             : !
     556             :     LOGICAL                :: hasVar
     557             :     CHARACTER(LEN=255)     :: v_name             ! netCDF variable name
     558             :     CHARACTER(LEN=255)     :: a_name             ! netCDF attribute name
     559             :     CHARACTER(LEN=255)     :: a_val              ! netCDF attribute value
     560             :     INTEGER                :: a_type             ! netCDF attribute type
     561             :     INTEGER                :: st1d(1), ct1d(1)   ! For 1D arrays
     562             :     INTEGER                :: I
     563             : 
     564             :     !=================================================================
     565             :     ! NC_READ_VAR_CORE begins here
     566             :     !=================================================================
     567             : 
     568             :     ! Init
     569           0 :     RC      = 0
     570           0 :     nVar    = 0
     571           0 :     hasVar  = .FALSE.
     572             : 
     573             :     ! Variable name
     574           0 :     v_name = var
     575             : 
     576             :     ! Check if variable exists
     577           0 :     hasVar = Ncdoes_Dim_Exist ( fID, TRIM(v_name) )
     578             : 
     579             :     ! Return here if variable not defined
     580           0 :     IF ( .NOT. hasVar ) RETURN
     581             : 
     582             :     ! Get dimension length
     583           0 :     CALL Ncget_Dimlen ( fID, TRIM(v_name), nVar )
     584             : 
     585             :     ! Read vector from file.
     586           0 :     IF ( PRESENT(VarVecSp) ) THEN
     587           0 :        IF ( ASSOCIATED( VarVecSp ) ) DEALLOCATE(VarVecSp)
     588           0 :        ALLOCATE ( VarVecSp(nVar) )
     589           0 :        st1d = (/ 1    /)
     590           0 :        ct1d = (/ nVar /)
     591           0 :        CALL NcRd( VarVecSp, fID, TRIM(v_name), st1d, ct1d )
     592             :     ENDIF
     593           0 :     IF ( PRESENT(VarVecDp) ) THEN
     594           0 :        IF ( ASSOCIATED( VarVecDp ) ) DEALLOCATE(VarVecDp)
     595           0 :        ALLOCATE ( VarVecDp(nVar) )
     596           0 :        st1d = (/ 1    /)
     597           0 :        ct1d = (/ nVar /)
     598           0 :        CALL NcRd( VarVecDp, fID, TRIM(v_name), st1d, ct1d )
     599             :     ENDIF
     600             : 
     601             :     ! Read units attribute. If unit attribute does not exist, return
     602             :     ! empty string (dimensionless vertical coordinates do not require
     603             :     ! a units attribute).
     604           0 :     a_name  = "units"
     605           0 :     hasVar  = Ncdoes_Attr_Exist ( fId, TRIM(v_name), TRIM(a_name), a_type )
     606           0 :     IF ( .NOT. hasVar ) THEN
     607           0 :        varUnit = ''
     608             :     ELSE
     609             :        CALL NcGet_Var_Attributes( fID,          TRIM(v_name), &
     610           0 :                                   TRIM(a_name), varUnit     )
     611             : 
     612             :        ! Check if the last character of VarUnit is the ASCII null character
     613             :        ! ("\0", ASCII value = 0), which is used to denote the end of a string.
     614             :        ! The ASCII null character may be introduced if the netCDF file was
     615             :        ! written using a language other than Fortran.  The compiler might
     616             :        ! interpret the null character as part of the string instead of as
     617             :        ! an empty space.  If the null space is there, then replace it with
     618             :        ! a Fortran empty string value (''). (bmy, 7/17/18)
     619           0 :        I = LEN_TRIM( VarUnit )
     620           0 :        IF ( ICHAR( VarUnit(I:I) ) == 0 ) THEN
     621           0 :           VarUnit(I:I) = ''
     622             :        ENDIF
     623             :     ENDIF
     624             : 
     625           0 :   END SUBROUTINE NC_READ_VAR_CORE
     626             : !EOC
     627             : !------------------------------------------------------------------------------
     628             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
     629             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
     630             : !------------------------------------------------------------------------------
     631             : !BOP
     632             : !
     633             : ! !IROUTINE: Nc_Read_Arr
     634             : !
     635             : ! !DESCRIPTION: Routine NC\_READ\_ARR reads variable ncVar into a 4-D array
     636             : ! (lon,lat,lev,time). Domain boundaries can be provided by input arguments
     637             : ! lon1,lon2, lat1,lat2, lev1,lev2, and time1,time2. The level and time bounds
     638             : ! are optional and can be set to zero (lev1=0 and/or time1=0) for data with
     639             : ! undefined level/time coordinates.
     640             : !\\
     641             : !\\
     642             : ! The default behavior for time slices is to read all slices (time1:time2),
     643             : ! and pass all of them to the output array. It is also possible to assign
     644             : ! specific weights (wgt1 and wgt2) to the two time slices time1 and time2,
     645             : ! respectively. In this case, only those two slices will be read and merged
     646             : ! using the given weights. The output array will then contain only one time
     647             : ! dimension. Negative weights are currently not supported and will be ignored,
     648             : ! e.g. providing negative weights has the same effect as providing no weights
     649             : ! at all.
     650             : !\\
     651             : !\\
     652             : ! If the passed variable contains attribute names `offset` and/or
     653             : ! `scale\_factor`, those operations will be applied to the data array
     654             : ! before returning it.
     655             : !\\
     656             : !\\
     657             : ! Missing values in the netCDF file are replaced with value 'MissVal'
     658             : ! (default = 0). Currently, the routine identifies attributes 'missing\_value'
     659             : ! and '\_FillValue' as missing values.
     660             : !\\
     661             : !\\
     662             : ! !INTERFACE:
     663             : !
     664           0 :   SUBROUTINE NC_READ_ARR( fID,    ncVar,   lon1,    lon2,  lat1,  &
     665             :                           lat2,   lev1,    lev2,    time1, time2, &
     666             :                           ncArr,  VarUnit, MissVal, wgt1,  wgt2,  &
     667             :                           ArbIdx, RC                               )
     668             : !
     669             : ! !USES:
     670             : !
     671             :     USE HCO_CHARPAK_MOD, ONLY : TRANLC
     672             : !
     673             : ! !INPUT PARAMETERS:
     674             : !
     675             :     INTEGER,          INTENT(IN)            :: fID
     676             :     CHARACTER(LEN=*), INTENT(IN)            :: ncVar        ! variable to read
     677             :     INTEGER,          INTENT(IN)            :: lon1,  lon2
     678             :     INTEGER,          INTENT(IN)            :: lat1,  lat2
     679             :     INTEGER,          INTENT(IN)            :: lev1,  lev2
     680             :     INTEGER,          INTENT(IN)            :: time1, time2
     681             :     REAL*4,           INTENT(IN ), OPTIONAL :: MissVal
     682             :     REAL*4,           INTENT(IN ), OPTIONAL :: wgt1
     683             :     REAL*4,           INTENT(IN ), OPTIONAL :: wgt2
     684             :     INTEGER,          INTENT(IN ), OPTIONAL :: ArbIdx      ! Index of arbitrary additional dimension (-1 if none)
     685             : !
     686             : ! !OUTPUT PARAMETERS:
     687             : !
     688             :     ! Array to write data
     689             :     REAL*4,           POINTER               :: ncArr(:,:,:,:)
     690             : 
     691             :     ! Optional output
     692             :     CHARACTER(LEN=*), INTENT(OUT), OPTIONAL :: VarUnit
     693             : !
     694             : ! !INPUT/OUTPUT PARAMETERS:
     695             : !
     696             :     ! Error handling
     697             :     INTEGER,          INTENT(INOUT)         :: RC
     698             : !
     699             : ! !REVISION HISTORY:
     700             : !  See https://github.com/geoschem/hemco for complete history
     701             : !EOP
     702             : !------------------------------------------------------------------------------
     703             : !BOC
     704             : !
     705             : ! !LOCAL VARIABLES:
     706             : !
     707             :     !=================================================================
     708             :     ! Variable declarations
     709             :     !=================================================================
     710             : 
     711             :     ! Data arrays
     712             :     CHARACTER(LEN=255)     :: v_name    ! netCDF variable name
     713             :     CHARACTER(LEN=255)     :: a_name    ! netCDF attribute name
     714             :     CHARACTER(LEN=255)     :: a_val     ! netCDF attribute value
     715             :     INTEGER                :: a_type    ! netCDF attribute type
     716             :     REAL*8                 :: corr      ! netCDF attribute value
     717             : 
     718             :     ! Arrays for netCDF start and count values
     719             :     INTEGER                :: I, nRead, l1, l2
     720             :     INTEGER                :: ndims
     721             :     INTEGER                :: nlon,  nlat, nlev, ntime, arbdim
     722             :     INTEGER                :: nclev, nctime
     723             :     INTEGER                :: s1, s2, s3, s4, s5
     724             :     INTEGER                :: n1, n2, n3, n4, n5
     725             :     INTEGER                :: nt, st, tdim, sti, nti
     726             :     INTEGER                :: st2d(2), ct2d(2)   ! For 2D arrays
     727             :     INTEGER                :: st3d(3), ct3d(3)   ! For 3D arrays
     728             :     INTEGER                :: st4d(4), ct4d(4)   ! For 4D arrays
     729             :     INTEGER                :: st5d(5), ct5d(5)   ! For 5D arrays
     730             : 
     731             :     ! Temporary arrays
     732           0 :     REAL*4, ALLOCATABLE    :: TMPARR_5D(:,:,:,:,:)
     733           0 :     REAL*4, ALLOCATABLE    :: WGTARR_5D(:,:,:,:,:)
     734           0 :     REAL*4, ALLOCATABLE    :: TMPARR_4D(:,:,:,:)
     735           0 :     REAL*4, ALLOCATABLE    :: WGTARR_4D(:,:,:,:)
     736           0 :     REAL*4, ALLOCATABLE    :: TMPARR_3D(:,:,:)
     737           0 :     REAL*4, ALLOCATABLE    :: WGTARR_3D(:,:,:)
     738           0 :     REAL*4, ALLOCATABLE    :: TMPARR_2D(:,:)
     739             : 
     740             :     ! Logicals
     741             :     LOGICAL                :: FlipZ
     742             :     LOGICAL                :: ReadAtt
     743             : 
     744             :     ! Missing value
     745             :     REAL*8                 :: miss8
     746             :     REAL*4                 :: miss4
     747             :     REAL*4                 :: MissValue
     748             : 
     749             :     ! Weights
     750             :     LOGICAL                :: ApplyWeights
     751             :     REAL*4                 :: weight1, weight2
     752             : 
     753             :     ! For error handling
     754             :     CHARACTER(LEN=255)     :: LOC, MSG
     755             : 
     756             :     !=================================================================
     757             :     ! NC_READ_ARR begins here
     758             :     !=================================================================
     759             : 
     760             :     !-----------------------------------------------------------------
     761             :     ! Initialize
     762             :     !-----------------------------------------------------------------
     763             : 
     764             :     ! For error handling
     765           0 :     LOC = 'NC_READ_ARR ("ncdf_mod.F")'
     766             : 
     767             :     ! Eventually deallocate output array
     768           0 :     IF ( ASSOCIATED ( ncArr ) ) DEALLOCATE ( ncArr )
     769             : 
     770             :     ! weights to be applied to time1 and time2 (if any):
     771           0 :     weight1 = -999.0
     772           0 :     weight2 = -999.0
     773           0 :     IF(PRESENT(wgt1)) weight1 = wgt1
     774           0 :     IF(PRESENT(wgt2)) weight2 = wgt2
     775             : 
     776             :     ! apply weights?
     777           0 :     IF ( time1 > 0 .AND. weight1 >= 0.0 ) THEN
     778             :        ApplyWeights = .TRUE.
     779             :     ELSE
     780           0 :        ApplyWeights = .FALSE.
     781             :     ENDIF
     782             : 
     783             :     ! # of horizontal dimensions to read
     784           0 :     nLon = lon2 - lon1 + 1
     785           0 :     nLat = lat2 - lat1 + 1
     786             : 
     787             :     ! # of vertical levels
     788           0 :     FlipZ = .FALSE. ! Flip z-axis?
     789           0 :     l1    = lev1    ! Lower level to be read
     790           0 :     l2    = lev2    ! Upper level to be read
     791           0 :     IF ( lev1 > 0 ) THEN
     792             : 
     793             :        ! Check if we need to flip the vertical axis
     794           0 :        IF ( lev1 > lev2 ) THEN
     795           0 :           FlipZ = .TRUE.
     796           0 :           l1    = lev2
     797           0 :           l2    = lev1
     798             :        ENDIF
     799             : 
     800             :        ! Number of levels to be read
     801           0 :        nLev = l2 - l1 + 1
     802             : 
     803             :     ! no vertical levels:
     804             :     ELSE
     805             :        nLev = 0
     806             :     ENDIF
     807             : 
     808             :     ! # of time slices
     809             :     ! read all time slices time1:time2:
     810           0 :     IF ( time1 > 0 .AND. weight1 < 0.0 ) THEN
     811           0 :        ntime = time2 - time1 + 1
     812             :     ! Interpolate amongs 2 time slices:
     813           0 :     ELSEIF ( ApplyWeights ) THEN
     814             :        ntime = 1
     815             :     ! no time dimension:
     816             :     ELSE
     817           0 :        ntime = 0
     818             :     ENDIF
     819             : 
     820             :     ! # of arbitrary other dimensions
     821           0 :     arbdim = -1
     822           0 :     IF ( PRESENT(ArbIdx) ) THEN
     823           0 :        IF ( ArbIdx > 0 ) THEN
     824           0 :           arbdim = ArbIdx
     825             :        ENDIF
     826             :     ENDIF
     827             : 
     828             :     ! Set dimensions of output array
     829             :     ! --> must have at least dimension 1
     830           0 :     nclev  = max(nlev ,1)
     831           0 :     nctime = max(ntime,1)
     832             : 
     833             :     ! set total number of dimensions to be read. This is at least 2 and
     834             :     ! at most 5.
     835           0 :     ndims = 2
     836           0 :     if ( nlev   > 0 ) ndims = ndims + 1
     837           0 :     if ( ntime  > 0 ) ndims = ndims + 1
     838           0 :     if ( arbdim > 0 ) ndims = ndims + 1
     839             : 
     840             :     !----------------------------------------
     841             :     ! Read array
     842             :     !----------------------------------------
     843             : 
     844             :     ! Variable name
     845           0 :     v_name = TRIM(ncVar)
     846             : 
     847             :     ! Allocate the output array
     848           0 :     ALLOCATE ( ncArr( nLon, nLat, ncLev, ncTime ) )
     849           0 :     ncArr = 0.0
     850             : 
     851             :     ! Define number of required reads and time dimension on temporary array
     852           0 :     nRead = 1
     853           0 :     IF ( ntime > 0 ) THEN
     854           0 :        IF ( ApplyWeights ) THEN
     855             :           nRead = 2
     856             :           nt    = 2
     857             :        ELSE
     858           0 :           nRead = 1
     859           0 :           nt    = ntime
     860             :        ENDIF
     861             :     ENDIF
     862             : 
     863             :     !----------------------------------------
     864             :     ! Read 5D array:
     865           0 :     IF ( ndims == 5 ) THEN
     866             : 
     867             :        ! Allocate array. If time weights are applied, the two
     868             :        ! time slices are read into TMPARR_5D and then temporarily
     869             :        ! stored in WGTARR_5D. Same applies to 4D and 3D below.
     870             :        ! (ckeller, 01/09/17)
     871           0 :        IF ( ApplyWeights ) THEN
     872           0 :           ALLOCATE ( TMPARR_5D( nlon, nlat, nlev, 1, 1 ) )
     873           0 :           TMPARR_5D = 0.0
     874           0 :           ALLOCATE ( WGTARR_5D( nlon, nlat, nlev, nt, 1 ) )
     875           0 :           WGTARR_5D = 0.0
     876             :        ELSE
     877           0 :           ALLOCATE ( TMPARR_5D( nlon, nlat, nlev, nt, 1 ) )
     878           0 :           TMPARR_5D = 0.0
     879             :        ENDIF
     880             : 
     881             :        ! Set default start/end indeces
     882           0 :        s1 = lon1
     883           0 :        n1 = nlon
     884           0 :        s2 = lat1
     885           0 :        n2 = nlat
     886           0 :        s3 = l1
     887           0 :        n3 = nlev
     888             :        s5 = arbdim
     889             :        n5 = 1
     890             : 
     891             :        ! Read arrays from file
     892           0 :        DO I = 1, nRead
     893             : 
     894             :           ! time index
     895           0 :           IF ( .NOT. ApplyWeights ) THEN
     896             :              s4 = time1
     897             :              n4 = ntime
     898             :           ELSE
     899           0 :              IF ( I == 1 ) THEN
     900             :                 s4 = time1
     901             :              ELSE
     902           0 :                 s4 = time2
     903             :              ENDIF
     904             :              n4 = 1
     905             :           ENDIF
     906             : 
     907           0 :           st5d = (/ s1, s2, s3, s4, s5 /)
     908           0 :           ct5d = (/ n1, n2, n3, n4, n5 /)
     909           0 :           CALL NcRd( TMPARR_5D, fId, TRIM(v_name), st5d, ct5d )
     910             : 
     911             :           ! Eventually pass time weighted arrays to temporary array
     912           0 :           IF ( ApplyWeights ) THEN
     913           0 :              WGTARR_5D(:,:,:,I,:) = TMPARR_5D(:,:,:,1,:)
     914             :           ENDIF
     915             : 
     916             :        ENDDO
     917             : 
     918             :        ! Pass to output array. Eventually apply time weights.
     919           0 :        IF ( ApplyWeights ) THEN
     920           0 :           ncArr(:,:,:,1) = WGTARR_5D(:,:,:,1,1) * weight1 &
     921           0 :                          + WGTARR_5D(:,:,:,2,1) * weight2
     922             :        ELSE
     923           0 :           ncArr(:,:,:,:) = TMPARR_5D(:,:,:,:,1)
     924             :        ENDIF
     925             : 
     926             :        ! Cleanup
     927           0 :        DEALLOCATE(TMPARR_5D)
     928           0 :        IF(ALLOCATED(WGTARR_5D)) DEALLOCATE(WGTARR_5D)
     929             :     ENDIF
     930             : 
     931             :     !----------------------------------------
     932             :     ! Read 4D array:
     933             :     ! This can be:
     934             :     ! - lon,lat,lev,time
     935             :     ! - lon,lat,lev,arb
     936             :     ! - lon,lat,time,arb
     937           0 :     IF ( ndims == 4 ) THEN
     938             : 
     939             :        ! Allocate temporary array
     940           0 :        s1    = lon1
     941           0 :        n1    = nlon
     942           0 :        s2    = lat1
     943           0 :        n2    = nlat
     944           0 :        tdim  = -1
     945             : 
     946             :        ! 3rd and 4th dim
     947             : 
     948             :        ! lev is defined
     949           0 :        IF ( nlev > 0 ) THEN
     950           0 :           s3   = l1
     951           0 :           n3   = nlev
     952             :           ! plus time...
     953           0 :           IF ( ntime > 0 ) THEN
     954             :              n4   = nt
     955             :              tdim = 4
     956             :           ! ... or plus arbitrary dim
     957             :           ELSE
     958           0 :              s4 = arbdim
     959           0 :              n4 = 1
     960             :           ENDIF
     961             : 
     962             :        ! lev not defined: time + arbitrary dim
     963             :        ELSE
     964             :           n3 = nt
     965             :           tdim = 3
     966             :           s4 = arbdim
     967             :           n4 = 1
     968             :        ENDIF
     969             : 
     970           0 :        IF ( ApplyWeights ) THEN
     971           0 :           ALLOCATE ( WGTARR_4D(n1,n2,n3,n4) )
     972           0 :           WGTARR_4D = 0.0
     973           0 :           IF ( tdim == 3 ) THEN
     974           0 :              ALLOCATE ( TMPARR_4D(n1,n2,1,n4) )
     975           0 :              TMPARR_4D = 0.0
     976           0 :           ELSEIF ( tdim == 4 ) THEN
     977           0 :              ALLOCATE ( TMPARR_4D(n1,n2,n3,1) )
     978           0 :              TMPARR_4D = 0.0
     979             :           ENDIF
     980             : 
     981             :        ELSE
     982           0 :           ALLOCATE ( TMPARR_4D(n1,n2,n3,n4) )
     983           0 :           TMPARR_4D = 0.0
     984             :        ENDIF
     985             : 
     986             :        ! Read arrays from file
     987           0 :        DO I = 1, nRead
     988             : 
     989             :           ! time index
     990           0 :           IF ( .NOT. ApplyWeights ) THEN
     991             :              sti = time1
     992             :              nti = ntime
     993             :           ELSE
     994           0 :              IF ( I == 1 ) THEN
     995             :                 sti = time1
     996             :              ELSE
     997           0 :                 sti = time2
     998             :              ENDIF
     999             :              nti = 1
    1000             :           ENDIF
    1001             : 
    1002             :           ! need to adjust time index: this is either 3rd or 4th dimension:
    1003           0 :           IF ( tdim == 3 ) THEN
    1004             :              s3 = sti
    1005             :              n3 = nti
    1006           0 :           ELSEIF ( tdim == 4 ) THEN
    1007           0 :              s4 = sti
    1008           0 :              n4 = nti
    1009             :           ENDIF
    1010             : 
    1011           0 :           st4d = (/ s1, s2, s3, s4 /)
    1012           0 :           ct4d = (/ n1, n2, n3, n4 /)
    1013             : 
    1014             :           ! Read data from disk
    1015           0 :           CALL NcRd( TMPARR_4D, fId, TRIM(v_name), st4d, ct4d )
    1016             : 
    1017             :           ! Eventually pass time weighted arrays to temporary array
    1018           0 :           IF ( ApplyWeights ) THEN
    1019           0 :              IF ( tdim == 3 ) THEN
    1020           0 :                 WGTARR_4D(:,:,I,:) = TMPARR_4D(:,:,1,:)
    1021           0 :              ELSEIF ( tdim == 4 ) THEN
    1022           0 :                 WGTARR_4D(:,:,:,I) = TMPARR_4D(:,:,:,1)
    1023             :              ENDIF
    1024             :           ENDIF
    1025             :        ENDDO
    1026             : 
    1027             :        ! Pass to output array. Eventually apply time weights.
    1028           0 :        IF ( ApplyWeights ) THEN
    1029           0 :           IF ( tdim == 3 ) THEN
    1030           0 :              ncArr(:,:,:,1) = WGTARR_4D(:,:,1,:) * weight1 &
    1031           0 :                             + WGTARR_4D(:,:,2,:) * weight2
    1032           0 :           ELSEIF ( tdim == 4 ) THEN
    1033           0 :              ncArr(:,:,:,1) = WGTARR_4D(:,:,:,1) * weight1 &
    1034           0 :                             + WGTARR_4D(:,:,:,2) * weight2
    1035             :           ENDIF
    1036             :        ELSE
    1037           0 :           ncArr(:,:,:,:) = TMPARR_4D(:,:,:,:)
    1038             :        ENDIF
    1039             : 
    1040             :        ! Cleanup
    1041           0 :        DEALLOCATE(TMPARR_4D)
    1042           0 :        IF(ALLOCATED(WGTARR_4D)) DEALLOCATE(WGTARR_4D)
    1043             :     ENDIF
    1044             : 
    1045             :     !----------------------------------------
    1046             :     ! Read 3D array:
    1047             :     ! This can be:
    1048             :     ! - lon,lat,lev
    1049             :     ! - lon,lat,time
    1050             :     ! - lon,lat,arb
    1051           0 :     IF ( ndims == 3 ) THEN
    1052             : 
    1053             :        ! Allocate temporary array
    1054           0 :        s1    = lon1
    1055           0 :        n1    = nlon
    1056           0 :        s2    = lat1
    1057           0 :        n2    = nlat
    1058           0 :        tdim  = -1
    1059             : 
    1060             :        ! 3rd dim:
    1061             :        ! - lev is defined:
    1062           0 :        IF ( nlev > 0 ) THEN
    1063             :           s3   = l1
    1064             :           n3   = nlev
    1065             :        ! - time is defined:
    1066           0 :        ELSEIF ( ntime > 0 ) THEN
    1067             :           n3   = nt
    1068             :           tdim = 3
    1069             :        ! - arbitrary dimension is defined:
    1070           0 :        ELSEIF ( arbdim > 0 ) THEN
    1071           0 :           s3   = arbdim
    1072           0 :           n3   = 1
    1073             :        ENDIF
    1074             : 
    1075           0 :        IF ( ApplyWeights ) THEN
    1076           0 :           ALLOCATE ( TMPARR_3D(n1,n2,1) )
    1077           0 :           TMPARR_3D = 0.0
    1078           0 :           ALLOCATE ( WGTARR_3D(n1,n2,n3) )
    1079           0 :           WGTARR_3D = 0.0
    1080             :        ELSE
    1081           0 :           ALLOCATE ( TMPARR_3D(n1,n2,n3) )
    1082           0 :           TMPARR_3D = 0.0
    1083             :        ENDIF
    1084             : 
    1085             :        ! Read arrays from file
    1086           0 :        DO I = 1, nRead
    1087             : 
    1088             :           ! time index
    1089           0 :           IF ( tdim  == 3 ) THEN
    1090           0 :              IF ( .NOT. ApplyWeights ) THEN
    1091             :                 s3 = time1
    1092             :                 n3 = ntime
    1093             :              ELSE
    1094           0 :                 IF ( I == 1 ) THEN
    1095             :                    s3 = time1
    1096             :                 ELSE
    1097           0 :                    s3 = time2
    1098             :                 ENDIF
    1099             :                 n3 = 1
    1100             :              ENDIF
    1101             :           ENDIF
    1102             : 
    1103           0 :           st3d = (/ s1, s2, s3 /)
    1104           0 :           ct3d = (/ n1, n2, n3 /)
    1105           0 :           CALL NcRd( TMPARR_3D, fId, TRIM(v_name), st3d, ct3d )
    1106             : 
    1107             :           ! Eventually pass time weighted arrays to temporary array
    1108           0 :           IF ( ApplyWeights ) THEN
    1109           0 :            WGTARR_3D(:,:,I) = TMPARR_3D(:,:,1)
    1110             :           ENDIF
    1111             : 
    1112             :        ENDDO
    1113             : 
    1114             :        ! Pass to output array. Eventually apply time weights.
    1115           0 :        IF ( ApplyWeights ) THEN
    1116           0 :           ncArr(:,:,1,1) = WGTARR_3D(:,:,1) * weight1 &
    1117           0 :                          + WGTARR_3D(:,:,2) * weight2
    1118             :        ELSE
    1119           0 :           IF ( tdim == 3 ) THEN
    1120           0 :              ncArr(:,:,1,:) = TMPARR_3D(:,:,:)
    1121             :           ELSE
    1122           0 :              ncArr(:,:,:,1) = TMPARR_3D(:,:,:)
    1123             :           ENDIF
    1124             :        ENDIF
    1125             : 
    1126             :        ! Cleanup
    1127           0 :        IF(ALLOCATED(TMPARR_3D)) DEALLOCATE(TMPARR_3D)
    1128           0 :        IF(ALLOCATED(WGTARR_3D)) DEALLOCATE(WGTARR_3D)
    1129             :     ENDIF
    1130             : 
    1131             :     !----------------------------------------
    1132             :     ! Read a 2D array (lon and lat only):
    1133           0 :     IF ( ndims == 2 ) THEN
    1134           0 :        ALLOCATE ( TMPARR_2D( nLon, nLat ) )
    1135           0 :        TMPARR_2D = 0.0
    1136           0 :        st2d      = (/ lon1, lat1 /)
    1137           0 :        ct2d      = (/ nlon, nlat /)
    1138           0 :        CALL NcRd( TMPARR_2D, fId, TRIM(v_name), st2d, ct2d )
    1139           0 :        ncArr(:,:,1,1) = TMPARR_2D(:,:)
    1140           0 :        DEALLOCATE(TMPARR_2D)
    1141             :     ENDIF
    1142             : 
    1143             :     ! ------------------------------------------
    1144             :     ! Eventually apply scale / offset factors
    1145             :     ! ------------------------------------------
    1146             : 
    1147             :     ! Check for scale factor
    1148           0 :     a_name  = "scale_factor"
    1149           0 :     ReadAtt = Ncdoes_Attr_Exist ( fId, TRIM(v_name), TRIM(a_name), a_type )
    1150             : 
    1151           0 :     IF ( ReadAtt ) THEN
    1152           0 :        CALL NcGet_Var_Attributes(fId,TRIM(v_name),TRIM(a_name),corr)
    1153           0 :        ncArr(:,:,:,:) = ncArr(:,:,:,:) * corr
    1154             :     ENDIF
    1155             : 
    1156             :     ! Check for offset factor
    1157           0 :     a_name  = "add_offset"
    1158           0 :     ReadAtt = Ncdoes_Attr_Exist ( fId, TRIM(v_name), TRIM(a_name), a_type )
    1159             : 
    1160           0 :     IF ( ReadAtt ) THEN
    1161           0 :        CALL NcGet_Var_Attributes(fId,TRIM(v_name),TRIM(a_name),corr)
    1162           0 :        ncArr(:,:,:,:) = ncArr(:,:,:,:) + corr
    1163             :     ENDIF
    1164             : 
    1165             :     ! ------------------------------------------
    1166             :     ! Check for filling values
    1167             :     ! NOTE: Test for REAL*4 and REAL*8
    1168             :     ! ------------------------------------------
    1169             : 
    1170             :     ! Define missing value
    1171           0 :     IF ( PRESENT(MissVal) ) THEN
    1172           0 :        MissValue = MissVal
    1173             :     ELSE
    1174             :        MissValue = 0.0
    1175             :     ENDIF
    1176             : 
    1177             :     ! 1: 'missing_value'
    1178           0 :     a_name  = "missing_value"
    1179           0 :     ReadAtt = Ncdoes_Attr_Exist ( fId, TRIM(v_name), TRIM(a_name), a_type )
    1180           0 :     IF ( ReadAtt ) THEN
    1181           0 :        IF ( a_type == NF90_REAL ) THEN
    1182           0 :           CALL NcGet_Var_Attributes( fId, TRIM(v_name), TRIM(a_name), miss4 )
    1183           0 :           WHERE ( ncArr == miss4 )
    1184             :              ncArr = MissValue
    1185             :           END WHERE
    1186           0 :        ELSE IF ( a_type == NF90_DOUBLE ) THEN
    1187           0 :           CALL NcGet_Var_Attributes( fId, TRIM(v_name), TRIM(a_name), miss8 )
    1188           0 :           miss4 = REAL( miss8 )
    1189           0 :           WHERE ( ncArr == miss4 )
    1190             :              ncArr = MissValue
    1191             :           END WHERE
    1192             :        ENDIF
    1193             :     ENDIF
    1194             : 
    1195             :     ! 2: '_FillValue'
    1196           0 :     a_name  = "_FillValue"
    1197           0 :     ReadAtt = Ncdoes_Attr_Exist ( fId, TRIM(v_name), TRIM(a_name), a_type )
    1198           0 :     IF ( ReadAtt ) THEN
    1199           0 :        IF ( a_type == NF90_REAL ) THEN
    1200           0 :           CALL NcGet_Var_Attributes( fId, TRIM(v_name), TRIM(a_name), miss4 )
    1201           0 :           WHERE ( ncArr == miss4 )
    1202             :              ncArr = MissValue
    1203             :           END WHERE
    1204           0 :        ELSE IF ( a_type == NF90_DOUBLE ) THEN
    1205           0 :           CALL NcGet_Var_Attributes( fId, TRIM(v_name), TRIM(a_name), miss8 )
    1206           0 :           miss4 = REAL( miss8 )
    1207           0 :           WHERE ( ncArr == miss4 )
    1208             :              ncArr = MissValue
    1209             :           END WHERE
    1210             :        ENDIF
    1211             :     ENDIF
    1212             : 
    1213             :     ! ------------------------------------------
    1214             :     ! Flip z-axis if needed
    1215             :     ! ------------------------------------------
    1216           0 :     IF ( FlipZ ) THEN
    1217           0 :        ncArr(:,:,:,:) = ncArr(:,:,ncLev:1:-1,:)
    1218             :     ENDIF
    1219             : 
    1220             :     ! ----------------------------
    1221             :     ! Read optional arguments
    1222             :     ! ----------------------------
    1223             : 
    1224             :     ! Read units
    1225           0 :     IF ( PRESENT(VarUnit) )THEN
    1226           0 :        a_name = "units"
    1227           0 :        CALL NcGet_Var_Attributes(fId,TRIM(v_name),TRIM(a_name),a_val)
    1228           0 :        VarUnit = TRIM(a_val)
    1229             : 
    1230             :        ! Check if the last character of VarUnit is the ASCII null character
    1231             :        ! ("\0", ASCII value = 0), which is used to denote the end of a string.
    1232             :        ! The ASCII null character may be introduced if the netCDF file was
    1233             :        ! written using a language other than Fortran.  The compiler might
    1234             :        ! interpret the null character as part of the string instead of as
    1235             :        ! an empty space.  If the null space is there, then replace it with
    1236             :        ! a Fortran empty string value (''). (bmy, 7/17/18)
    1237           0 :        I = LEN_TRIM( VarUnit )
    1238           0 :        IF ( ICHAR( VarUnit(I:I) ) == 0 ) THEN
    1239           0 :           VarUnit(I:I) = ''
    1240             :        ENDIF
    1241             :     ENDIF
    1242             : 
    1243             :     !=================================================================
    1244             :     ! Cleanup and quit
    1245             :     !=================================================================
    1246             : 
    1247             :     ! Return w/ success
    1248           0 :     RC = 0
    1249             : 
    1250           0 :   END SUBROUTINE NC_READ_ARR
    1251             : !EOC
    1252             : !------------------------------------------------------------------------------
    1253             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    1254             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    1255             : !------------------------------------------------------------------------------
    1256             : !BOP
    1257             : !
    1258             : ! !IROUTINE: Nc_Read_Time_yyyymmddhhmm
    1259             : !
    1260             : ! !DESCRIPTION: Returns a vector containing the datetimes (YYYYMMDDhhmm) of
    1261             : ! all time slices in the netCDF file.
    1262             : !\\
    1263             : ! !INTERFACE:
    1264             : !
    1265           0 :   SUBROUTINE NC_READ_TIME_YYYYMMDDhhmm( fID,              nTime,    &
    1266             :                                         all_YYYYMMDDhhmm, timeUnit, &
    1267             :                                         refYear,          RC )
    1268             : !
    1269             : ! !USES:
    1270             : !
    1271             :     USE HCO_JULDAY_MOD, ONLY : JULDAY, CALDATE
    1272             : !
    1273             : ! !INPUT PARAMETERS:
    1274             : !
    1275             :     INTEGER,          INTENT(IN   )           :: fID
    1276             : !
    1277             : ! !INPUT/OUTPUT PARAMETERS:
    1278             : !
    1279             :     REAL*8,           POINTER                 :: all_YYYYMMDDhhmm(:)
    1280             :     CHARACTER(LEN=*), INTENT(  OUT), OPTIONAL :: timeUnit
    1281             :     INTEGER,          INTENT(  OUT), OPTIONAL :: refYear
    1282             : !
    1283             : ! !INPUT/OUTPUT PARAMETERS:
    1284             : !
    1285             :     INTEGER,          INTENT(INOUT)           :: nTime
    1286             :     INTEGER,          INTENT(INOUT)           :: RC
    1287             : !
    1288             : ! !REVISION HISTORY:
    1289             : !  See https://github.com/geoschem/hemco for complete history
    1290             : !EOP
    1291             : !------------------------------------------------------------------------------
    1292             : !BOC
    1293             : !
    1294             : ! !LOCAL VARIABLES:
    1295             : !
    1296             :     ! Scalars
    1297             :     CHARACTER(LEN=255)  :: ncUnit, cal
    1298             :     INTEGER             :: refYr, refMt, refDy, refHr, refMn, refSc
    1299             :     INTEGER             :: T, YYYYMMDD, hhmmss
    1300             :     REAL*8              :: realrefDy, refJulday, tJulday
    1301             : 
    1302             :     ! Pointers
    1303           0 :     REAL*8,   POINTER   :: tVec(:)
    1304             : 
    1305             :     !=================================================================
    1306             :     ! NC_READ_TIME_YYYYMMDDhhmm begins here
    1307             :     !=================================================================
    1308             : 
    1309             :     ! Init values
    1310           0 :     RC = 0
    1311           0 :     tVec => NULL()
    1312           0 :     IF ( PRESENT(TimeUnit) ) TimeUnit = ''
    1313           0 :     IF ( PRESENT(refYear ) ) refYear  = 0
    1314             : 
    1315             :     ! Read time vector
    1316             :     CALL NC_READ_TIME ( fID,          nTime,            ncUnit,              &
    1317           0 :                         timeVec=tVec, timeCalendar=cal, RC=RC               )
    1318           0 :     IF ( RC/=0 ) THEN
    1319           0 :        WRITE( 6, '(/,a)' ) REPEAT( '=', 79 )
    1320           0 :        WRITE( 6, '(a)'   ) 'Error encountered in NC_READ_TIME (ncdf_mod.F90)'
    1321           0 :        WRITE( 6, '(a,/)' ) REPEAT( '=', 79 )
    1322           0 :        RETURN
    1323             :     ENDIF
    1324             : 
    1325             :     ! If nTime is zero, return here!
    1326           0 :     IF ( nTime == 0 ) RETURN
    1327             : 
    1328             :     ! Get reference date in julian days
    1329             :     CALL NC_GET_REFDATETIME ( ncUnit, refYr, refMt, &
    1330           0 :                               refDy,  refHr, refMn, refSc, RC )
    1331           0 :     IF ( RC /= 0 ) RETURN
    1332             :     realrefDy =         refDy              &
    1333             :               + ( MAX(0,refHr) / 24d0    ) &
    1334             :               + ( MAX(0,refMn) / 1440d0  ) &
    1335           0 :               + ( MAX(0,refSc) / 86400d0 )
    1336           0 :     refJulday = JULDAY ( refYr, refMt, realrefDy )
    1337             : 
    1338             :     ! NOTE: It seems that there is an issue with reference dates
    1339             :     ! between 1800 and 1901: the respective time stamps all seem to
    1340             :     ! be off by one day (this problem doesn't appear for netCDF files
    1341             :     ! with reference date zero, i.e. hours since 1-1-1)!
    1342             :     ! I'm not sure what causes this problem, but adding one day to
    1343             :     ! reference dates that lie between 1600 and 1900 seems to fix the
    1344             :     ! problem.
    1345             :     ! TODO: requires more testing!
    1346           0 :     IF ( refYr <= 1900 .AND. refYr >= 1600 ) THEN
    1347           0 :        refJulday = refJulday + 1.0
    1348             :        !PRINT *, 'Reference julian day increased by one day!!!'
    1349             :     ENDIF
    1350             : 
    1351             :     ! Get calendar dates
    1352           0 :     IF ( ASSOCIATED ( all_YYYYMMDDhhmm ) ) DEALLOCATE( all_YYYYMMDDhhmm )
    1353           0 :     ALLOCATE( all_YYYYMMDDhhmm(nTime) )
    1354           0 :     all_YYYYMMDDhhmm = 0.0d0
    1355             : 
    1356             :     ! Construct julian date for every available time slice. Make sure it is
    1357             :     ! in the proper 'units', e.g. in days, hours or minutes, depending on
    1358             :     ! the reference unit.
    1359           0 :     DO T = 1, nTime
    1360           0 :        tJulDay = tVec(T)
    1361           0 :        IF ( refHr >= 0 ) tJulday = tJulday / 24.d0
    1362           0 :        IF ( refMn >= 0 ) tJulday = tJulday / 60.d0
    1363           0 :        IF ( refSc >= 0 ) tJulday = tJulday / 60.d0
    1364           0 :        tJulday = tJulday + refJulday
    1365           0 :        CALL CALDATE ( tJulday, YYYYMMDD, hhmmss )
    1366           0 :        all_YYYYMMDDhhmm(T) = ( DBLE( YYYYMMDD ) * 1d4   ) + &
    1367           0 :                              ( DBLE( hhmmss     / 100 ) )
    1368             :     ENDDO
    1369             : 
    1370             :     ! Cleanup
    1371           0 :     IF ( ASSOCIATED( tVec ) ) DEALLOCATE( tVec )
    1372             : 
    1373             :     ! Return
    1374           0 :     IF ( PRESENT(timeUnit) ) timeUnit = ncUnit
    1375           0 :     IF ( PRESENT(refYear ) ) refYear  = refYr
    1376           0 :     RC = 0
    1377             : 
    1378           0 :   END SUBROUTINE NC_READ_TIME_YYYYMMDDhhmm
    1379             : !EOC
    1380             : !------------------------------------------------------------------------------
    1381             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    1382             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    1383             : !------------------------------------------------------------------------------
    1384             : !BOP
    1385             : !
    1386             : ! !IROUTINE: Nc_Get_RefDateTime
    1387             : !
    1388             : ! !DESCRIPTION: Returns the reference datetime (tYr / tMt / tDy / tHr /
    1389             : ! tMn ) of the provided time unit. For now, supported formats are
    1390             : ! "days since YYYY-MM-DD", "hours since YYYY-MM-DD HH:MM:SS", and
    1391             : ! "minutes since YYYY-MM-DD HH:NN:SS". For times in days since refdate,
    1392             : ! the returned reference hour rHr is set to -1. The same applies for the
    1393             : ! reference minute for units in days / hours since XXX.
    1394             : !\\
    1395             : ! !INTERFACE:
    1396             : !
    1397           0 :   SUBROUTINE NC_GET_REFDATETIME( tUnit, tYr, tMt, tDy, tHr, tMn, tSc, RC )
    1398             : !
    1399             : ! !USES:
    1400             : !
    1401             :     USE HCO_CHARPAK_MOD, ONLY : TRANLC
    1402             : !
    1403             : ! !INPUT PARAMETERS:
    1404             : !
    1405             :     ! Required
    1406             :     CHARACTER(LEN=*), INTENT( IN)    :: tUnit
    1407             : !
    1408             : ! !OUTPUT PARAMETERS:
    1409             : !
    1410             :     INTEGER,          INTENT(OUT)    :: tYr
    1411             :     INTEGER,          INTENT(OUT)    :: tMt
    1412             :     INTEGER,          INTENT(OUT)    :: tDy
    1413             :     INTEGER,          INTENT(OUT)    :: tHr
    1414             :     INTEGER,          INTENT(OUT)    :: tMn
    1415             :     INTEGER,          INTENT(OUT)    :: tSc
    1416             : !
    1417             : ! !INPUT/OUTPUT PARAMETERS:
    1418             : !
    1419             :     INTEGER,          INTENT(INOUT)  :: RC
    1420             : !
    1421             : ! !REMARKS:
    1422             : !
    1423             : ! !REVISION HISTORY:
    1424             : !  See https://github.com/geoschem/hemco for complete history
    1425             : !EOP
    1426             : !------------------------------------------------------------------------------
    1427             : !BOC
    1428             : !
    1429             : ! !LOCAL VARIABLES:
    1430             : !
    1431             :     CHARACTER(LEN=255)    :: LOC, MSG
    1432             :     CHARACTER(LEN=255)    :: MIRRUNIT
    1433             :     INTEGER               :: TTYPE, STAT, L1, L2
    1434             :     INTEGER               :: MINLEN, STRLEN, I
    1435             : 
    1436             :     !=================================================================
    1437             :     ! NC_GET_REFDATETIME starts here
    1438             :     !=================================================================
    1439             : 
    1440             :     ! Init
    1441           0 :     LOC = 'NC_GET_REFDATETIME (ncdf_mod.F)'
    1442             : 
    1443             :     ! ----------------------------------------------------------------------
    1444             :     ! Determine time unit type
    1445             :     ! ----------------------------------------------------------------------
    1446             : 
    1447             :     ! Mirror time unit and convert to lower case
    1448           0 :     MIRRUNIT = tUnit
    1449           0 :     CALL TRANLC( MIRRUNIT )
    1450             : 
    1451             :     ! Check for reference time unit '(days, hours, minutes) since ...'
    1452             :     ! Set beginning of reference date according to the unit and define
    1453             :     ! minimum string length required by unit.
    1454             : 
    1455             :     ! 'days since YYYY-M-D'
    1456           0 :     IF ( MIRRUNIT(1:10) == 'days since' ) THEN
    1457             :        TTYPE  = 1
    1458             :        L1     = 12
    1459             :        MINLEN = 19
    1460             : 
    1461             :     ! 'hours since YYYY-M-D h:m:s'
    1462           0 :     ELSEIF ( MIRRUNIT(1:11) == 'hours since' ) THEN
    1463             :        TTYPE  = 2
    1464             :        L1     = 13
    1465             :        MINLEN = 26
    1466             : 
    1467             :     ! 'minutes since YYYY-M-D h:m:s'
    1468           0 :     ELSEIF ( MIRRUNIT(1:13) == 'minutes since' ) THEN
    1469             :        TTYPE  = 3
    1470             :        L1     = 15
    1471             :        MINLEN = 28
    1472             : 
    1473             :     ! 'seconds since YYYY-M-D h:m:s'
    1474           0 :     ELSEIF ( MIRRUNIT(1:13) == 'seconds since' ) THEN
    1475             :        TTYPE  = 4
    1476             :        L1     = 15
    1477             :        MINLEN = 28
    1478             : 
    1479             :     ! Return w/ error otherwise
    1480             :     ELSE
    1481           0 :        PRINT *, 'Invalid time unit: ' // TRIM(tUnit)
    1482           0 :        RC = -999; RETURN
    1483             :     ENDIF
    1484             : 
    1485             :     ! Check if time string is long enough or not
    1486           0 :     STRLEN = LEN(tUnit)
    1487           0 :     IF ( STRLEN < MINLEN ) THEN
    1488           0 :        PRINT *, 'Time unit string too short: ' // TRIM(tUnit)
    1489           0 :        RC = -999; RETURN
    1490             :     ENDIF
    1491             : 
    1492             :     ! ----------------------------------------------------------------------
    1493             :     ! Determine reference time/date
    1494             :     ! Get the year, month, day and hour from the string
    1495             :     ! '... since YYYY-MM-DD hh:mm:ss
    1496             : 
    1497             :     ! Read reference year, i.e. from beginning of date string until
    1498             :     ! first separator sign (-).
    1499           0 :     DO I=L1,STRLEN
    1500           0 :        IF(tUnit(I:I) == '-') EXIT
    1501             :     ENDDO
    1502           0 :     L2 = I-1
    1503             : 
    1504           0 :     READ( tUnit(L1:L2),'(i4)', IOSTAT=STAT ) tYr
    1505           0 :     IF ( STAT /= 0 ) THEN
    1506           0 :        PRINT *, 'Invalid year in ' // TRIM(tUnit)
    1507           0 :        RC = -999; RETURN
    1508             :     ENDIF
    1509             : 
    1510             :     ! Advance in date string: now read reference month.
    1511           0 :     L1 = L2 + 2
    1512           0 :     DO I=L1,STRLEN
    1513           0 :        IF(tUnit(I:I) == '-') EXIT
    1514             :     ENDDO
    1515           0 :     L2 = I-1
    1516           0 :     READ( tUnit(L1:L2), '(i2)', IOSTAT=STAT ) tMt
    1517           0 :     IF ( STAT /= 0 ) THEN
    1518           0 :        PRINT *, 'Invalid month in ' // TRIM(tUnit)
    1519           0 :        RC = -999; RETURN
    1520             :     ENDIF
    1521             : 
    1522             :     ! Advance in date string: now read reference day.
    1523           0 :     L1 = L2 + 2
    1524           0 :     DO I=L1,STRLEN
    1525           0 :        IF(tUnit(I:I) == ' ') EXIT
    1526             :     ENDDO
    1527           0 :     L2 = I-1
    1528           0 :     READ( tUnit(L1:L2), '(i2)', IOSTAT=STAT ) tDy
    1529           0 :     IF ( STAT /= 0 ) THEN
    1530           0 :        PRINT *, 'Invalid day in ' // TRIM(tUnit)
    1531           0 :        RC = -999; RETURN
    1532             :     ENDIF
    1533             : 
    1534             :     ! Get reference hour only if 'hours/minutes/seconds since'.
    1535           0 :     IF ( TTYPE > 1 ) THEN
    1536             : 
    1537             :        ! Reference hour
    1538           0 :        L1 = L2 + 2
    1539           0 :        DO I=L1,STRLEN
    1540           0 :           IF(tUnit(I:I) == ':') EXIT
    1541             :        ENDDO
    1542           0 :        L2 = I-1
    1543           0 :        READ( tUnit(L1:L2), '(i2)', IOSTAT=STAT ) tHr
    1544           0 :        IF ( STAT /= 0 ) THEN
    1545           0 :           PRINT *, 'Invalid hour in ', TRIM(tUnit)
    1546           0 :           RC = -999; RETURN
    1547             :        ENDIF
    1548             : 
    1549             :     ELSE
    1550             :        ! Set reference hour to -1
    1551           0 :        tHr = -1
    1552             :     ENDIF
    1553             : 
    1554             :     ! Get reference minute only if 'minutes since...'
    1555           0 :     IF ( TTYPE>2 ) THEN
    1556             : 
    1557             :        ! Reference minute
    1558           0 :        L1 = L2 + 2
    1559           0 :        DO I=L1,STRLEN
    1560           0 :           IF(tUnit(I:I) == ':') EXIT
    1561             :        ENDDO
    1562           0 :        L2 = I-1
    1563           0 :        READ( tUnit(L1:L2), '(i2)', IOSTAT=STAT ) tMn
    1564           0 :        IF ( STAT /= 0 ) THEN
    1565           0 :           PRINT *, 'Invalid minute in ', TRIM(tUnit)
    1566           0 :           RC = -999; RETURN
    1567             :        ENDIF
    1568             : 
    1569             :     ELSE
    1570             :        ! Set reference minute to -1
    1571           0 :        tMn = -1
    1572             :     ENDIF
    1573             : 
    1574             :     ! Get reference minute only if 'seconds since...'
    1575           0 :     IF ( TTYPE>3 ) THEN
    1576             : 
    1577             :        ! Reference second
    1578           0 :        L1 = L2 + 2
    1579           0 :        DO I=L1,STRLEN
    1580           0 :           IF(tUnit(I:I) == ':') EXIT
    1581             :        ENDDO
    1582           0 :        L2 = I-1
    1583           0 :        READ( tUnit(L1:L2), '(i2)', IOSTAT=STAT ) tSc
    1584           0 :        IF ( STAT /= 0 ) THEN
    1585           0 :           PRINT *, 'Invalid second in ', TRIM(tUnit)
    1586           0 :           RC = -999; RETURN
    1587             :        ENDIF
    1588             : 
    1589             :     ELSE
    1590             :        ! Set reference second to -1
    1591           0 :        tSc = -1
    1592             :     ENDIF
    1593             : 
    1594             :     ! Return w/ success
    1595           0 :     RC = 0
    1596             : 
    1597           0 :   END SUBROUTINE NC_GET_REFDATETIME
    1598             : !EOC
    1599             : !------------------------------------------------------------------------------
    1600             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    1601             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    1602             : !------------------------------------------------------------------------------
    1603             : !BOP
    1604             : !
    1605             : ! !IROUTINE: Get_Tidx
    1606             : !
    1607             : ! !DESCRIPTION: Routine GET\_TIDX returns the index with the specified time
    1608             : ! for a given time vector.
    1609             : !\\
    1610             : !\\
    1611             : ! !INTERFACE:
    1612             : !
    1613             :   SUBROUTINE GET_TIDX( TDIM, TIMEVEC,  TTYPE, TOFFSET, &
    1614             :                        YEAR, MONTH,    DAY,   HOUR,    &
    1615             :                        TIDX, TDIMREAD, RC )
    1616             : !
    1617             : ! !INPUT PARAMETERS:
    1618             : !
    1619             :     ! Required
    1620             :     INTEGER, INTENT(   IN)           :: TDIM
    1621             :     INTEGER, INTENT(   IN)           :: TTYPE
    1622             :     REAL*8,  INTENT(   IN)           :: TOFFSET
    1623             : !
    1624             : ! !INPUT/OUTPUT PARAMETERS:
    1625             : !
    1626             :     INTEGER, INTENT(INOUT)           :: TIMEVEC(TDIM)
    1627             :     INTEGER, INTENT(INOUT)           :: YEAR
    1628             :     INTEGER, INTENT(INOUT)           :: MONTH
    1629             :     INTEGER, INTENT(INOUT)           :: DAY
    1630             :     INTEGER, INTENT(INOUT)           :: HOUR
    1631             :     INTEGER, INTENT(INOUT)           :: RC
    1632             : !
    1633             : ! !OUTPUT PARAMETERS:
    1634             : !
    1635             :     INTEGER, INTENT(  OUT)           :: TIDX
    1636             :     INTEGER, INTENT(  OUT)           :: TDIMREAD
    1637             : !
    1638             : ! !REMARKS:
    1639             : !
    1640             : ! !REVISION HISTORY:
    1641             : !  See https://github.com/geoschem/hemco for complete history
    1642             : !EOP
    1643             : !------------------------------------------------------------------------------
    1644             : !BOC
    1645             : !
    1646             : ! !LOCAL VARIABLES:
    1647             : !
    1648             :     INTEGER                :: II, iiDiff, minDiff
    1649             :     REAL*8                 :: TAU
    1650             :     CHARACTER(LEN=255)     :: MSG, LOC
    1651             : 
    1652             :     !=================================================================
    1653             :     ! GET_TIDX starts here
    1654             :     !=================================================================
    1655             : 
    1656             :     ! Init
    1657             :     LOC = 'GET_TIDX (ncdf_mod.F)'
    1658             :     TIDX = 0
    1659             :     minDiff = -999
    1660             : 
    1661             :     !-----------------------------------------------------------------
    1662             :     ! If year is given, compare netcdf-tau against desired tau
    1663             :     !-----------------------------------------------------------------
    1664             :     IF ( YEAR > 0 ) THEN
    1665             : 
    1666             :        ! Restrict month, day and hour to valid values
    1667             :        MONTH = MIN ( MAX( 1, MONTH ), 12 )
    1668             :        DAY   = MIN ( MAX( 1, DAY   ), 31 )
    1669             :        HOUR  = MIN ( MAX( 0, HOUR  ), 23 )
    1670             : 
    1671             :        ! Read desired tau => hours relative to G-C reference time
    1672             :        TAU = GET_TAU0( MONTH, DAY, YEAR, HOUR )
    1673             : 
    1674             :        ! Convert to 'hours since ...' if unit is 'days since ...'
    1675             :        IF ( TTYPE == 2 ) THEN
    1676             :           TIMEVEC(:) = TIMEVEC(:) * 24
    1677             :        ENDIF
    1678             : 
    1679             :        ! Convert time stamps to hours since G-C reference time
    1680             :        TIMEVEC(:) = TIMEVEC(:) + INT(TOFFSET)
    1681             : 
    1682             :        ! Compare wanted tau to tau's of ncdf-file.
    1683             :        ! Loop over all time stamps and check which one is closest
    1684             :        ! to the specified one. Print a warning if time stamps don't
    1685             :        ! match!
    1686             :        DO II = 1, TDIM
    1687             : 
    1688             :           ! Difference between time stamps
    1689             :           iiDiff = ABS( TIMEVEC(II) - INT(TAU) )
    1690             : 
    1691             :           ! Check if this is closest time stamp so far, and save this
    1692             :           ! index and difference
    1693             :           IF ( iiDiff < minDiff .OR. II == 1 ) THEN
    1694             :              minDiff = iiDiff
    1695             :              TIDX    = II
    1696             :           ENDIF
    1697             : 
    1698             :           ! Exit loop if difference is zero
    1699             :           IF ( minDiff == 0 ) EXIT
    1700             : 
    1701             :        ENDDO
    1702             : 
    1703             :        ! Warning if time stamps did not match
    1704             :        IF ( minDiff /= 0 ) THEN
    1705             :           PRINT *, 'In NCDF_MOD: Time stamp not found ' // &
    1706             :                    'take closest timestamp!'
    1707             :        ENDIF
    1708             : 
    1709             :        ! Set number of time stamps to be read to 1
    1710             :        TDIMREAD = 1
    1711             : 
    1712             :     !-----------------------------------------------------------------
    1713             :     ! If only month is given, assume netCDF file to contain monthly
    1714             :     ! data and pick the desired month.
    1715             :     !-----------------------------------------------------------------
    1716             :     ELSEIF ( MONTH > 0 ) THEN
    1717             : 
    1718             :        ! Check if it's indeed monthly data:
    1719             :        IF ( TDIM /= 12 ) THEN
    1720             :           PRINT *, 'Array is not monthly '
    1721             :           RC = -999; RETURN
    1722             :        ENDIF
    1723             : 
    1724             :        ! Set time index to specified month
    1725             :        TIDX = MONTH
    1726             : 
    1727             :        ! Set number of time stamps to be read to 1
    1728             :        TDIMREAD = 1
    1729             : 
    1730             :     !-----------------------------------------------------------------
    1731             :     ! If hour is given, assume netCDF file to contain hourly data
    1732             :     ! and pick the desired hour.
    1733             :     !-----------------------------------------------------------------
    1734             :     ELSEIF ( HOUR >= 0 ) THEN
    1735             : 
    1736             :        ! Check if it's indeed hourly data:
    1737             :        IF ( TDIM /= 24 ) THEN
    1738             :           PRINT *, 'Array is not hourly'
    1739             :           RC = -999; RETURN
    1740             :        ENDIF
    1741             : 
    1742             :        ! Set time index to specified hour (+1 since hour 0 is idx 1)
    1743             :        TIDX = HOUR + 1
    1744             : 
    1745             :        ! Set number of time stamps to be read to 1
    1746             :        TDIMREAD = 1
    1747             : 
    1748             :     !-----------------------------------------------------------------
    1749             :     ! Otherwise, read all time dimensions
    1750             :     !-----------------------------------------------------------------
    1751             :     ELSE
    1752             :        TIDX     = 1
    1753             :        TDIMREAD = TDIM
    1754             :     ENDIF
    1755             : 
    1756             :     ! Return w/ success
    1757             :     RC = 0
    1758             : 
    1759             :   END SUBROUTINE GET_TIDX
    1760             : !EOC
    1761             : !------------------------------------------------------------------------------
    1762             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    1763             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    1764             : !------------------------------------------------------------------------------
    1765             : !BOP
    1766             : !
    1767             : ! !IROUTINE: TimeUnit_Check
    1768             : !
    1769             : ! !DESCRIPTION: Makes a validity check of the passed unit string.
    1770             : ! Supported formats are "days since YYYY-MM-DD" (TIMETYPE=1) and
    1771             : ! "hours since YYYY-MM-DD HH:MM:SS" (TIMETYPE=2).
    1772             : !\\
    1773             : !\\
    1774             : ! The output argument TOFFSET gives the offset of the ncdf reference
    1775             : ! time relative to Geos-Chem reference time (in hours).
    1776             : !\\
    1777             : !\\
    1778             : ! !INTERFACE:
    1779             : !
    1780             :   SUBROUTINE TIMEUNIT_CHECK( TIMEUNIT, TIMETYPE, TOFFSET, FILENAME, RC )
    1781             : !
    1782             : ! !USES:
    1783             : !
    1784             :     USE HCO_CHARPAK_MOD, ONLY : TRANLC
    1785             : !
    1786             : ! !INPUT PARAMETERS:
    1787             : !
    1788             :     ! Required
    1789             :     CHARACTER(LEN=*), INTENT(IN  )  :: TIMEUNIT
    1790             :     CHARACTER(LEN=*), INTENT(IN  )  :: FILENAME
    1791             : !
    1792             : ! !OUTPUT PARAMETERS:
    1793             : !
    1794             :     INTEGER,          INTENT(  OUT) :: TIMETYPE
    1795             :     REAL*8,           INTENT(  OUT) :: TOFFSET
    1796             : !
    1797             : ! !INPUT/OUTPUT PARAMETERS:
    1798             : !
    1799             :     INTEGER,          INTENT(INOUT) :: RC
    1800             : !
    1801             : ! !REMARKS:
    1802             : !
    1803             : ! !REVISION HISTORY:
    1804             : !  See https://github.com/geoschem/hemco for complete history
    1805             : !EOP
    1806             : !------------------------------------------------------------------------------
    1807             : !BOC
    1808             : !
    1809             : ! !LOCAL VARIABLES:
    1810             : !
    1811             :     CHARACTER(LEN=255)    :: LOC, MSG
    1812             :     CHARACTER(LEN=255)    :: MIRRUNIT
    1813             :     INTEGER               :: STAT, L1, L2
    1814             :     INTEGER               :: TTYPE
    1815             :     INTEGER               :: YYYY, MM, DD, HH
    1816             :     INTEGER               :: STRLEN
    1817             : 
    1818             :     !=================================================================
    1819             :     ! TIMEUNIT_CHECK starts here
    1820             :     !=================================================================
    1821             : 
    1822             :     ! Init
    1823             :     LOC = 'TIMEUNIT_CHECK (ncdf_mod.F)'
    1824             : 
    1825             :     ! Check length of time unit string. This must be at least 21
    1826             :     ! ("days since YYYY:MM:DD" is of length 21)
    1827             :     STRLEN = LEN(TIMEUNIT)
    1828             :     IF ( STRLEN < 21 ) THEN
    1829             :        PRINT *, 'Time unit string too short: ' // TRIM(FILENAME)
    1830             :        RC = -999; RETURN
    1831             :     ENDIF
    1832             : 
    1833             :     ! ----------------------------------------------------------------------
    1834             :     ! Determine time unit type
    1835             :     ! ----------------------------------------------------------------------
    1836             : 
    1837             :     ! Mirror time unit and convert to lower case
    1838             :     MIRRUNIT = TIMEUNIT
    1839             :     CALL TRANLC( MIRRUNIT )
    1840             : 
    1841             :     ! Check for 'hours since'. If true, set TTYPE to 1 and set the
    1842             :     ! begin of the effective date string to 12. Also check if the time
    1843             :     ! string is at least of length 25, which is required for this
    1844             :     ! unit.
    1845             :     IF ( MIRRUNIT(1:11) == 'hours since' ) THEN
    1846             :        TTYPE = 1
    1847             :        L1    = 13
    1848             :        IF ( STRLEN < 25 ) THEN
    1849             :           PRINT *, 'Time unit string too short: ' // TRIM(FILENAME)
    1850             :           RC = -999; RETURN
    1851             :        ENDIF
    1852             : 
    1853             :     ! Check for 'days since'. If true, set TTYPE to 2 and set the
    1854             :     ! begin of the effective date string to 11.
    1855             :     ELSEIF ( MIRRUNIT(1:10) == 'days since' ) THEN
    1856             :        TTYPE = 2
    1857             :        L1    = 12
    1858             :     ELSE
    1859             :        ! Return w/ error
    1860             :        PRINT *, 'Invalid time unit in', TRIM(FILENAME)
    1861             :        RC = -999; RETURN
    1862             :     ENDIF
    1863             : 
    1864             :     ! ----------------------------------------------------------------------
    1865             :     ! Determine reference time/date
    1866             :     ! Get the year, month, day and hour from the string
    1867             :     ! '... since YYYY-MM-DD hh:mm:ss
    1868             :     ! ----------------------------------------------------------------------
    1869             : 
    1870             :     ! Read reference year, i.e. first four integers
    1871             :     L2 = L1 + 3
    1872             :     READ( TIMEUNIT(L1:L2),'(i4)', IOSTAT=STAT ) YYYY
    1873             :     IF ( STAT /= 0 ) THEN
    1874             :        PRINT *, 'Invalid year in ', TRIM(TIMEUNIT), &
    1875             :             ' in file'             , TRIM(FILENAME)
    1876             :        RC = -999; RETURN
    1877             :     ENDIF
    1878             : 
    1879             :     ! Read reference month. Typically, the month is represented by
    1880             :     ! two characters, i.e. 1 is 01, etc.
    1881             :     L1 = L2 + 2
    1882             :     L2 = L1 + 1
    1883             :     READ( TIMEUNIT(L1:L2), '(i2)', IOSTAT=STAT ) MM
    1884             :     ! Also check for the case where the month is only one character:
    1885             :     IF ( STAT /= 0 ) THEN
    1886             :        L2 = L1
    1887             :        READ( TIMEUNIT(L1:L2), '(i2)', IOSTAT=STAT ) MM
    1888             :        IF ( STAT /= 0 ) THEN
    1889             :           PRINT *, 'Invalid month in ', TRIM(TIMEUNIT), &
    1890             :                    ' in file'         , TRIM(FILENAME)
    1891             :           RC = -999; RETURN
    1892             :        ENDIF
    1893             :     ENDIF
    1894             : 
    1895             :     ! Reference day. Typically, the day is represented by two
    1896             :     ! characters, i.e. 1 is 01, etc.
    1897             :     L1 = L2 + 2
    1898             :     L2 = L1 + 1
    1899             :     READ( TIMEUNIT(L1:L2), '(i2)', IOSTAT=STAT ) DD
    1900             :     ! Also check for the case where the day is only one character:
    1901             :     IF ( STAT /= 0 ) THEN
    1902             :        L2 = L1
    1903             :        READ( TIMEUNIT(L1:L2), '(i2)', IOSTAT=STAT ) DD
    1904             :        IF ( STAT /= 0 ) THEN
    1905             :           PRINT *, 'Invalid day in ', TRIM(TIMEUNIT), &
    1906             :                    ' in file'       , TRIM(FILENAME)
    1907             :           RC = -999; RETURN
    1908             :        ENDIF
    1909             :     ENDIF
    1910             : 
    1911             :     ! Get reference hour only if 'hours since...'
    1912             :     IF ( TTYPE == 1 ) THEN
    1913             : 
    1914             :        ! Reference hour
    1915             :        L1 = L2 + 2
    1916             :        L2 = L1 + 1
    1917             :        READ( TIMEUNIT(L1:L2), '(i2)', IOSTAT=STAT ) HH
    1918             :        IF ( STAT /= 0 ) THEN
    1919             :           L2 = L1
    1920             :           READ( TIMEUNIT(L1:L2), '(i2)', IOSTAT=STAT ) HH
    1921             :           IF ( STAT /= 0 ) THEN
    1922             :              PRINT *, 'Invalid hour in ', TRIM(TIMEUNIT), &
    1923             :                       ' in file'            , TRIM(FILENAME)
    1924             :              RC = -999; RETURN
    1925             :           ENDIF
    1926             :        ENDIF
    1927             : 
    1928             :     ELSE
    1929             :        ! Set reference hour to 0
    1930             :        HH = 0
    1931             : 
    1932             :     ENDIF
    1933             : 
    1934             :     ! Get reference tau relative to G-C reference time, i.e. the
    1935             :     ! offset of the netCDF reference time to the G-C reference time.
    1936             :     ! This is hours since G-C reftime.
    1937             :     TOFFSET = GET_TAU0( MM, DD, YYYY, HH )
    1938             : 
    1939             :     ! Remove one day if TOFFSET is negative, i.e. if the netCDF
    1940             :     ! reference time is older than G-C reference time. We have to do
    1941             :     ! this because GET_TAU0 does count the last day in this case!
    1942             :     IF ( TOFFSET < 0d0 ) THEN
    1943             :        TOFFSET = TOFFSET + 24d0
    1944             :     ENDIF
    1945             : 
    1946             :     ! Output argument
    1947             :     TIMETYPE = TTYPE
    1948             : 
    1949             :     ! Return w/ success
    1950             :     RC = 0
    1951             : 
    1952             :   END SUBROUTINE TIMEUNIT_CHECK
    1953             : !EOC
    1954             : !------------------------------------------------------------------------------
    1955             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    1956             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    1957             : !------------------------------------------------------------------------------
    1958             : !BOP
    1959             : !
    1960             : ! !IROUTINE: Nc_Get_Grid_Edges_Sp
    1961             : !
    1962             : ! !DESCRIPTION: Routine to get the longitude or latitude edges. If the edge
    1963             : ! cannot be read from the netCDF file, they are calculated from the provided
    1964             : ! grid midpoints. Use the axis input argument to discern between longitude
    1965             : ! (axis 1) and latitude (axis 2).
    1966             : !\\
    1967             : !\\
    1968             : ! !INTERFACE:
    1969             : !
    1970           0 :   SUBROUTINE NC_GET_GRID_EDGES_SP( fID, AXIS, MID, NMID, EDGE, NEDGE, RC )
    1971             : !
    1972             : ! !USES:
    1973             : !
    1974             :     IMPLICIT NONE
    1975             : !
    1976             : ! !INPUT PARAMETERS:
    1977             : !
    1978             :     INTEGER,          INTENT(IN   ) :: fID             ! Ncdf File ID
    1979             :     INTEGER,          INTENT(IN   ) :: AXIS            ! 1=lon, 2=lat
    1980             :     INTEGER,          INTENT(IN   ) :: NMID            ! # of midpoints
    1981             :     REAL*4,           INTENT(IN   ) :: MID(NMID)       ! midpoints
    1982             : !
    1983             : ! !INPUT/OUTPUT PARAMETERS:
    1984             : !
    1985             :     REAL*4,           POINTER       :: EDGE(:)         ! edges
    1986             :     INTEGER,          INTENT(INOUT) :: NEDGE           ! # of edges
    1987             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    1988             : !
    1989             : ! !REVISION HISTORY:
    1990             : !  See https://github.com/geoschem/hemco for complete history
    1991             : !EOP
    1992             : !------------------------------------------------------------------------------
    1993             : !BOC
    1994             : 
    1995             :     !======================================================================
    1996             :     ! NC_GET_GRID_EDGES_SP begins here
    1997             :     !======================================================================
    1998             : 
    1999             :     CALL NC_GET_GRID_EDGES_C( fID, AXIS, NMID, NEDGE, RC, &
    2000           0 :                               MID4=MID,  EDGE4=EDGE )
    2001             : 
    2002           0 :   END SUBROUTINE NC_GET_GRID_EDGES_SP
    2003             : !EOC
    2004             : !------------------------------------------------------------------------------
    2005             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2006             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2007             : !------------------------------------------------------------------------------
    2008             : !BOP
    2009             : !
    2010             : ! !IROUTINE: Nc_Get_Grid_Edges_Dp
    2011             : !
    2012             : ! !DESCRIPTION: Routine to get the longitude or latitude edges. If the edge
    2013             : ! cannot be read from the netCDF file, they are calculated from the provided
    2014             : ! grid midpoints. Use the axis input argument to discern between longitude
    2015             : ! (axis 1) and latitude (axis 2).
    2016             : !\\
    2017             : !\\
    2018             : ! !INTERFACE:
    2019             : !
    2020           0 :   SUBROUTINE NC_GET_GRID_EDGES_DP( fID, AXIS, MID, NMID, EDGE, NEDGE, RC )
    2021             : !
    2022             : ! !USES:
    2023             : !
    2024             :     IMPLICIT NONE
    2025             : !
    2026             : ! !INPUT PARAMETERS:
    2027             : !
    2028             :     INTEGER,          INTENT(IN   ) :: fID             ! Ncdf File ID
    2029             :     INTEGER,          INTENT(IN   ) :: AXIS            ! 1=lon, 2=lat
    2030             :     INTEGER,          INTENT(IN   ) :: NMID            ! # of midpoints
    2031             :     REAL*8,           INTENT(IN   ) :: MID(NMID)       ! midpoints
    2032             : !
    2033             : ! !INPUT/OUTPUT PARAMETERS:
    2034             : !
    2035             :     REAL*8,           POINTER       :: EDGE(:)         ! edges
    2036             :     INTEGER,          INTENT(INOUT) :: NEDGE           ! # of edges
    2037             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    2038             : !
    2039             : ! !REVISION HISTORY:
    2040             : !  See https://github.com/geoschem/hemco for complete history
    2041             : !EOP
    2042             : !------------------------------------------------------------------------------
    2043             : !BOC
    2044             : 
    2045             :     !======================================================================
    2046             :     ! NC_GET_GRID_EDGES_DP begins here
    2047             :     !======================================================================
    2048             : 
    2049             :     CALL NC_GET_GRID_EDGES_C( fID, AXIS, NMID, NEDGE, RC, &
    2050           0 :                               MID8=MID,  EDGE8=EDGE )
    2051             : 
    2052           0 :   END SUBROUTINE NC_GET_GRID_EDGES_DP
    2053             : !EOC
    2054             : !------------------------------------------------------------------------------
    2055             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2056             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2057             : !------------------------------------------------------------------------------
    2058             : !BOP
    2059             : !
    2060             : ! !IROUTINE: Nc_Get_Grid_Edges_C
    2061             : !
    2062             : ! !DESCRIPTION: Routine to get the longitude or latitude edges. If the edge
    2063             : ! cannot be read from the netCDF file, they are calculated from the provided
    2064             : ! grid midpoints. Use the axis input argument to discern between longitude
    2065             : ! (axis 1) and latitude (axis 2).
    2066             : !\\
    2067             : !\\
    2068             : ! !INTERFACE:
    2069             : !
    2070           0 :   SUBROUTINE NC_GET_GRID_EDGES_C( fID, AXIS, NMID, NEDGE, RC, &
    2071           0 :                                   MID4, MID8, EDGE4, EDGE8 )
    2072             : !
    2073             : ! !INPUT PARAMETERS:
    2074             : !
    2075             :     INTEGER,          INTENT(IN   ) :: fID             ! Ncdf File ID
    2076             :     INTEGER,          INTENT(IN   ) :: AXIS            ! 1=lon, 2=lat
    2077             :     INTEGER,          INTENT(IN   ) :: NMID            ! # of midpoints
    2078             :     REAL*4, OPTIONAL, INTENT(IN   ) :: MID4(NMID)       ! midpoints
    2079             :     REAL*8, OPTIONAL, INTENT(IN   ) :: MID8(NMID)       ! midpoints
    2080             : !
    2081             : ! !INPUT/OUTPUT PARAMETERS:
    2082             : !
    2083             :     REAL*4, OPTIONAL, POINTER       :: EDGE4(:)         ! edges
    2084             :     REAL*8, OPTIONAL, POINTER       :: EDGE8(:)         ! edges
    2085             :     INTEGER,          INTENT(INOUT) :: NEDGE           ! # of edges
    2086             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    2087             : !
    2088             : ! !REVISION HISTORY:
    2089             : !  See https://github.com/geoschem/hemco for complete history
    2090             : !EOP
    2091             : !------------------------------------------------------------------------------
    2092             : !BOC
    2093             : !
    2094             : ! !LOCAL VARIABLES:
    2095             : !
    2096             :     LOGICAL              :: PoleMid
    2097             :     INTEGER              :: I, AS
    2098             :     CHARACTER(LEN=255)   :: ncVar, ThisUnit
    2099             : 
    2100             :     !======================================================================
    2101             :     ! NC_GET_GRID_EDGES_DP begins here
    2102             :     !======================================================================
    2103             : 
    2104             :     ! Error trap: edge and mid must be same kind
    2105           0 :     IF ( PRESENT(EDGE4) ) THEN
    2106           0 :        IF ( .NOT. PRESENT(MID4) ) THEN
    2107           0 :           PRINT *, 'If you provide EDGE4, you must also provide MID4'
    2108           0 :           RC = -999
    2109           0 :           RETURN
    2110             :        ENDIF
    2111           0 :     ELSEIF ( PRESENT(EDGE8) ) THEN
    2112           0 :        IF ( .NOT. PRESENT(MID8) ) THEN
    2113           0 :           PRINT *, 'If you provide EDGE8, you must also provide MID8'
    2114           0 :           RC = -999
    2115           0 :           RETURN
    2116             :        ENDIF
    2117             :     ELSE
    2118           0 :        PRINT *, 'EDGE4 or EDGE8 must be given'
    2119           0 :        RC = -999
    2120           0 :        RETURN
    2121             :     ENDIF
    2122             : 
    2123             :     ! Try to read edges from ncdf file
    2124           0 :     IF ( AXIS == 1 ) THEN
    2125           0 :        ncVar = 'lon_edge'
    2126           0 :     ELSEIF ( AXIS == 2 ) THEN
    2127           0 :        ncVar = 'lat_edge'
    2128             :     ENDIF
    2129             : 
    2130           0 :     IF ( PRESENT(EDGE4) ) THEN
    2131           0 :        CALL NC_READ_VAR( fID, TRIM(ncVar), nEdge, ThisUnit, Edge4, RC )
    2132             :     ELSE
    2133           0 :        CALL NC_READ_VAR( fID, TRIM(ncVar), nEdge, ThisUnit, Edge8, RC )
    2134             :     ENDIF
    2135           0 :     IF ( RC /= 0 ) RETURN
    2136             : 
    2137             :     ! Also try 'XXX_edges'
    2138           0 :     IF ( nEdge == 0 ) THEN
    2139           0 :        IF ( AXIS == 1 ) THEN
    2140           0 :           ncVar = 'lon_edges'
    2141           0 :        ELSEIF ( AXIS == 2 ) THEN
    2142           0 :           ncVar = 'lat_edges'
    2143             :        ENDIF
    2144           0 :        IF ( PRESENT(EDGE4) ) THEN
    2145           0 :           CALL NC_READ_VAR( fID, 'lon_edges', nEdge, ThisUnit, Edge4, RC )
    2146             :        ELSE
    2147           0 :           CALL NC_READ_VAR( fID, 'lon_edges', nEdge, ThisUnit, Edge8, RC )
    2148             :        ENDIF
    2149           0 :        IF ( RC /= 0 ) RETURN
    2150             :     ENDIF
    2151             : 
    2152             :     ! Sanity check if edges are read from files: dimension must be nlon + 1!
    2153           0 :     IF ( nEdge > 0 ) THEN
    2154           0 :        IF ( nEdge /= (nMid + 1) ) THEN
    2155           0 :           PRINT *, 'Edge has incorrect length!'
    2156           0 :           RC = -999; RETURN
    2157             :        ENDIF
    2158             : 
    2159             :     ! If not read from file, calculate from provided lon midpoints.
    2160             :     ELSE
    2161             : 
    2162           0 :        nEdge = nMid + 1
    2163           0 :        IF ( PRESENT(EDGE4) ) THEN
    2164           0 :           IF ( ASSOCIATED ( Edge4 ) ) DEALLOCATE( Edge4 )
    2165           0 :           ALLOCATE ( Edge4(nEdge), STAT=AS )
    2166           0 :           IF ( AS /= 0 ) THEN
    2167           0 :              PRINT *, 'Edge alloc. error in NC_GET_LON_EDGES (ncdf_mod.F90)'
    2168           0 :              RC = -999; RETURN
    2169             :           ENDIF
    2170           0 :           Edge4 = 0.0
    2171             :        ELSE
    2172           0 :           IF ( ASSOCIATED ( Edge8 ) ) DEALLOCATE( Edge8 )
    2173           0 :           ALLOCATE ( Edge8(nEdge), STAT=AS )
    2174             :           IF ( AS /= 0 ) THEN
    2175           0 :              PRINT *, 'Edge alloc. error in NC_GET_LON_EDGES (ncdf_mod.F90)'
    2176           0 :              RC = -999; RETURN
    2177             :           ENDIF
    2178           0 :           Edge8 = 0.0d0
    2179             :        ENDIF
    2180             : 
    2181             :        ! Get leftmost edge by extrapolating from first two midpoints.
    2182             :        ! Error trap: for latitude axis, first edge must not be below -90!
    2183           0 :        IF ( PRESENT(EDGE4) ) THEN
    2184           0 :           Edge4(1) = Mid4(1) - ( (Mid4(2) - Mid4(1) ) / 2.0 )
    2185           0 :           IF ( Edge4(1) < -90.0 .AND. AXIS == 2 ) Edge4(1) = -90.0
    2186             :        ELSE
    2187           0 :           Edge8(1) = Mid8(1) - ( (Mid8(2) - Mid8(1) ) / 2.0d0 )
    2188           0 :           IF ( Edge8(1) < -90.0d0 .AND. AXIS == 2 ) Edge8(1) = -90.0d0
    2189             :        ENDIF
    2190             : 
    2191             :        ! Calculate second edge. We need to catch the case where the first
    2192             :        ! latitude mid-point is -90 (this is the case for GEOS-5 generic
    2193             :        ! grids...). In that case, the second edge is put in the middle of
    2194             :        ! the first two mid points (e.g. between -90 and -89). In all other
    2195             :        ! case, we calculate it from the previously calculated left edge.
    2196             :        IF ( PRESENT(EDGE4) ) THEN
    2197           0 :           IF ( Mid4(1) == Edge4(1) ) THEN
    2198           0 :              Edge4(2) = Mid4(1) + ( Mid4(2) - Mid4(1) ) / 2.0
    2199           0 :              PoleMid  = .TRUE.
    2200             :           ELSE
    2201           0 :              Edge4(2) = Mid4(1) + Mid4(1) - Edge4(1)
    2202           0 :              PoleMid  = .FALSE.
    2203             :           ENDIF
    2204             : 
    2205             :           ! Sequentially calculate the right edge from the previously
    2206             :           ! calculated left edge.
    2207           0 :           DO I = 2, nMid
    2208           0 :              Edge4(I+1) = Mid4(I) + Mid4(I) - Edge4(I)
    2209             :           ENDDO
    2210             : 
    2211             :           ! Error check: max. lat edge must not exceed +90!
    2212           0 :           IF ( Edge4(nMId+1) > 90.01 .AND. AXIS == 2 ) THEN
    2213           0 :              IF ( PoleMid ) THEN
    2214           0 :                 Edge4(nMid+1) = 90.0
    2215             :              ELSE
    2216           0 :                 PRINT *, 'Uppermost latitude edge above 90 deg north!'
    2217           0 :                 PRINT *, Edge4
    2218           0 :                 RC = -999; RETURN
    2219             :              ENDIF
    2220             :           ENDIF
    2221             : 
    2222             :        ! Real8
    2223             :        ELSE
    2224           0 :           IF ( Mid8(1) == Edge8(1) ) THEN
    2225           0 :              Edge8(2) = Mid8(1) + ( Mid8(2) - Mid8(1) ) / 2.0d0
    2226           0 :              PoleMid  = .TRUE.
    2227             :           ELSE
    2228           0 :              Edge8(2) = Mid8(1) + Mid8(1) - Edge8(1)
    2229           0 :              PoleMid  = .FALSE.
    2230             :           ENDIF
    2231             : 
    2232             :           ! Sequentially calculate the right edge from the previously
    2233             :           ! calculated left edge.
    2234           0 :           DO I = 2, nMid
    2235           0 :              Edge8(I+1) = Mid8(I) + Mid8(I) - Edge8(I)
    2236             :           ENDDO
    2237             : 
    2238             :           ! Error check: max. lat edge must not exceed +90!
    2239           0 :           IF ( Edge8(nMId+1) > 90.01d0 .AND. AXIS == 2 ) THEN
    2240           0 :              IF ( PoleMid ) THEN
    2241           0 :                 Edge8(nMid+1) = 90.0d0
    2242             :              ELSE
    2243           0 :                 PRINT *, 'Uppermost latitude edge above 90 deg north!'
    2244           0 :                 PRINT *, Edge8
    2245           0 :                 RC = -999; RETURN
    2246             :              ENDIF
    2247             :           ENDIF
    2248             :        ENDIF
    2249             :     ENDIF
    2250             : 
    2251             :     ! Return w/ success
    2252           0 :     RC = 0
    2253             : 
    2254           0 :   END SUBROUTINE NC_GET_GRID_EDGES_C
    2255             : !EOC
    2256             : !------------------------------------------------------------------------------
    2257             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2258             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2259             : !------------------------------------------------------------------------------
    2260             : !BOP
    2261             : !
    2262             : ! !IROUTINE: Nc_Get_Sigma_Levels_Sp
    2263             : !
    2264             : ! !DESCRIPTION: Wrapper routine to get the sigma levels in single precision.
    2265             : !\\
    2266             : !\\
    2267             : ! !INTERFACE:
    2268             : !
    2269           0 :   SUBROUTINE NC_GET_SIGMA_LEVELS_SP( fID,  ncFile, levName, lon1, lon2, lat1, &
    2270             :                                      lat2, lev1,   lev2,    time, SigLev, dir, RC )
    2271             : !
    2272             : ! !INPUT PARAMETERS:
    2273             : !
    2274             :     INTEGER,          INTENT(IN   ) :: fID             ! Ncdf File ID
    2275             :     CHARACTER(LEN=*), INTENT(IN   ) :: ncFile          ! ncFile
    2276             :     CHARACTER(LEN=*), INTENT(IN   ) :: levName         ! variable name
    2277             :     INTEGER,          INTENT(IN   ) :: lon1            ! lon lower bound
    2278             :     INTEGER,          INTENT(IN   ) :: lon2            ! lon upper bound
    2279             :     INTEGER,          INTENT(IN   ) :: lat1            ! lat lower bound
    2280             :     INTEGER,          INTENT(IN   ) :: lat2            ! lat upper bound
    2281             :     INTEGER,          INTENT(IN   ) :: lev1            ! lev lower bound
    2282             :     INTEGER,          INTENT(IN   ) :: lev2            ! lev upper bound
    2283             :     INTEGER,          INTENT(IN   ) :: time            ! time index
    2284             : !
    2285             : ! !INPUT/OUTPUT PARAMETERS:
    2286             : !
    2287             :     REAL*4,           POINTER       :: SigLev(:,:,:)   ! sigma levels
    2288             :     INTEGER,          INTENT(INOUT) :: dir             ! axis direction (1=up;-1=down)
    2289             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    2290             : !
    2291             : ! !REVISION HISTORY:
    2292             : !  See https://github.com/geoschem/hemco for complete history
    2293             : !EOP
    2294             : !------------------------------------------------------------------------------
    2295             : !BOC
    2296             : 
    2297             :   CALL NC_GET_SIGMA_LEVELS_C( fID,  ncFile, levName, lon1, lon2, lat1, &
    2298             :                               lat2, lev1,   lev2,    time, dir,  RC,   &
    2299           0 :                               SigLev4=SigLev )
    2300             : 
    2301           0 :   END SUBROUTINE NC_GET_SIGMA_LEVELS_SP
    2302             : !EOC
    2303             : !------------------------------------------------------------------------------
    2304             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2305             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2306             : !------------------------------------------------------------------------------
    2307             : !BOP
    2308             : !
    2309             : ! !IROUTINE: Nc_Get_Sigma_Levels_Dp
    2310             : !
    2311             : ! !DESCRIPTION: Wrapper routine to get the sigma levels in double precision.
    2312             : !\\
    2313             : !\\
    2314             : ! !INTERFACE:
    2315             : !
    2316           0 :   SUBROUTINE NC_GET_SIGMA_LEVELS_DP( fID,  ncFile, levName, lon1, lon2, lat1, &
    2317             :                                      lat2, lev1,   lev2,    time, SigLev, dir, RC )
    2318             : !
    2319             : ! !INPUT PARAMETERS:
    2320             : !
    2321             :     INTEGER,          INTENT(IN   ) :: fID             ! Ncdf File ID
    2322             :     CHARACTER(LEN=*), INTENT(IN   ) :: ncFile          ! ncFile
    2323             :     CHARACTER(LEN=*), INTENT(IN   ) :: levName         ! variable name
    2324             :     INTEGER,          INTENT(IN   ) :: lon1            ! lon lower bound
    2325             :     INTEGER,          INTENT(IN   ) :: lon2            ! lon upper bound
    2326             :     INTEGER,          INTENT(IN   ) :: lat1            ! lat lower bound
    2327             :     INTEGER,          INTENT(IN   ) :: lat2            ! lat upper bound
    2328             :     INTEGER,          INTENT(IN   ) :: lev1            ! lev lower bound
    2329             :     INTEGER,          INTENT(IN   ) :: lev2            ! lev upper bound
    2330             :     INTEGER,          INTENT(IN   ) :: time            ! time index
    2331             : !
    2332             : ! !INPUT/OUTPUT PARAMETERS:
    2333             : !
    2334             :     REAL*8,           POINTER       :: SigLev(:,:,:)   ! sigma levels
    2335             :     INTEGER,          INTENT(INOUT) :: dir             ! axis direction (1=up;-1=down)
    2336             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    2337             : !
    2338             : ! !REVISION HISTORY:
    2339             : !  See https://github.com/geoschem/hemco for complete history
    2340             : !EOP
    2341             : !------------------------------------------------------------------------------
    2342             : !BOC
    2343             : 
    2344             :   CALL NC_GET_SIGMA_LEVELS_C( fID,  ncFile, levName, lon1, lon2, lat1, &
    2345             :                               lat2, lev1,   lev2,    time, dir,  RC,   &
    2346           0 :                               SigLev8=SigLev )
    2347             : 
    2348           0 :   END SUBROUTINE NC_GET_SIGMA_LEVELS_DP
    2349             : !EOC
    2350             : !------------------------------------------------------------------------------
    2351             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2352             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2353             : !------------------------------------------------------------------------------
    2354             : !BOP
    2355             : !
    2356             : ! !IROUTINE: Nc_Get_Sigma_Levels_C
    2357             : !
    2358             : ! !DESCRIPTION: Routine to get the sigma levels from the netCDF file
    2359             : ! within the given grid bounds and for the given time index. This routine
    2360             : ! attempts to construct the 3D sigma values from provided variable levName.
    2361             : ! The vertical coordinate system is determined based upon the variable
    2362             : ! attribute "standard\_name".
    2363             : !\\
    2364             : !\\
    2365             : ! For now, only hybrid sigma coordinate systems are supported, and the
    2366             : ! standard\_name attribute must follow CF conventions and be set to
    2367             : ! "atmosphere\_hybrid\_sigma\_pressure\_coordinate".
    2368             : !\\
    2369             : !\\
    2370             : ! !INTERFACE:
    2371             : !
    2372           0 :   SUBROUTINE NC_GET_SIGMA_LEVELS_C( fID,  ncFile, levName, lon1, lon2, lat1, &
    2373             :                                     lat2, lev1,   lev2,    time, dir,  RC,   &
    2374             :                                     SigLev4, SigLev8 )
    2375             : !
    2376             : ! !INPUT PARAMETERS:
    2377             : !
    2378             :     INTEGER,          INTENT(IN   ) :: fID             ! Ncdf File ID
    2379             :     CHARACTER(LEN=*), INTENT(IN   ) :: ncFile          ! ncFile
    2380             :     CHARACTER(LEN=*), INTENT(IN   ) :: levName         ! variable name
    2381             :     INTEGER,          INTENT(IN   ) :: lon1            ! lon lower bound
    2382             :     INTEGER,          INTENT(IN   ) :: lon2            ! lon upper bound
    2383             :     INTEGER,          INTENT(IN   ) :: lat1            ! lat lower bound
    2384             :     INTEGER,          INTENT(IN   ) :: lat2            ! lat upper bound
    2385             :     INTEGER,          INTENT(IN   ) :: lev1            ! lev lower bound
    2386             :     INTEGER,          INTENT(IN   ) :: lev2            ! lev upper bound
    2387             :     INTEGER,          INTENT(IN   ) :: time            ! time index
    2388             : !
    2389             : ! !INPUT/OUTPUT PARAMETERS:
    2390             : !
    2391             :     INTEGER,          INTENT(  OUT) :: dir             ! axis direction (1=up;-1=down)
    2392             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    2393             :     REAL*4, OPTIONAL, POINTER       :: SigLev4(:,:,:)  ! sigma levels w/in
    2394             :     REAL*8, OPTIONAL, POINTER       :: SigLev8(:,:,:)  ! specified boundaries
    2395             : !
    2396             : ! !REVISION HISTORY:
    2397             : !  See https://github.com/geoschem/hemco for complete history
    2398             : !EOP
    2399             : !------------------------------------------------------------------------------
    2400             : !BOC
    2401             : !
    2402             : ! !LOCAL VARIABLES:
    2403             : !
    2404             :     ! Scalars
    2405             :     LOGICAL            :: found
    2406             :     INTEGER            :: a_type    ! netCDF attribute type
    2407             : 
    2408             :     ! Straings
    2409             :     CHARACTER(LEN=255) :: stdname
    2410             :     CHARACTER(LEN=255) :: a_name    ! netCDF attribute name
    2411             :     CHARACTER(LEN=255) :: a_val     ! netCDF attribute value
    2412             : 
    2413             :     !========================================================================
    2414             :     ! NC_GET_SIGMA_LEVELS begins here
    2415             :     !========================================================================
    2416             : 
    2417             :     ! Initialize
    2418           0 :     RC = 0
    2419             : 
    2420             :     !------------------------------------------------------------------------
    2421             :     ! Test that the level index variable exists
    2422             :     !------------------------------------------------------------------------
    2423           0 :     found = Ncdoes_Var_Exist( fID, TRIM(levName) )
    2424           0 :     IF ( .not. found ) THEN
    2425           0 :        WRITE(*,*) 'Cannot find level variable ',                             &
    2426           0 :                   TRIM(levName), ' in ', TRIM(ncFile), '!'
    2427           0 :        RC = -999
    2428           0 :        RETURN
    2429             :     ENDIF
    2430             : 
    2431             :     !------------------------------------------------------------------------
    2432             :     ! Look for the "standard_name" or "long_name" attribute,
    2433             :     ! which will be used to identify the vertical coordinate
    2434             :     !------------------------------------------------------------------------
    2435             : 
    2436             :     ! First look for "standard_name"
    2437           0 :     a_name = "standard_name"
    2438           0 :     found  = NcDoes_Attr_Exist( fId, TRIM(levName), TRIM(a_name), a_type )
    2439             : 
    2440             :     ! If not found, then look for "long_name"
    2441           0 :     IF ( .not. found ) THEN
    2442           0 :        a_name = "long_name"
    2443           0 :        found  = NcDoes_Attr_Exist( fId, TRIM(levName), TRIM(a_name), a_type )
    2444             : 
    2445             :        ! If neither attribute is found, then exit with error
    2446           0 :        IF ( .not. found ) THEN
    2447           0 :           WRITE(*,*) 'Cannot find level attribute ', TRIM(a_name),           &
    2448           0 :                ' in variable ', TRIM(levName), ' - File: ', TRIM(ncFile), '!'
    2449           0 :           RC = -999
    2450           0 :           RETURN
    2451             :        ENDIF
    2452             :     ENDIF
    2453             : 
    2454             :     ! Read the "standard_name" or "long_name" attribute (whichever is found)
    2455           0 :     CALL NcGet_Var_Attributes( fID, TRIM(levName), TRIM(a_name), a_val )
    2456             : 
    2457             :     !------------------------------------------------------------------------
    2458             :     ! Call functions to calculate sigma levels depending on the coordinate
    2459             :     ! system.
    2460             :     !------------------------------------------------------------------------
    2461           0 :     IF ( TRIM(a_val) == 'atmosphere_hybrid_sigma_pressure_coordinate' ) THEN
    2462             : 
    2463           0 :        IF ( PRESENT( SigLev4 ) ) THEN
    2464             : 
    2465             :           ! Return 4-byte real array
    2466             :           CALL NC_GET_SIG_FROM_HYBRID( fID,  levName, lon1, lon2,            &
    2467             :                                        lat1, lat2,    lev1, lev2,            &
    2468           0 :                                        time, dir,     RC,   SigLev4=SigLev4 )
    2469           0 :        ELSE IF ( PRESENT( SigLev8 ) ) THEN
    2470             : 
    2471             :           ! Return 8-byte real array
    2472             :           CALL NC_GET_SIG_FROM_HYBRID( fID,  levName, lon1, lon2,            &
    2473             :                                        lat1, lat2,    lev1, lev2,            &
    2474           0 :                                        time,  dir,    RC,   SigLev8=SigLev8 )
    2475             :        ELSE
    2476             : 
    2477             :           ! Othrwise exit with error
    2478           0 :           WRITE(*,*) 'SigLev array is missing!'
    2479           0 :           RC = -999
    2480           0 :           RETURN
    2481             :        ENDIF
    2482           0 :        IF ( RC /= 0 ) RETURN
    2483             : 
    2484             :     ELSE
    2485             : 
    2486             :        ! NOTE: for now, only hybrid sigma coordinates are supported!
    2487             :        ! So exit with error if we get this far
    2488           0 :        WRITE(*,*) 'Invalid level standard name: ', TRIM(stdname),            &
    2489           0 :             ' in ', TRIM(ncFile)
    2490           0 :        RC = -999
    2491           0 :        RETURN
    2492             :     ENDIF
    2493             : 
    2494             :     ! Return w/ success
    2495           0 :     RC = 0
    2496             : 
    2497             :   END SUBROUTINE NC_GET_SIGMA_LEVELS_C
    2498             : !EOC
    2499             : !------------------------------------------------------------------------------
    2500             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2501             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2502             : !------------------------------------------------------------------------------
    2503             : !BOP
    2504             : !
    2505             : ! !IROUTINE: Nc_Get_Sig_From_Hybrid
    2506             : !
    2507             : ! !DESCRIPTION: Calculates the sigma level field for a hybrid sigma coordinate
    2508             : ! system:
    2509             : !
    2510             : ! sigma(i,j,l,t) = ( a(l) * p0 + b(l) * ps(i,j,t) ) / ps(i,j,t)
    2511             : !
    2512             : ! or (p0=1):
    2513             : !
    2514             : ! sigma(i,j,l,t) = ( ap(l) + b(l) * ps(i,j,t) ) / ps(i,j,t)
    2515             : !
    2516             : ! where sigma are the sigma levels, ap and bp are the hybrid sigma coordinates,
    2517             : ! p0 is the constant reference pressure, and ps is the surface pressure. The
    2518             : ! variable names of ap, p0, bp, and ps are taken from level attribute
    2519             : ! `formula\_terms`.
    2520             : !\\
    2521             : !\\
    2522             : ! The direction of the vertical coordinate system is determined from attribute
    2523             : ! `positive` (up or down) or - if not found - from the b values, whereby it is
    2524             : ! assumed that the higher b value is found at the surface. The return argument
    2525             : ! dir is set to 1 for upward coordinates (level 1 is surface level) and -1 for
    2526             : ! downward coordinates (level 1 is top of atmosphere).
    2527             : !\\
    2528             : !\\
    2529             : ! !REMARKS:
    2530             : ! Example of valid netCDF meta-data: The attributes `standard\_name` and
    2531             : ! `formula\_terms` are required, as is the 3D surface pressure field.
    2532             : !
    2533             : ! double lev(lev) ;\\
    2534             : !        lev:standard_name = "atmosphere_hybrid_sigma_pressure_coordinate" ;\\
    2535             : !        lev:units = "level" ;\\
    2536             : !        lev:positive = "down" ;\\
    2537             : !        lev:formula_terms = "ap: hyam b: hybm ps: PS" ;\\
    2538             : ! double hyam(nhym) ;\\
    2539             : !        hyam:long_name = "hybrid A coefficient at layer midpoints" ;\\
    2540             : !        hyam:units = "hPa" ;\\
    2541             : ! double hybm(nhym) ;\\
    2542             : !        hybm:long_name = "hybrid B coefficient at layer midpoints" ;\\
    2543             : !        hybm:units = "1" ;\\
    2544             : ! double time(time) ;\\
    2545             : !        time:standard_name = "time" ;\\
    2546             : !        time:units = "days since 2000-01-01 00:00:00" ;\\
    2547             : !        time:calendar = "standard" ;\\
    2548             : ! double PS(time, lat, lon) ;\\
    2549             : !        PS:long_name = "surface pressure" ;\\
    2550             : !        PS:units = "hPa" ;\\
    2551             : !
    2552             : ! !INTERFACE:
    2553             : !
    2554           0 :   SUBROUTINE NC_GET_SIG_FROM_HYBRID ( fID,  levName, lon1,   lon2, lat1,     &
    2555             :                                       lat2, lev1,    lev2,   time, dir,      &
    2556             :                                       RC,   sigLev4, sigLev8                )
    2557             : !
    2558             : ! !INPUT PARAMETERS:
    2559             : !
    2560             :     INTEGER,          INTENT(IN   ) :: fID             ! Ncdf File ID
    2561             :     CHARACTER(LEN=*), INTENT(IN   ) :: levName         ! variable name
    2562             :     INTEGER,          INTENT(IN   ) :: lon1            ! lon lower bound
    2563             :     INTEGER,          INTENT(IN   ) :: lon2            ! lon upper bound
    2564             :     INTEGER,          INTENT(IN   ) :: lat1            ! lat lower bound
    2565             :     INTEGER,          INTENT(IN   ) :: lat2            ! lat upper bound
    2566             :     INTEGER,          INTENT(IN   ) :: lev1            ! lev lower bound
    2567             :     INTEGER,          INTENT(IN   ) :: lev2            ! lev upper bound
    2568             :     INTEGER,          INTENT(IN   ) :: time            ! time index
    2569             : !
    2570             : ! !INPUT/OUTPUT PARAMETERS:
    2571             : !
    2572             :     REAL*4, OPTIONAL, POINTER       :: SigLev4(:,:,:)  ! sigma levels w/in
    2573             :     REAL*8, OPTIONAL, POINTER       :: SigLev8(:,:,:)  ! specified boundaries
    2574             :     INTEGER,          INTENT(  OUT) :: dir             ! axis direction (1=up;-1=down)
    2575             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    2576             : !
    2577             : ! !REVISION HISTORY:
    2578             : !  See https://github.com/geoschem/hemco for complete history
    2579             : !EOP
    2580             : !------------------------------------------------------------------------------
    2581             : !BOC
    2582             : !
    2583             : ! !LOCAL VARIABLES:
    2584             : !
    2585             :     INTEGER              :: I, J, l1, l2, AS
    2586             :     INTEGER              :: nlev, nlat, nlon
    2587             :     INTEGER              :: nlevs
    2588             :     INTEGER              :: st1d(1), ct1d(1)
    2589             :     LOGICAL              :: ok
    2590           0 :     REAL*4, POINTER      :: a(:)
    2591           0 :     REAL*4, POINTER      :: b(:)
    2592           0 :     REAL*4, POINTER      :: ps(:,:,:,:)
    2593             :     REAL*8               :: p0
    2594             :     CHARACTER(LEN=255)   :: formula, ThisUnit
    2595             :     CHARACTER(LEN=255)   :: aname, bname, psname, p0name
    2596             :     CHARACTER(LEN=255)   :: a_name    ! netCDF attribute name
    2597             :     INTEGER              :: a_type    ! netCDF attribute type
    2598             : 
    2599             :     !======================================================================
    2600             :     ! NC_GET_SIG_FROM_HYBRID begins here
    2601             :     !======================================================================
    2602             : 
    2603             :     ! Init
    2604           0 :     p0 = -999.d0
    2605           0 :     a  => NULL()
    2606           0 :     b  => NULL()
    2607           0 :     ps => NULL()
    2608             : 
    2609             :     ! Get desired grid dimensions.
    2610           0 :     nlon = lon2 - lon1 + 1
    2611           0 :     nlat = lat2 - lat1 + 1
    2612           0 :     nlev = lev2 - lev1 + 1
    2613             : 
    2614             :     ! Get dimension length
    2615           0 :     CALL Ncget_Dimlen ( fID, TRIM(LevName), nlevs )
    2616             : 
    2617             :     ! Sanity check
    2618           0 :     IF ( nlevs < nlev ) THEN
    2619           0 :        WRITE(*,*) TRIM(LevName), ' is only of length ', nlevs, ' - required is: ', nlev
    2620           0 :        RC = -999
    2621           0 :        RETURN
    2622             :     ENDIF
    2623             : 
    2624             :     !------------------------------------------------------------------------
    2625             :     ! Get formula and parse variable names (ap, bp, p0, ps)
    2626             :     !------------------------------------------------------------------------
    2627             : 
    2628             :     ! Get formula
    2629           0 :     a_name = "formula_terms"
    2630           0 :     IF ( .NOT. NcDoes_Attr_Exist ( fID,          TRIM(levName),            &
    2631             :                                    TRIM(a_name), a_type         ) ) THEN
    2632           0 :        WRITE(*,*) 'Cannot find attribute ', TRIM(a_name), ' in variable ', &
    2633           0 :                   TRIM(levName)
    2634           0 :        RC = -999
    2635           0 :        RETURN
    2636             :     ENDIF
    2637           0 :     CALL NcGet_Var_Attributes( fID, TRIM(levName), TRIM(a_name), formula )
    2638             : 
    2639             :     ! Get variable names
    2640             :     !-------------------
    2641           0 :     I = INDEX( formula, 'a:' )
    2642           0 :     IF ( I > 0 ) THEN
    2643           0 :        CALL GetVarFromFormula( formula, 'a:',  aname, RC )
    2644           0 :        IF ( RC /= 0 ) RETURN
    2645           0 :        CALL GetVarFromFormula( formula, 'p0:', p0name, RC )
    2646           0 :        IF ( RC /= 0 ) RETURN
    2647             :     ELSE
    2648           0 :        CALL GetVarFromFormula( formula, 'ap:', aname, RC )
    2649           0 :        IF ( RC /= 0 ) RETURN
    2650           0 :        p0 = 1.0d0
    2651             :     ENDIF
    2652           0 :     IF ( RC /= 0 ) RETURN
    2653             : 
    2654           0 :     CALL GetVarFromFormula( formula, 'b:', bname, RC )
    2655           0 :     IF ( RC /= 0 ) RETURN
    2656             : 
    2657           0 :     CALL GetVarFromFormula( formula, 'ps:', psname, RC )
    2658           0 :     IF ( RC /= 0 ) RETURN
    2659             : 
    2660             :     !------------------------------------------------------------------------
    2661             :     ! Read variables from file.
    2662             :     !------------------------------------------------------------------------
    2663             : 
    2664           0 :     ALLOCATE ( a(nlevs), b(nlevs) )
    2665           0 :     st1d = (/ 1     /)
    2666           0 :     ct1d = (/ nlevs /)
    2667             : 
    2668             :     ! read a
    2669             :     !-------
    2670           0 :     IF ( .NOT. Ncdoes_Var_Exist( fID, TRIM(aname) ) ) THEN
    2671           0 :        WRITE(*,*) 'Cannot find variable ', TRIM(aname), '!'
    2672           0 :        RC = -999
    2673           0 :        RETURN
    2674             :     ENDIF
    2675           0 :     CALL NcRd( a, fID, TRIM(aname), st1d, ct1d )
    2676             : 
    2677             :     ! eventually read p0
    2678             :     !-------------------
    2679           0 :     IF ( p0 < 0.0d0 ) THEN
    2680           0 :        IF ( .NOT. Ncdoes_Var_Exist( fID, TRIM(p0name) ) ) THEN
    2681           0 :           WRITE(*,*) 'Cannot find variable ', TRIM(p0name), '!'
    2682           0 :           RC = -999
    2683           0 :           RETURN
    2684             :        ENDIF
    2685           0 :     CALL NcRd( p0, fID, TRIM(p0name) )
    2686             :     ENDIF
    2687             : 
    2688             :     ! read b
    2689             :     !-------
    2690           0 :     IF ( .NOT. Ncdoes_Var_Exist( fID, TRIM(bname) ) ) THEN
    2691           0 :        WRITE(*,*) 'Cannot find variable ', TRIM(bname), '!'
    2692           0 :        RC = -999
    2693           0 :        RETURN
    2694             :     ENDIF
    2695           0 :     CALL NcRd( b, fID, TRIM(bname), st1d, ct1d )
    2696             : 
    2697             :     ! Read ps
    2698             :     !--------
    2699             :     CALL NC_READ_ARR( fID, TRIM(psname), lon1, lon2, lat1, &
    2700           0 :                       lat2, 0, 0, time,  time, ps, VarUnit=thisUnit, RC=RC )
    2701           0 :     IF ( RC /= 0 ) RETURN
    2702             : 
    2703             :     !------------------------------------------------------------------------
    2704             :     ! Determine positive axis ('up' or 'down')
    2705             :     ! Try to read it from the netCDF meta data (attribute `positive`). If not
    2706             :     ! found, determine it from b values (b value at surface higher than at
    2707             :     ! top of atmosphere).
    2708             :     !------------------------------------------------------------------------
    2709           0 :     a_name = "positive"
    2710           0 :     IF ( NcDoes_Attr_Exist( fID, TRIM(levName), TRIM(a_name), a_type ) ) THEN
    2711           0 :        CALL NcGet_Var_Attributes( fID, TRIM(levName), TRIM(a_name), formula )
    2712           0 :        IF ( TRIM(formula) == 'up' ) THEN
    2713           0 :           dir = 1
    2714           0 :        ELSEIF ( TRIM(formula) == 'down' ) THEN
    2715           0 :           dir = -1
    2716             :        ELSE
    2717           0 :           WRITE(*,*) 'level attribute `positive` must be `up` ', &
    2718           0 :                      'or `down`, instead: ', TRIM(formula)
    2719           0 :           RC = -999
    2720           0 :           RETURN
    2721             :        ENDIF
    2722             : 
    2723             :     ! determine direction from b values.
    2724             :     ELSE
    2725             : 
    2726           0 :        IF ( b(1) > b(nlevs) ) THEN
    2727           0 :           dir = 1
    2728             :        ELSE
    2729           0 :           dir = -1
    2730             :        ENDIF
    2731             :     ENDIF
    2732             : 
    2733             :     !------------------------------------------------------------------------
    2734             :     ! Determine vertical indeces to be used. It is possible to calculate
    2735             :     ! the pressure only for a given number of layers (as specified by input
    2736             :     ! arguments lev1 and lev2). Assume those are always from bottom to top,
    2737             :     ! i.e. counting `upwards`.
    2738             :     !------------------------------------------------------------------------
    2739             : 
    2740           0 :     IF ( dir == -1 ) THEN
    2741           0 :        l1 = nlevs - lev2 + 1
    2742           0 :        l2 = nlevs - lev1 + 1
    2743             :     ELSE
    2744             :        l1 = lev1
    2745             :        l2 = lev2
    2746             :     ENDIF
    2747             : 
    2748             :     !------------------------------------------------------------------------
    2749             :     ! Calculate sigma values at grid edges
    2750             :     !------------------------------------------------------------------------
    2751             : 
    2752           0 :     IF ( PRESENT(SigLev4) ) THEN
    2753           0 :        IF ( ASSOCIATED(SigLev4) ) DEALLOCATE(SigLev4)
    2754           0 :        ALLOCATE(SigLev4(nlon,nlat,nlev),STAT=AS)
    2755           0 :     ELSEIF ( PRESENT(SigLev8) ) THEN
    2756           0 :        IF ( ASSOCIATED(SigLev8) ) DEALLOCATE(SigLev8)
    2757           0 :        ALLOCATE(SigLev8(nlon,nlat,nlev),STAT=AS)
    2758             :     ELSE
    2759           0 :        WRITE(*,*) 'SigLev must be provided!'
    2760           0 :        RC = -999
    2761           0 :        RETURN
    2762             :     ENDIF
    2763           0 :     IF ( AS /= 0 ) THEN
    2764           0 :        WRITE(*,*) 'Cannot allocate SigLev!'
    2765           0 :        RC = -999
    2766           0 :        RETURN
    2767             :     ENDIF
    2768             : 
    2769           0 :     DO J=1,nlat
    2770           0 :     DO I=1,nlon
    2771           0 :        IF ( PRESENT(SigLev4) ) THEN
    2772           0 :           SigLev4(i,j,:) = ( ( a(l1:l2) * p0 ) + ( b(l1:l2) * ps(i,j,1,1) ) ) &
    2773           0 :                         / ps(i,j,1,1)
    2774             :        ELSE
    2775           0 :           SigLev8(i,j,:) = ( ( a(l1:l2) * p0 ) + ( b(l1:l2) * ps(i,j,1,1) ) ) &
    2776           0 :                         / ps(i,j,1,1)
    2777             :        ENDIF
    2778             :     ENDDO
    2779             :     ENDDO
    2780             : 
    2781             :     ! Cleanup
    2782           0 :     IF ( ASSOCIATED(a ) ) DEALLOCATE(a )
    2783           0 :     IF ( ASSOCIATED(b ) ) DEALLOCATE(b )
    2784           0 :     IF ( ASSOCIATED(ps) ) DEALLOCATE(ps)
    2785             : 
    2786             :     ! Return w/ success
    2787           0 :     RC = 0
    2788             : 
    2789           0 :   END SUBROUTINE NC_GET_SIG_FROM_HYBRID
    2790             : !EOC
    2791             : !------------------------------------------------------------------------------
    2792             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2793             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2794             : !------------------------------------------------------------------------------
    2795             : !BOP
    2796             : !
    2797             : ! !IROUTINE: GetVarFromFormula
    2798             : !
    2799             : ! !DESCRIPTION: helper function to extract the variable name from a vertical
    2800             : ! coordinate formula.
    2801             : !\\
    2802             : !\\
    2803             : ! !INTERFACE:
    2804             : !
    2805           0 :   SUBROUTINE GetVarFromFormula ( formula, inname, outname, RC )
    2806             : !
    2807             : ! !INPUT PARAMETERS:
    2808             : !
    2809             :     CHARACTER(LEN=*), INTENT(IN   ) :: formula
    2810             :     CHARACTER(LEN=*), INTENT(IN   ) :: inname
    2811             : !
    2812             : ! !INPUT/OUTPUT PARAMETERS:
    2813             : !
    2814             :     CHARACTER(LEN=*), INTENT(  OUT) :: outname
    2815             :     INTEGER,          INTENT(INOUT) :: RC              ! Return code
    2816             : !
    2817             : ! !REVISION HISTORY:
    2818             : !  See https://github.com/geoschem/hemco for complete history
    2819             : !EOP
    2820             : !------------------------------------------------------------------------------
    2821             : !BOC
    2822             : !
    2823             : ! !LOCAL VARIABLES:
    2824             : !
    2825             :     INTEGER              :: I, J, IDX, LN
    2826             : 
    2827             :     !======================================================================
    2828             :     ! GetVarFromFormula begins here
    2829             :     !======================================================================
    2830             : 
    2831             :     ! maximum length
    2832           0 :     LN = LEN(TRIM(formula))
    2833             : 
    2834             :     ! Get start index of string
    2835             :     !--------------------------
    2836           0 :     I = INDEX( TRIM(formula), TRIM(inname) )
    2837           0 :     IF ( I <= 0 ) THEN
    2838           0 :        WRITE(*,*) 'Cannot extract ', TRIM(inname), ' from ', TRIM(formula)
    2839           0 :        RC = -999
    2840           0 :        RETURN
    2841             :     ENDIF
    2842             : 
    2843             :     ! The variable name follows the formula string plus one space!
    2844           0 :     I = I + LEN(inname) + 1
    2845             : 
    2846           0 :     outname = ''
    2847             :     IDX = 1
    2848           0 :     DO J = I, LN
    2849           0 :        IF ( formula(J:J) == ' ' ) EXIT
    2850           0 :        outname(IDX:IDX) = formula(J:J)
    2851           0 :        IDX = IDX + 1
    2852             :     ENDDO
    2853             : 
    2854             :     ! Return w/ success
    2855           0 :     RC = 0
    2856             : 
    2857           0 :   END SUBROUTINE GetVarFromFormula
    2858             : !EOC
    2859             : !------------------------------------------------------------------------------
    2860             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2861             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2862             : !------------------------------------------------------------------------------
    2863             : !BOP
    2864             : !
    2865             : ! !IROUTINE: Nc_Write_3d
    2866             : !
    2867             : ! !DESCRIPTION: Routine to write time slices of 2D fields into netCDF.
    2868             : !\\
    2869             : !\\
    2870             : ! !INTERFACE:
    2871             : !
    2872           0 :   SUBROUTINE NC_WRITE_3D( ncFile,  I,  J,    T,  N,   lon, lat, &
    2873           0 :                           time,    timeUnit, ncVars,  ncUnits,  &
    2874           0 :                           ncLongs, ncShorts, ncArrays            )
    2875             : !
    2876             : ! !INPUT PARAMETERS:
    2877             : !
    2878             :     CHARACTER(LEN=*), INTENT(IN)  :: ncFile             ! file path+name
    2879             :     INTEGER,          INTENT(IN)  :: I                  ! # of lons
    2880             :     INTEGER,          INTENT(IN)  :: J                  ! # of lats
    2881             :     INTEGER,          INTENT(IN)  :: T                  ! # of time slices
    2882             :     INTEGER,          INTENT(IN)  :: N                  ! # of vars
    2883             :     REAL*4,           INTENT(IN)  :: lon(I)             ! longitude
    2884             :     REAL*4,           INTENT(IN)  :: lat(J)             ! latitude
    2885             :     REAL*4,           INTENT(IN)  :: time(T)            ! time
    2886             :     CHARACTER(LEN=*), INTENT(IN)  :: timeUnit           ! time unit
    2887             :     CHARACTER(LEN=*), INTENT(IN)  :: ncVars(N)          ! nc variables
    2888             :     CHARACTER(LEN=*), INTENT(IN)  :: ncUnits(N)         ! var units
    2889             :     CHARACTER(LEN=*), INTENT(IN)  :: ncLongs(N)         ! var long names
    2890             :     CHARACTER(LEN=*), INTENT(IN)  :: ncShorts(N)        ! var short names
    2891             :     REAL*4, TARGET,   INTENT(IN)  :: ncArrays(I,J,T,N)  ! var arrays
    2892             : !
    2893             : ! !REMARKS:
    2894             : !  Created with the ncCodeRead script of the NcdfUtilities package,
    2895             : !  with subsequent hand-editing.
    2896             : !
    2897             : ! !REVISION HISTORY:
    2898             : !  See https://github.com/geoschem/hemco for complete history
    2899             : !EOP
    2900             : !------------------------------------------------------------------------------
    2901             : !BOC
    2902             : !
    2903             : ! !LOCAL VARIABLES:
    2904             : !
    2905             :     ! Scalars
    2906             :     INTEGER            :: fId, II
    2907             :     REAL*4, POINTER    :: tmpArr(:,:,:) => NULL()
    2908             : 
    2909             :     !======================================================================
    2910             :     ! NC_WRITE_3D begins here
    2911             :     !======================================================================
    2912             : 
    2913             :     CALL NC_DEFINE(ncFile=ncFile, nLon=I,            nLat=J,         &
    2914             :                    nTime=T,       timeUnit=timeUnit, ncVars=ncVars,  &
    2915             :                    ncUnits=ncUnits,ncLongs=ncLongs,ncShorts=ncShorts,&
    2916           0 :                    fId=fId )
    2917             : 
    2918           0 :     CALL NC_WRITE_DIMS( fID=fId, lon=lon, lat=lat, time=time )
    2919             : 
    2920           0 :     DO II = 1, N
    2921           0 :        tmpArr => ncArrays(:,:,:,II)
    2922           0 :        CALL NC_WRITE_DATA_3D ( fId, ncVars(II), tmpArr )
    2923           0 :        tmpArr => NULL()
    2924             :     ENDDO
    2925             : 
    2926           0 :     CALL NcCl( fId )
    2927             : 
    2928           0 :   END SUBROUTINE NC_WRITE_3D
    2929             : !EOC
    2930             : !------------------------------------------------------------------------------
    2931             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    2932             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    2933             : !------------------------------------------------------------------------------
    2934             : !BOP
    2935             : !
    2936             : ! !IROUTINE: Nc_Write_4d
    2937             : !
    2938             : ! !DESCRIPTION: Routine to write time slices of 3D fields into netCDF.
    2939             : !\\
    2940             : !\\
    2941             : ! !INTERFACE:
    2942             : !
    2943           0 :   SUBROUTINE NC_WRITE_4D (ncFile,  I, J, L, T, N, lon, lat, lev, &
    2944           0 :                           time,    timeUnit, ncVars,  ncUnits,   &
    2945           0 :                           ncLongs, ncShorts, ncArrays             )
    2946             : !
    2947             : ! !INPUT PARAMETERS:
    2948             : !
    2949             :     CHARACTER(LEN=*), INTENT(IN)  :: ncFile   ! file path+name
    2950             :     INTEGER,          INTENT(IN)  :: I        ! # of lons
    2951             :     INTEGER,          INTENT(IN)  :: J        ! # of lats
    2952             :     INTEGER,          INTENT(IN)  :: L        ! # of levs
    2953             :     INTEGER,          INTENT(IN)  :: T        ! # of time slices
    2954             :     INTEGER,          INTENT(IN)  :: N        ! # of vars
    2955             :     REAL*4,           INTENT(IN)  :: lon(:)   ! longitude
    2956             :     REAL*4,           INTENT(IN)  :: lat(:)   ! latitude
    2957             :     REAL*4,           INTENT(IN)  :: lev(:)   ! levels
    2958             :     REAL*4,           INTENT(IN)  :: time(:)  ! time
    2959             :     CHARACTER(LEN=*), INTENT(IN)  :: timeUnit ! time unit
    2960             :     CHARACTER(LEN=*), INTENT(IN)  :: ncVars(:)    ! nc variables
    2961             :     CHARACTER(LEN=*), INTENT(IN)  :: ncUnits(:)   ! var units
    2962             :     CHARACTER(LEN=*), INTENT(IN)  :: ncLongs(:)   ! var long names
    2963             :     CHARACTER(LEN=*), INTENT(IN)  :: ncShorts(:)  ! var short names
    2964             :     REAL*4, TARGET,   INTENT(IN)  :: ncArrays(:,:,:,:,:)  ! var arrays
    2965             : !
    2966             : ! !REMARKS:
    2967             : !  Created with the ncCodeRead script of the NcdfUtilities package,
    2968             : !  with subsequent hand-editing.
    2969             : !
    2970             : ! !REVISION HISTORY:
    2971             : !  See https://github.com/geoschem/hemco for complete history
    2972             : !EOP
    2973             : !------------------------------------------------------------------------------
    2974             : !BOC
    2975             : !
    2976             : ! !LOCAL VARIABLES:
    2977             : !
    2978             :     INTEGER            :: II, fID
    2979             :     REAL*4, POINTER    :: tmpArr(:,:,:,:) => NULL()
    2980             : 
    2981             :     !======================================================================
    2982             :     ! NC_WRITE begins here
    2983             :     !======================================================================
    2984             : 
    2985             :     CALL NC_DEFINE(ncFile=ncFile, nLon=I, nLat=J, nLev=L,            &
    2986             :                    nTime=T,  timeUnit=timeUnit, ncVars=ncVars,       &
    2987             :                    ncUnits=ncUnits,ncLongs=ncLongs,ncShorts=ncShorts,&
    2988           0 :                    fId=fId )
    2989             : 
    2990           0 :     CALL NC_WRITE_DIMS( fID=fId, lon=lon, lat=lat, time=time, lev=lev)
    2991             : 
    2992           0 :     DO II = 1, size(ncVars)
    2993           0 :        tmpArr => ncArrays(:,:,:,:,II)
    2994           0 :        CALL NC_WRITE_DATA_4D ( fId, ncVars(II), tmpArr )
    2995           0 :        tmpArr => NULL()
    2996             :     ENDDO
    2997             : 
    2998           0 :     CALL NcCl( fId )
    2999             : 
    3000           0 :   END SUBROUTINE NC_WRITE_4D
    3001             : !EOC
    3002             : !------------------------------------------------------------------------------
    3003             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    3004             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    3005             : !------------------------------------------------------------------------------
    3006             : !BOP
    3007             : !
    3008             : ! !IROUTINE: Nc_Define
    3009             : !
    3010             : ! !DESCRIPTION: Routine to define the variables and attributes of a netCDF
    3011             : !  file.
    3012             : !\\
    3013             : !\\
    3014             : ! !INTERFACE:
    3015             : !
    3016           0 :   SUBROUTINE NC_DEFINE ( ncFile,  nLon,    nLat,    nLev,    nTime,&
    3017           0 :                          timeUnit, ncVars,  ncUnits, ncLongs, ncShorts, fId )
    3018             : !
    3019             : ! !INPUT PARAMETERS:
    3020             : !
    3021             :     CHARACTER(LEN=*),   INTENT(IN   )  :: ncFile      ! ncdf file path + name
    3022             :     INTEGER,            INTENT(IN   )  :: nLon        ! # of lons
    3023             :     INTEGER,            INTENT(IN   )  :: nLat        ! # of lats
    3024             :     INTEGER, OPTIONAL,  INTENT(IN   )  :: nLev        ! # of levels
    3025             :     INTEGER,            INTENT(IN   )  :: nTime       ! # of time stamps
    3026             :     CHARACTER(LEN=*),   INTENT(IN   )  :: timeUnit    ! time unit
    3027             :     CHARACTER(LEN=*),   INTENT(IN   )  :: ncVars(:)   ! ncdf variables
    3028             :     CHARACTER(LEN=*),   INTENT(IN   )  :: ncUnits(:)  ! var units
    3029             :     CHARACTER(LEN=*),   INTENT(IN   )  :: ncLongs(:)  ! var long names
    3030             :     CHARACTER(LEN=*),   INTENT(IN   )  :: ncShorts(:) ! var short names
    3031             : !
    3032             : ! !OUTPUT PARAMETERS:
    3033             : !
    3034             :     INTEGER,            INTENT(  OUT)  :: fId      ! netCDF file ID
    3035             : !
    3036             : ! !REMARKS:
    3037             : !  Assumes that you have:
    3038             : !  (1) A netCDF library (either v3 or v4) installed on your system
    3039             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    3040             : !                                                                             .
    3041             : !  Although this routine was generated automatically, some further
    3042             : !  hand-editing may be required.
    3043             : !
    3044             : ! !REVISION HISTORY:
    3045             : !  See https://github.com/geoschem/hemco for complete history
    3046             : !EOP
    3047             : !------------------------------------------------------------------------------
    3048             : !BOC
    3049             : !
    3050             : ! !LOCAL VARIABLES:
    3051             : !
    3052             :     ! Declare netCDF variable ID and fill mode
    3053             :     INTEGER            :: vId
    3054             :     INTEGER            :: omode
    3055             : 
    3056             :     ! Variables for netCDF dimensions
    3057             :     INTEGER            :: id_lon
    3058             :     INTEGER            :: id_lat
    3059             :     INTEGER            :: id_time
    3060             :     INTEGER            :: id_lev
    3061             : 
    3062             :     ! Character strings
    3063             :     CHARACTER(LEN=255) :: v_name      ! netCDF variable name
    3064             :     CHARACTER(LEN=255) :: a_name      ! netCDF attribute name
    3065             :     CHARACTER(LEN=255) :: a_val       ! netCDF attribute value
    3066             :     CHARACTER(LEN=3  ) :: idstr       ! tracer ID string
    3067             : 
    3068             :     ! Arrays for netCDF dimension IDs
    3069             :     INTEGER            :: var1d(1)    ! For 1D arrays
    3070             :     INTEGER            :: var3d(3)    ! For 3D arrays
    3071             :     INTEGER            :: var4d(4)    ! For 4D arrays
    3072             : 
    3073             :     ! Other variables
    3074             :     INTEGER            :: I
    3075             : 
    3076             :     !=================================================================
    3077             :     ! %%%%% NETCDF DEFINITION SECTION %%%%%
    3078             :     !=================================================================
    3079             : 
    3080             :     ! Initialize the variable ID counter
    3081           0 :     vId = 0
    3082             : 
    3083             :     ! Open filename
    3084           0 :     CALL NcCr_Wr( fId, TRIM(ncFile) )
    3085             : 
    3086             :     ! Turn filling off
    3087           0 :     CALL NcSetFill( fId, NF90_NOFILL, omode )
    3088             : 
    3089             :     !--------------------------------
    3090             :     ! GLOBAL ATTRIBUTES
    3091             :     !--------------------------------
    3092             : 
    3093             :     ! Define the title global attribute
    3094           0 :     a_name = "Title"
    3095           0 :     a_val  = "Field generated by ncdf_util.F"
    3096           0 :     CALL NcDef_Glob_Attributes( fId, TRIM(a_name), TRIM(a_val) )
    3097             : 
    3098             :     ! Define the history global attribute
    3099           0 :     a_name = "History"
    3100           0 :     a_val  = "Initial version"
    3101           0 :     CALL NcDef_Glob_Attributes( fId, TRIM(a_name), TRIM(a_val) )
    3102             : 
    3103             :     ! Define the conventions global attribute
    3104           0 :     a_name = "Conventions"
    3105           0 :     a_val  = "COARDS"
    3106           0 :     CALL NcDef_Glob_Attributes( fId, TRIM(a_name), TRIM(a_val) )
    3107             : 
    3108             :     ! Define the format global attribute
    3109           0 :     a_name = "Format"
    3110           0 :     a_val  = "netCDF-3"
    3111           0 :     CALL NcDef_Glob_Attributes( fId, TRIM(a_name), TRIM(a_val) )
    3112             : 
    3113             :     !--------------------------------
    3114             :     ! DIMENSIONS
    3115             :     !--------------------------------
    3116             : 
    3117             :     ! Define lon dimension
    3118           0 :     v_name = "lon"
    3119           0 :     CALL NcDef_Dimension( fId, TRIM(v_name), nlon, id_lon )
    3120             : 
    3121             :     ! Define lat dimension
    3122           0 :     v_name = "lat"
    3123           0 :     CALL NcDef_Dimension( fId, TRIM(v_name), nlat, id_lat )
    3124             : 
    3125             :     ! Define lev dimension
    3126           0 :     IF ( PRESENT(nlev) ) THEN
    3127           0 :        v_name = "lev"
    3128           0 :        CALL NcDef_Dimension( fId, TRIM(v_name), nlev, id_lev )
    3129             :     ENDIF
    3130             : 
    3131             :     ! Define time dimension
    3132           0 :     v_name = "time"
    3133           0 :     CALL NcDef_Dimension( fId, TRIM(v_name), ntime, id_time, unlimited=.true. )
    3134             : 
    3135             :     !--------------------------------
    3136             :     ! VARIABLE: lon
    3137             :     !--------------------------------
    3138             : 
    3139             :     ! Define the "lon" variable
    3140           0 :     v_name = "lon"
    3141           0 :     var1d = (/ id_lon /)
    3142           0 :     CALL NcDef_Variable( fId, TRIM(v_name), NF90_FLOAT, 1, var1d, vId )
    3143             : 
    3144             :     ! Define the "lon:long_name" attribute
    3145           0 :     a_name = "long_name"
    3146           0 :     a_val  = "Longitude"
    3147           0 :     CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val) )
    3148             : 
    3149             :     ! Define the "lon:units" attribute
    3150           0 :     a_name = "units"
    3151           0 :     a_val  = "degrees_east"
    3152           0 :     CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val) )
    3153             : 
    3154             :     !--------------------------------
    3155             :     ! VARIABLE: lat
    3156             :     !--------------------------------
    3157             : 
    3158             :     ! Define the "lat" variable
    3159           0 :     v_name = "lat"
    3160           0 :     var1d = (/ id_lat /)
    3161           0 :     CALL NcDef_Variable( fId, TRIM(v_name), NF90_FLOAT, 1, var1d, vId )
    3162             : 
    3163             :     ! Define the "lat:long_name" attribute
    3164           0 :     a_name = "long_name"
    3165           0 :     a_val  = "Latitude"
    3166           0 :     CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val) )
    3167             : 
    3168             :     ! Define the "lat:units" attribute
    3169           0 :     a_name = "units"
    3170           0 :     a_val  = "degrees_north"
    3171           0 :     CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val) )
    3172             : 
    3173             :     !--------------------------------
    3174             :     ! VARIABLE: lev
    3175             :     !--------------------------------
    3176             : 
    3177           0 :     IF ( PRESENT(nlev) ) THEN
    3178             : 
    3179             :        ! Define the "levels" variable
    3180           0 :        v_name = "lev"
    3181           0 :        var1d = (/ id_lev /)
    3182           0 :        CALL NcDef_Variable( fId, TRIM(v_name), NF90_INT, 1, var1d, vId )
    3183             : 
    3184             :        ! Define the "time:long_name" attribute
    3185           0 :        a_name = "long_name"
    3186           0 :        a_val  = "Levels"
    3187           0 :        CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val))
    3188             : 
    3189             :        ! Define the "time:units" attribute
    3190           0 :        a_name = "units"
    3191           0 :        a_val  = "unitless"
    3192           0 :        CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val))
    3193             :     ENDIF
    3194             : 
    3195             :     !--------------------------------
    3196             :     ! VARIABLE: time
    3197             :     !--------------------------------
    3198             : 
    3199             :     ! Define the "time" variable
    3200           0 :     v_name = "time"
    3201           0 :     var1d = (/ id_time /)
    3202           0 :     CALL NcDef_Variable( fId, TRIM(v_name), NF90_INT, 1, var1d, vId )
    3203             : 
    3204             :     ! Define the "time:long_name" attribute
    3205           0 :     a_name = "long_name"
    3206           0 :     a_val  = "Time"
    3207           0 :     CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val) )
    3208             : 
    3209             :     ! Define the "time:units" attribute
    3210           0 :     a_name = "units"
    3211           0 :     a_val  = trim(timeUnit)
    3212           0 :     CALL NcDef_Var_Attributes( fId, vId, TRIM(a_name), TRIM(a_val) )
    3213             : 
    3214             :     !--------------------------------
    3215             :     ! Define variables
    3216             :     !--------------------------------
    3217             : 
    3218           0 :     DO I = 1, SIZE(ncVars)
    3219             : 
    3220           0 :        v_name = TRIM(ncVars(I))
    3221           0 :        IF ( PRESENT(nlev) ) THEN
    3222           0 :           var4d = (/ id_lon, id_lat, id_lev, id_time /)
    3223           0 :           CALL NcDef_Variable(fId,TRIM(v_name),NF90_DOUBLE,4,var4d,vId)
    3224             :        ELSE
    3225           0 :           var3d = (/ id_lon, id_lat, id_time /)
    3226           0 :           CALL NcDef_Variable(fId,TRIM(v_name),NF90_DOUBLE,3,var3d,vId)
    3227             :        ENDIF
    3228             : 
    3229             :        ! Define the long_name attribute
    3230           0 :        a_name = "long_name"
    3231           0 :        a_val  = TRIM(ncLongs(I))
    3232           0 :        CALL NcDef_Var_Attributes(fId, vId, TRIM(a_name), TRIM(a_val) )
    3233             : 
    3234             :        ! Define the short_name attribute
    3235           0 :        a_name = "short_name"
    3236           0 :        a_val  = TRIM(ncShorts(I))
    3237           0 :        CALL NcDef_Var_Attributes(fId, vId, TRIM(a_name), TRIM(a_val) )
    3238             : 
    3239             :        ! Define the units attribute
    3240           0 :        a_name = "units"
    3241           0 :        a_val  = TRIM(ncUnits(I))
    3242           0 :        CALL NcDef_Var_Attributes(fId, vId, TRIM(a_name), TRIM(a_val) )
    3243             :     ENDDO
    3244             : 
    3245             :     !=================================================================
    3246             :     ! %%%%% END OF NETCDF DEFINITION SECTION %%%%%
    3247             :     !=================================================================
    3248           0 :     CALL NcEnd_Def( fId )
    3249             : 
    3250           0 :   END SUBROUTINE NC_DEFINE
    3251             : !EOC
    3252             : !------------------------------------------------------------------------------
    3253             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    3254             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    3255             : !------------------------------------------------------------------------------
    3256             : !BOP
    3257             : !
    3258             : ! !IROUTINE: Nc_Write_Dims
    3259             : !
    3260             : ! !DESCRIPTION: Routine to write dimension arrays to a netCDF file.
    3261             : !\\
    3262             : !\\
    3263             : ! !INTERFACE:
    3264             : !
    3265           0 :   SUBROUTINE NC_WRITE_DIMS( fID, lon, lat, time, lev )
    3266             : !
    3267             : ! !INPUT/OUTPUT PARAMETERS:
    3268             : !
    3269             :     INTEGER,          INTENT(INOUT) :: fId
    3270             : !
    3271             : ! !INPUT PARAMETERS:
    3272             : !
    3273             :     REAL*4,           INTENT(IN   ) :: lon(:)
    3274             :     REAL*4,           INTENT(IN   ) :: lat(:)
    3275             :     REAL*4,           INTENT(IN   ) :: time(:)
    3276             :     REAL*4, OPTIONAL, INTENT(IN   ) :: lev(:)
    3277             : !
    3278             : ! !REMARKS:
    3279             : !  Assumes that you have:
    3280             : !  (1) A netCDF library (either v3 or v4) installed on your system
    3281             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    3282             : !                                                                             .
    3283             : !  Although this routine was generated automatically, some further
    3284             : !  hand-editing may be required.
    3285             : !
    3286             : ! !REVISION HISTORY:
    3287             : !  See https://github.com/geoschem/hemco for complete history
    3288             : !EOP
    3289             : !------------------------------------------------------------------------------
    3290             : !BOC
    3291             : !
    3292             : ! !LOCAL VARIABLES:
    3293             : !
    3294             :     ! Character strings
    3295             :     CHARACTER(LEN=255) :: v_name             ! netCDF variable name
    3296             : 
    3297             :     ! Arrays for netCDF start and count values
    3298             :     INTEGER            :: st1d(1), ct1d(1)   ! For 1D arrays
    3299             :     INTEGER            :: v_size
    3300             : 
    3301             :     !=================================================================
    3302             :     ! Define lon/lat
    3303             :     !=================================================================
    3304             : 
    3305             :     ! Write lon to netCDF file
    3306           0 :     v_name = "lon"
    3307           0 :     v_size = size( lon, 1 )
    3308           0 :     st1d   = (/ 1      /)
    3309           0 :     ct1d   = (/ v_size /)
    3310           0 :     CALL NcWr( lon, fId, TRIM(v_name), st1d, ct1d )
    3311             : 
    3312             :     ! Write lat to netCDF file
    3313           0 :     v_name = "lat"
    3314           0 :     v_size = size( lat, 1 )
    3315           0 :     st1d   = (/ 1      /)
    3316           0 :     ct1d   = (/ v_size /)
    3317           0 :     CALL NcWr( lat, fId, TRIM(v_name), st1d, ct1d )
    3318             : 
    3319             :     ! Write lev to netCDF file
    3320           0 :     IF ( PRESENT(lev) ) THEN
    3321           0 :        v_name = "lev"
    3322           0 :        v_size = size( lev, 1 )
    3323           0 :        st1d   = (/ 1      /)
    3324           0 :        ct1d   = (/ v_size /)
    3325           0 :        CALL NcWr( lev, fId, TRIM(v_name), st1d, ct1d )
    3326             :     ENDIF
    3327             : 
    3328             :     ! Write passed time integer to netCDF file
    3329           0 :     v_name = "time"
    3330           0 :     v_size = size( time, 1 )
    3331           0 :     st1d   = (/ 1      /)
    3332           0 :     ct1d   = (/ v_size /)
    3333           0 :     CALL NcWr( time, fId, TRIM(v_name), st1d, ct1d )
    3334             : 
    3335           0 :   END SUBROUTINE NC_WRITE_DIMS
    3336             : !EOC
    3337             : !------------------------------------------------------------------------------
    3338             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    3339             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    3340             : !------------------------------------------------------------------------------
    3341             : !BOP
    3342             : !
    3343             : ! !IROUTINE: Nc_Nrite_Data_3d
    3344             : !
    3345             : ! !DESCRIPTION: Routine to write a 3-D array to a netCDF file.
    3346             : !\\
    3347             : !\\
    3348             : ! !INTERFACE:
    3349             : !
    3350           0 :   SUBROUTINE NC_WRITE_DATA_3D ( fID, ncVar, Array )
    3351             : !
    3352             : ! !INPUT/OUTPUT PARAMETERS:
    3353             : !
    3354             :     INTEGER,          INTENT(INOUT) :: fId
    3355             : !
    3356             : ! !INPUT PARAMETERS:
    3357             : !
    3358             :     CHARACTER(LEN=*), INTENT(IN   ) :: ncVar
    3359             :     REAL*4,           POINTER       :: Array(:,:,:)
    3360             : !
    3361             : ! !REMARKS:
    3362             : !  Assumes that you have:
    3363             : !  (1) A netCDF library (either v3 or v4) installed on your system
    3364             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    3365             : !                                                                             .
    3366             : !  Although this routine was generated automatically, some further
    3367             : !  hand-editing may be required.
    3368             : !
    3369             : ! !REVISION HISTORY:
    3370             : !  See https://github.com/geoschem/hemco for complete history
    3371             : !EOP
    3372             : !------------------------------------------------------------------------------
    3373             : !BOC
    3374             : !
    3375             : ! !LOCAL VARIABLES:
    3376             : !
    3377             :     ! Arrays for netCDF start and count values
    3378             :     INTEGER            :: st3d(3), ct3d(3)   ! For 3D arrays
    3379             : 
    3380             :     !=================================================================
    3381             :     ! Write data to netCDF file
    3382             :     !=================================================================
    3383             : 
    3384           0 :     st3d = (/ 1, 1, 1 /)
    3385           0 :     ct3d = (/ size(array,1), size(array,2), size(array,3) /)
    3386           0 :     CALL NcWr( ARRAY, fId, TRIM(ncVar), st3d, ct3d )
    3387             : 
    3388           0 :   END SUBROUTINE NC_WRITE_DATA_3D
    3389             : !EOC
    3390             : !------------------------------------------------------------------------------
    3391             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    3392             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    3393             : !------------------------------------------------------------------------------
    3394             : !BOP
    3395             : !
    3396             : ! !IROUTINE: Nc_Write_Data_4d
    3397             : !
    3398             : ! !DESCRIPTION: Routine to write a 4-D array to a netCDF file.
    3399             : !\\
    3400             : !\\
    3401             : ! !INTERFACE:
    3402             : !
    3403           0 :   SUBROUTINE NC_WRITE_DATA_4D ( fID, ncVar, Array )
    3404             : !
    3405             : ! !INPUT/OUTPUT PARAMETERS:
    3406             : !
    3407             :     INTEGER,          INTENT(INOUT) :: fId
    3408             : !
    3409             : ! !INPUT PARAMETERS:
    3410             : !
    3411             :     CHARACTER(LEN=*), INTENT(IN   ) :: ncVar
    3412             :     REAL*4,           POINTER       :: Array(:,:,:,:)
    3413             : !
    3414             : ! !REMARKS:
    3415             : !  Assumes that you have:
    3416             : !  (1) A netCDF library (either v3 or v4) installed on your system
    3417             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    3418             : !                                                                             .
    3419             : !  Although this routine was generated automatically, some further
    3420             : !  hand-editing may be required.
    3421             : !
    3422             : ! !REVISION HISTORY:
    3423             : !  See https://github.com/geoschem/hemco for complete history
    3424             : !EOP
    3425             : !------------------------------------------------------------------------------
    3426             : !BOC
    3427             : !
    3428             : ! !LOCAL VARIABLES:
    3429             : !
    3430             :     ! Arrays for netCDF start and count values
    3431             :     INTEGER            :: st4d(4), ct4d(4)   ! For 4D arrays
    3432             : 
    3433             :     !=================================================================
    3434             :     ! Write data to netCDF file
    3435             :     !=================================================================
    3436             : 
    3437           0 :     st4d   = (/ 1, 1, 1, 1 /)
    3438             :     ct4d   = (/ size(array,1), size(array,2), &
    3439           0 :                   size(array,3), size(array,4)   /)
    3440           0 :     CALL NcWr( ARRAY, fId, TRIM(ncVar), st4d, ct4d )
    3441             : 
    3442           0 :   END SUBROUTINE NC_WRITE_DATA_4D
    3443             : !EOC
    3444             : !------------------------------------------------------------------------------
    3445             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    3446             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    3447             : !------------------------------------------------------------------------------
    3448             : !BOP
    3449             : !
    3450             : ! !IROUTINE: Nc_Create
    3451             : !
    3452             : ! !DESCRIPTION: Creates a new netCDF file and defines several global
    3453             : !  attributes.
    3454             : !\\
    3455             : !\\
    3456             : ! !INTERFACE:
    3457             : !
    3458           0 :   SUBROUTINE Nc_Create( NcFile,      Title,          nLon,                   &
    3459             :                         nLat,        nLev,           nTime,                  &
    3460             :                         fId,         lonID,          latId,                  &
    3461             :                         levId,       timeId,         VarCt,                  &
    3462             :                         Create_NC4,  KeepDefMode,    NcFormat,               &
    3463             :                         Conventions, History,        ProdDateTime,           &
    3464             :                         Reference,   Contact,        nIlev,                  &
    3465             :                         iLevId,      StartTimeStamp, EndTimeStamp           )
    3466             : !
    3467             : ! !INPUT PARAMETERS:
    3468             : !
    3469             :     ! Required arguments
    3470             :     CHARACTER(LEN=*), INTENT(IN   )  :: ncFile         ! ncdf file path + name
    3471             :     CHARACTER(LEN=*), INTENT(IN   )  :: title          ! ncdf file title
    3472             :     INTEGER,          INTENT(IN   )  :: nLon           ! # of lons
    3473             :     INTEGER,          INTENT(IN   )  :: nLat           ! # of lats
    3474             :     INTEGER,          INTENT(IN   )  :: nLev           ! # of level midpoints
    3475             :     INTEGER,          INTENT(IN   )  :: nTime          ! # of times
    3476             :     INTEGER,          OPTIONAL       :: nILev          ! # of level interfaces
    3477             : 
    3478             :     ! Optional arguments (mostly global attributes)
    3479             :     LOGICAL,          OPTIONAL       :: Create_Nc4     ! Save as netCDF-4
    3480             :     LOGICAL,          OPTIONAL       :: KeepDefMode    ! If = T, then don't
    3481             :                                                        !  exit define mode
    3482             :     CHARACTER(LEN=*), OPTIONAL       :: NcFormat       ! e.g. netCDF-4
    3483             :     CHARACTER(LEN=*), OPTIONAL       :: Conventions    ! e.g. COARDS, CF, etc.
    3484             :     CHARACTER(LEN=*), OPTIONAL       :: History        ! History glob attribute
    3485             :     CHARACTER(LEN=*), OPTIONAL       :: ProdDateTime   ! Time/date of production
    3486             :     CHARACTER(LEN=*), OPTIONAL       :: Reference      ! Reference string
    3487             :     CHARACTER(LEN=*), OPTIONAL       :: Contact        ! People to contact
    3488             :     CHARACTER(LEN=*), OPTIONAL       :: StartTimeStamp ! Timestamps at start
    3489             :     CHARACTER(LEN=*), OPTIONAL       :: EndTimeStamp   !  and end of simulation
    3490             : !
    3491             : ! !OUTPUT PARAMETERS:
    3492             : !
    3493             :     INTEGER,          INTENT(  OUT)  :: fId            ! file id
    3494             :     INTEGER,          INTENT(  OUT)  :: lonId          ! lon  dimension id
    3495             :     INTEGER,          INTENT(  OUT)  :: latId          ! lat  dimension id
    3496             :     INTEGER,          INTENT(  OUT)  :: levId          ! lev  dimension id
    3497             :     INTEGER,          INTENT(  OUT)  :: timeId         ! time dimension id
    3498             :     INTEGER,          INTENT(  OUT)  :: VarCt          ! variable counter
    3499             :     INTEGER,          OPTIONAL       :: ilevId         ! ilev dimension id
    3500             : !
    3501             : ! !REMARKS:
    3502             : !  Assumes that you have:
    3503             : !  (1) A netCDF library (either v3 or v4) installed on your system
    3504             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    3505             : !                                                                             .
    3506             : !  Although this routine was generated automatically, some further
    3507             : !  hand-editing may be required.
    3508             : !
    3509             : ! !REVISION HISTORY:
    3510             : !  See https://github.com/geoschem/hemco for complete history
    3511             : !EOP
    3512             : !------------------------------------------------------------------------------
    3513             : !BOC
    3514             : !
    3515             : ! !LOCAL VARIABLES:
    3516             : !
    3517             :     ! Scalars
    3518             :     INTEGER            :: omode
    3519             :     LOGICAL            :: Save_As_Nc4
    3520             :     LOGICAL            :: QuitDefMode
    3521             : 
    3522             :     ! Strings
    3523             :     CHARACTER(LEN=255) :: ThisHistory
    3524             :     CHARACTER(LEN=255) :: ThisNcFormat
    3525             :     CHARACTER(LEN=255) :: ThisConv
    3526             :     CHARACTER(LEN=255) :: ThisPdt
    3527             :     CHARACTER(LEN=255) :: ThisReference
    3528             :     CHARACTER(LEN=255) :: ThisContact
    3529             :     CHARACTER(LEN=255) :: ThisStartTimeStamp
    3530             :     CHARACTER(LEN=255) :: ThisEndTimeStamp
    3531             : 
    3532             :     !=======================================================================
    3533             :     ! Initialize
    3534             :     !=======================================================================
    3535             : 
    3536             :     ! Create file as NetCDF4?
    3537           0 :     IF ( PRESENT( Create_Nc4 ) ) THEN
    3538           0 :        Save_As_Nc4 = Create_Nc4
    3539             :     ELSE
    3540           0 :        Save_As_Nc4 = .FALSE.
    3541             :     ENDIF
    3542             : 
    3543             :     ! Should we exit netCDF define mode before leaving this routine?
    3544           0 :     IF ( PRESENT( KeepDefMode ) ) THEN
    3545           0 :        QuitDefMode = ( .not. KeepDefMode )
    3546             :     ELSE
    3547             :        QuitDefMode = .TRUE.
    3548             :     ENDIF
    3549             : 
    3550             :     ! History global attribute
    3551           0 :     IF ( PRESENT( History ) ) THEN
    3552           0 :        ThisHistory = TRIM( History )
    3553             :     ELSE
    3554           0 :        ThisHistory = 'Created by routine NC_CREATE (in ncdf_mod.F90)'
    3555             :     ENDIF
    3556             : 
    3557             :     ! NetCDF format global attribute
    3558           0 :     IF ( PRESENT( NcFormat ) ) Then
    3559           0 :        ThisNcFormat = NcFormat
    3560             :     ELSE
    3561           0 :        IF ( Save_As_Nc4 ) THEN
    3562           0 :           ThisNcFormat = 'NetCDF-4'
    3563             :        ELSE
    3564           0 :           ThisNcFormat = 'NetCDF-3'
    3565             :        ENDIF
    3566             :     ENDIF
    3567             : 
    3568             :     ! Conventions global attribute (assume COARDS)
    3569           0 :     IF ( PRESENT( Conventions ) ) THEN
    3570           0 :        ThisConv = TRIM( Conventions )
    3571             :     ELSE
    3572           0 :        ThisConv = 'COARDS'
    3573             :     ENDIF
    3574             : 
    3575             :     ! Conventions global attribute (assume COARDS)
    3576           0 :     IF ( PRESENT( ProdDateTime ) ) THEN
    3577           0 :        ThisPdt= TRIM( ProdDateTime )
    3578             :     ENDIF
    3579             : 
    3580             :     ! Conventions global attribute (assume COARDS)
    3581           0 :     IF ( PRESENT( Reference ) ) THEN
    3582           0 :        ThisReference = TRIM( Reference )
    3583             :     ELSE
    3584           0 :        ThisReference = ''
    3585             :     ENDIF
    3586             : 
    3587             :     ! Contact
    3588           0 :     IF ( PRESENT( Contact ) ) THEN
    3589           0 :        ThisContact = TRIM( Contact )
    3590             :     ELSE
    3591           0 :        ThisContact = ''
    3592             :     ENDIF
    3593             : 
    3594             :     ! Starting date and time of the simulation
    3595           0 :     IF ( PRESENT( StartTimeStamp ) ) THEN
    3596           0 :        ThisStartTimeStamp = TRIM( StartTimeStamp )
    3597             :     ELSE
    3598           0 :        ThisStartTimeStamp = ''
    3599             :     ENDIF
    3600             : 
    3601             :     ! Ending date and time of the simulation
    3602           0 :     IF ( PRESENT( EndTimeStamp ) ) THEN
    3603           0 :        ThisEndTimeStamp = TRIM( EndTimeStamp )
    3604             :     ELSE
    3605           0 :        ThisEndTimeStamp = ''
    3606             :     ENDIF
    3607             : 
    3608             :     !=======================================================================
    3609             :     ! Open the file
    3610             :     !=======================================================================
    3611             : 
    3612             :     ! Open filename.  Save file in netCDF-4 format if requested by user.
    3613           0 :     CALL NcCr_Wr( fId, TRIM( ncFile ), Save_As_Nc4 )
    3614             : 
    3615             :     ! Turn filling off
    3616           0 :     CALL NcSetFill( fId, NF90_NOFILL, omode )
    3617             : 
    3618             :     !=======================================================================
    3619             :     ! Set global attributes
    3620             :     !=======================================================================
    3621             : 
    3622             :     ! These attributes are required for COARDS or CF conventions
    3623           0 :     CALL NcDef_Glob_Attributes(  fId, 'title',        TRIM( Title         ) )
    3624           0 :     CALL NcDef_Glob_Attributes(  fId, 'history',      TRIM( ThisHistory   ) )
    3625           0 :     CALL NcDef_Glob_Attributes(  fId, 'format',       TRIM( ThisNcFormat  ) )
    3626           0 :     CALL NcDef_Glob_Attributes(  fId, 'conventions',  TRIM( ThisConv      ) )
    3627             : 
    3628             :     ! These attributes are optional
    3629           0 :     IF ( PRESENT( ProdDateTime ) ) THEN
    3630           0 :      CALL NcDef_Glob_Attributes( fId, 'ProdDateTime', TRIM( ThisPdt       ) )
    3631             :     ENDIF
    3632             : 
    3633           0 :     IF ( PRESENT( Reference ) ) THEN
    3634           0 :      CALL NcDef_Glob_Attributes( fId, 'reference',    TRIM( ThisReference ) )
    3635             :     ENDIF
    3636             : 
    3637           0 :     IF ( PRESENT( Contact ) ) THEN
    3638           0 :      CALL NcDef_Glob_Attributes( fId, 'contact',      TRIM( ThisContact   ) )
    3639             :     ENDIF
    3640             : 
    3641           0 :     IF ( PRESENT( StartTimeStamp ) ) THEN
    3642             :      CALL NcDef_Glob_Attributes( fId, 'simulation_start_date_and_time',      &
    3643           0 :                                        TRIM( ThisStartTimeStamp   )         )
    3644             :     ENDIF
    3645             : 
    3646           0 :     IF ( PRESENT( EndTimeStamp ) ) THEN
    3647             :      CALL NcDef_Glob_Attributes( fId, 'simulation_end_date_and_time',        &
    3648           0 :                                        TRIM( ThisEndTimeStamp )             )
    3649             :     ENDIF
    3650             : 
    3651             :     !=======================================================================
    3652             :     ! Set dimensions
    3653             :     !=======================================================================
    3654             : 
    3655             :     ! Time
    3656           0 :     CALL NcDef_Dimension( fId, 'time', nTime, TimeId, unlimited=.true. )
    3657             : 
    3658             :     ! Level midpoints
    3659           0 :     IF ( nLev > 0 ) THEN
    3660           0 :        CALL NcDef_Dimension( fId, 'lev',  nLev,  levId  )
    3661             :     ELSE
    3662           0 :        levId = -1
    3663             :     ENDIF
    3664             : 
    3665             :     ! Optional ILev dimension: level interfaces
    3666           0 :     IF ( PRESENT( nIlev ) .and. PRESENT( iLevId ) ) THEN
    3667           0 :        IF ( nILev > 0 ) THEN
    3668           0 :           CALL NcDef_Dimension( fId, 'ilev', nIlev, iLevId )
    3669             :        ELSE
    3670           0 :           iLevId = -1
    3671             :        ENDIF
    3672             :     ENDIF
    3673             : 
    3674             :     ! Lat and lon
    3675           0 :     CALL NcDef_Dimension( fId, 'lat',  nLat,  latId  )
    3676           0 :     CALL NcDef_Dimension( fId, 'lon',  nLon,  lonId  )
    3677             : 
    3678             :     ! Close definition section
    3679           0 :     IF ( QuitDefMode ) THEN
    3680           0 :        CALL NcEnd_Def( fId )
    3681             :     ENDIF
    3682             : 
    3683             :     ! Initialize variable counter
    3684           0 :     VarCt = -1
    3685             : 
    3686           0 :   END SUBROUTINE Nc_Create
    3687             : !EOC
    3688             : !------------------------------------------------------------------------------
    3689             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    3690             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    3691             : !------------------------------------------------------------------------------
    3692             : !BOP
    3693             : !
    3694             : ! !IROUTINE: Nc_Var_Def
    3695             : !
    3696             : ! !DESCRIPTION: Defines a new netCDF variable along with its attributes.
    3697             : !\\
    3698             : !\\
    3699             : ! !INTERFACE:
    3700             : !
    3701           0 :   SUBROUTINE NC_Var_Def( fId,       lonId,        latId,        levId,       &
    3702             :                          TimeId,    VarName,      VarLongName,  VarUnit,     &
    3703             :                          DataType,  VarCt,        DefMode,      Compress,    &
    3704             :                          AddOffset, MissingValue, ScaleFactor,  Calendar,    &
    3705             :                          Axis,      StandardName, FormulaTerms, AvgMethod,   &
    3706             :                          Positive,  iLevId,       nUpdates                  )
    3707             : !
    3708             : ! !INPUT PARAMETERS:
    3709             : !
    3710             :     ! Required inputs
    3711             :     INTEGER,          INTENT(IN   ) :: fId          ! file ID
    3712             :     INTEGER,          INTENT(IN   ) :: lonId        ! ID of lon      (X) dim
    3713             :     INTEGER,          INTENT(IN   ) :: latId        ! ID of lat      (Y) dim
    3714             :     INTEGER,          INTENT(IN   ) :: levId        ! ID of lev ctr  (Z) dim
    3715             :     INTEGER,          OPTIONAL      :: iLevId       ! ID of lev edge (I) dim
    3716             :     INTEGER,          INTENT(IN   ) :: TimeId       ! ID of time     (T) dim
    3717             :     CHARACTER(LEN=*), INTENT(IN   ) :: VarName      ! Variable name
    3718             :     CHARACTER(LEN=*), INTENT(IN   ) :: VarLongName  ! Long name description
    3719             :     CHARACTER(LEN=*), INTENT(IN   ) :: VarUnit      ! Units
    3720             :     INTEGER,          INTENT(IN   ) :: DataType     ! 1=Int, 4=float, 8=double
    3721             : 
    3722             :     ! Optional inputs
    3723             :     LOGICAL,          OPTIONAL      :: DefMode      ! Toggles define mode
    3724             :     LOGICAL,          OPTIONAL      :: Compress     ! Toggles compression
    3725             :     REAL*4,           OPTIONAL      :: AddOffset    ! Add offset attribute
    3726             :     REAL*4,           OPTIONAL      :: MissingValue ! Missing value attribute
    3727             :     REAL*4,           OPTIONAL      :: ScaleFactor  ! Scale factor attribute
    3728             :     CHARACTER(LEN=*), OPTIONAL      :: Calendar     ! Calendar for time var
    3729             :     CHARACTER(LEN=*), OPTIONAL      :: Axis         ! Axis for index vars
    3730             :     CHARACTER(LEN=*), OPTIONAL      :: StandardName ! Standard name attribute
    3731             :     CHARACTER(LEN=*), OPTIONAL      :: FormulaTerms ! Formula for vert coords
    3732             :     CHARACTER(LEN=*), OPTIONAL      :: AvgMethod    ! Averaging method
    3733             :     CHARACTER(LEN=*), OPTIONAL      :: Positive     ! Positive dir (up or down)
    3734             :     REAL*4,           OPTIONAL      :: nUpdates     ! # of updates (for time-
    3735             :                                                     !  averaged fields only)
    3736             : !
    3737             : ! !INPUT/OUTPUT PARAMETERS:
    3738             : !
    3739             :     INTEGER,          INTENT(INOUT) :: VarCt        ! variable counter
    3740             : !
    3741             : ! !REMARKS:
    3742             : !  Assumes that you have:
    3743             : !  (1) A netCDF library (either v3 or v4) installed on your system
    3744             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    3745             : !
    3746             : ! !REVISION HISTORY:
    3747             : !  See https://github.com/geoschem/hemco for complete history
    3748             : !EOP
    3749             : !------------------------------------------------------------------------------
    3750             : !BOC
    3751             : !
    3752             : ! !LOCAL VARIABLES:
    3753             : !
    3754             :     ! Arrays
    3755           0 :     INTEGER, ALLOCATABLE :: VarDims(:)
    3756             : 
    3757             :     ! Scalars
    3758             :     INTEGER              :: nDim,     Pos
    3759             :     INTEGER              :: NF90_TYPE,  tmpIlevId
    3760             :     LOGICAL              :: isDefMode
    3761             : 
    3762             :     ! Strings
    3763             :     CHARACTER(LEN=80)    :: Att
    3764             : 
    3765             :     !=======================================================================
    3766             :     ! Initialize
    3767             :     !=======================================================================
    3768             : 
    3769             :     ! Assume file is not in define mode unless explicitly told otherwise
    3770           0 :     IF ( PRESENT( DefMode ) ) THEN
    3771           0 :        isDefMode = DefMode
    3772             :     ELSE
    3773             :        isDefMode = .FALSE.
    3774             :     ENDIF
    3775             : 
    3776             :     ! Test if iLevId (dimension for level interfaces) is present
    3777           0 :     IF ( PRESENT( iLevId ) ) THEN
    3778           0 :        tmpIlevId = iLevId
    3779             :     ELSE
    3780             :        tmpIlevId = -1
    3781             :     ENDIF
    3782             : 
    3783             :     !=======================================================================
    3784             :     ! DEFINE VARIABLE
    3785             :     !=======================================================================
    3786             : 
    3787             :     ! Reopen definition section, if necessary
    3788           0 :     IF ( .not. isDefMode ) CALL NcBegin_Def( fId )
    3789             : 
    3790           0 :     VarCt = VarCt + 1
    3791             : 
    3792             :     ! number of dimensions
    3793           0 :     nDim = 0
    3794           0 :     IF ( lonId     >= 0 ) nDim = nDim + 1
    3795           0 :     IF ( latId     >= 0 ) nDim = nDim + 1
    3796           0 :     IF ( levId     >= 0 ) nDim = nDim + 1
    3797           0 :     IF ( tmpIlevId >= 0 ) nDim = nDim + 1
    3798           0 :     if ( timeId    >= 0 ) nDim = nDim + 1
    3799             : 
    3800             :     ! write dimensions
    3801           0 :     ALLOCATE( VarDims(nDim) )
    3802           0 :     Pos = 1
    3803           0 :     IF ( lonId >= 0 ) THEN
    3804           0 :        VarDims(Pos) = lonId
    3805           0 :        Pos          = Pos + 1
    3806             :     ENDIF
    3807           0 :     IF ( latId >= 0 ) THEN
    3808           0 :        VarDims(Pos) = latId
    3809           0 :        Pos          = Pos + 1
    3810             :     ENDIF
    3811           0 :     IF ( levId >= 0 ) THEN
    3812           0 :        VarDims(Pos) = levId
    3813           0 :        Pos          = Pos + 1
    3814             :     ENDIF
    3815           0 :     IF ( tmpIlevId >= 0 ) THEN
    3816           0 :        VarDims(Pos) = tmpIlevId
    3817           0 :        Pos          = Pos + 1
    3818             :     ENDIF
    3819           0 :     IF ( timeId >= 0 ) THEN
    3820           0 :        VarDims(Pos) = timeId
    3821           0 :        Pos          = Pos + 1
    3822             :     ENDIF
    3823             : 
    3824             :     ! Set data type
    3825           0 :     IF ( DataType == 1 ) THEN
    3826           0 :        NF90_TYPE = NF90_INT
    3827           0 :     ELSEIF ( DataType == 4 ) THEN
    3828           0 :        NF90_TYPE = NF90_FLOAT
    3829           0 :     ELSEIF ( DataType == 8 ) THEN
    3830           0 :        NF90_TYPE = NF90_DOUBLE
    3831             :     ELSE
    3832           0 :        NF90_TYPE = NF90_FLOAT
    3833             :     ENDIF
    3834             : 
    3835             :     !-----------------------------------------------------------------------
    3836             :     ! Define variable
    3837             :     !-----------------------------------------------------------------------
    3838             :     CALL NcDef_Variable( fId,  TRIM(VarName), NF90_TYPE,                     &
    3839           0 :                          nDim, VarDims,       VarCt,      Compress          )
    3840           0 :     DEALLOCATE( VarDims )
    3841             : 
    3842             :     !-----------------------------------------------------------------------
    3843             :     ! Define variable atttibutes (some are optional)
    3844             :     !-----------------------------------------------------------------------
    3845             : 
    3846             :     ! long_name (reuired)
    3847           0 :     Att = 'long_name'
    3848           0 :     CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), TRIM(VarLongName) )
    3849             : 
    3850             :     ! units (requited)
    3851           0 :     Att = 'units'
    3852           0 :     CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att),  TRIM(VarUnit) )
    3853             : 
    3854             :     ! add_offset (optional)
    3855           0 :     IF ( PRESENT( AddOffset ) ) THEN
    3856           0 :        Att = 'add_offset'
    3857           0 :        CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), AddOffset )
    3858             :     ENDIF
    3859             : 
    3860             :     ! scale_factor (optional)
    3861           0 :     IF ( PRESENT( ScaleFactor ) ) THEN
    3862           0 :        Att = 'scale_factor'
    3863           0 :        CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), ScaleFactor )
    3864             :     ENDIF
    3865             : 
    3866             :     ! missing_value (optional but recommended)
    3867           0 :     IF ( PRESENT( MissingValue ) ) THEN
    3868           0 :        Att = '_FillValue'
    3869           0 :        CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att),  MissingValue )
    3870             :     ENDIF
    3871             : 
    3872             :     ! calendar (only used for time) -- skip if null string
    3873           0 :     IF ( PRESENT( Calendar ) ) THEN
    3874           0 :        IF ( LEN_TRIM( Calendar ) > 0 ) THEN
    3875           0 :           Att = 'calendar'
    3876           0 :           CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), TRIM(Calendar) )
    3877             :        ENDIF
    3878             :     ENDIF
    3879             : 
    3880             :     ! axis (only used for index variables) -- skip if null string
    3881           0 :     IF ( PRESENT( Axis ) ) THEN
    3882           0 :        IF ( LEN_TRIM( Axis ) > 0 ) THEN
    3883           0 :           Att = 'axis'
    3884           0 :           CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), TRIM(Axis) )
    3885             :        ENDIF
    3886             :     ENDIF
    3887             : 
    3888             :     ! averaging_method (optional) -- skip if null string
    3889           0 :     IF ( PRESENT( AvgMethod ) ) THEN
    3890           0 :        IF ( LEN_TRIM( AvgMethod ) > 0 ) THEN
    3891           0 :           Att = 'averaging_method'
    3892           0 :           CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), TRIM(AvgMethod) )
    3893             :        ENDIF
    3894             :     ENDIF
    3895             : 
    3896             :     ! averaging_method (optional) -- skip if null string
    3897           0 :     IF ( PRESENT( Positive ) ) THEN
    3898           0 :        IF ( LEN_TRIM( Positive ) > 0 ) THEN
    3899           0 :           Att = 'positive'
    3900           0 :           CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), TRIM(Positive) )
    3901             :        ENDIF
    3902             :     ENDIF
    3903             : 
    3904             :     ! Standard name (optional) -- skip if null string
    3905           0 :     IF ( PRESENT( StandardName ) ) THEN
    3906           0 :        IF ( LEN_TRIM( StandardName ) > 0 ) THEN
    3907           0 :           Att = 'standard_name'
    3908           0 :           CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), TRIM(StandardName))
    3909             :        ENDIF
    3910             :     ENDIF
    3911             : 
    3912             :     ! Formula terms (optional) -- skip if null string
    3913           0 :     IF ( PRESENT( FormulaTerms ) ) THEN
    3914           0 :        IF ( LEN_TRIM( FormulaTerms ) > 0 ) THEN
    3915           0 :           Att = 'formula_terms'
    3916           0 :           CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), TRIM(FormulaTerms))
    3917             :        ENDIF
    3918             :     ENDIF
    3919             : 
    3920             :     ! Number of updates
    3921           0 :     IF ( PRESENT( nUpdates ) ) THEN
    3922           0 :        IF ( nUpdates > 0.0 ) THEN
    3923           0 :           Att = 'number_of_updates'
    3924           0 :           CALL NcDef_Var_Attributes( fId, VarCt, TRIM(Att), nUpdates )
    3925             :        ENDIF
    3926             :     ENDIF
    3927             : 
    3928             :     ! Close definition section, if necessary
    3929           0 :     IF ( .not. isDefMode ) CALL NcEnd_Def( fId )
    3930             : 
    3931           0 :   END SUBROUTINE NC_Var_Def
    3932             : !EOC
    3933             : !------------------------------------------------------------------------------
    3934             : !                  GEOS-Chem Global Chemical Transport Model                  !
    3935             : !------------------------------------------------------------------------------
    3936             : !BOP
    3937             : !
    3938             : ! !IROUTINE: Nc_Var_Chunk
    3939             : !
    3940             : ! !DESCRIPTION: Turns on chunking for a netCDF variable.
    3941             : !\\
    3942             : !\\
    3943             : ! !INTERFACE:
    3944             : !
    3945           0 :   SUBROUTINE Nc_Var_Chunk( fId, vId, ChunkSizes, RC )
    3946             : !
    3947             : ! !INPUT PARAMETERS:
    3948             : !
    3949             :     INTEGER, INTENT(IN)  :: fId            ! NetCDF file ID
    3950             :     INTEGER, INTENT(IN)  :: vId            ! NetCDF variable ID
    3951             :     INTEGER, INTENT(IN)  :: ChunkSizes(:)  ! NetCDF chunk sizes for each dim
    3952             : !
    3953             : ! !OUTPUT PARAMETERS:
    3954             : !
    3955             :     INTEGER, INTENT(OUT) :: RC             ! Success or failure?
    3956             : !
    3957             : ! !REMARKS:
    3958             : !  RC will return an error (nonzero) status if chunking cannot be activated.
    3959             : !  Most often, this is because support for netCDF-4 compression is disabled,
    3960             : !  or if the netCDF file is not a netCDF-4 file.  In this case, RC will have
    3961             : !  an error code of -111.
    3962             : !
    3963             : ! !REVISION HISTORY:
    3964             : !  See https://github.com/geoschem/hemco for complete history
    3965             : !EOP
    3966             : !------------------------------------------------------------------------------
    3967             : !BOC
    3968             : !
    3969             : ! !LOCAL VARIABLES:
    3970             : !
    3971             : #if defined( NC_HAS_COMPRESSION )
    3972             : 
    3973             :     ! Turn on chunking for this variable
    3974             :     ! But only if the netCDF library supports it
    3975             :     RC = NF90_Def_Var_Chunking( fId, vId, NF90_CHUNKED, ChunkSizes )
    3976             : 
    3977             : #else
    3978             : 
    3979             :     ! Otherwise return success
    3980           0 :     RC = 0
    3981             : 
    3982             : #endif
    3983             : 
    3984           0 :   END SUBROUTINE Nc_Var_Chunk
    3985             : !EOC
    3986             : !------------------------------------------------------------------------------
    3987             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    3988             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    3989             : !------------------------------------------------------------------------------
    3990             : !BOP
    3991             : !
    3992             : ! !IROUTINE: Nc_Var_Write_R8_0d
    3993             : !
    3994             : ! !DESCRIPTION: Writes data of a 0-D double precision variable.
    3995             : !\\
    3996             : !\\
    3997             : ! !INTERFACE:
    3998             : !
    3999           0 :   SUBROUTINE NC_VAR_WRITE_R8_0D( fId, VarName, Var )
    4000             : !
    4001             : ! !INPUT PARAMETERS:
    4002             : !
    4003             :     INTEGER,          INTENT(IN)  :: fId           ! file ID
    4004             :     CHARACTER(LEN=*), INTENT(IN)  :: VarName       ! variable name
    4005             :     REAL(kind=dp)                 :: Var           ! Variable to be written
    4006             : !
    4007             : ! !REMARKS:
    4008             : !  Assumes that you have:
    4009             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4010             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4011             : !                                                                             .
    4012             : !  Although this routine was generated automatically, some further
    4013             : !  hand-editing may be required.
    4014             : !
    4015             : ! !REVISION HISTORY:
    4016             : !  See https://github.com/geoschem/hemco for complete history
    4017             : !EOP
    4018             : !------------------------------------------------------------------------------
    4019             : !BOC
    4020             : !
    4021             : ! !LOCAL VARIABLES:
    4022             : !
    4023             :     !--------------------------------
    4024             :     ! WRITE DATA
    4025             :     !--------------------------------
    4026             : 
    4027             :     ! Write to netCDF file
    4028           0 :     CALL NcWr( Var, fId, VarName )
    4029             : 
    4030           0 :   END SUBROUTINE NC_VAR_WRITE_R8_0d
    4031             : !EOC
    4032             : !------------------------------------------------------------------------------
    4033             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4034             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4035             : !------------------------------------------------------------------------------
    4036             : !BOP
    4037             : !
    4038             : ! !IROUTINE: Nc_Var_Write_R8_1d
    4039             : !
    4040             : ! !DESCRIPTION: Writes data of a 1-D double precision variable.
    4041             : !\\
    4042             : !\\
    4043             : ! !INTERFACE:
    4044             : !
    4045           0 :   SUBROUTINE NC_VAR_WRITE_R8_1D( fId, VarName, Arr1D )
    4046             : !
    4047             : ! !INPUT PARAMETERS:
    4048             : !
    4049             :     INTEGER,          INTENT(IN)  :: fId           ! file ID
    4050             :     CHARACTER(LEN=*), INTENT(IN)  :: VarName       ! variable name
    4051             :     REAL(kind=dp),    POINTER     :: Arr1D(:)      ! array to be written
    4052             : !
    4053             : ! !REMARKS:
    4054             : !  Assumes that you have:
    4055             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4056             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4057             : !                                                                             .
    4058             : !  Although this routine was generated automatically, some further
    4059             : !  hand-editing may be required.
    4060             : !
    4061             : ! !REVISION HISTORY:
    4062             : !  See https://github.com/geoschem/hemco for complete history
    4063             : !EOP
    4064             : !------------------------------------------------------------------------------
    4065             : !BOC
    4066             : !
    4067             : ! !LOCAL VARIABLES:
    4068             : !
    4069             :     ! Arrays
    4070             :     INTEGER :: St1d(1), Ct1d(1)
    4071             : 
    4072             :     !--------------------------------
    4073             :     ! WRITE DATA
    4074             :     !--------------------------------
    4075             : 
    4076             :     ! Set start & count arrays
    4077           0 :     St1d(1) = 1
    4078           0 :     Ct1d(1) = SIZE( Arr1d, 1 )
    4079             : 
    4080             :     ! Write to netCDF file
    4081           0 :     CALL NcWr( Arr1d, fId, VarName, St1d, Ct1d )
    4082             : 
    4083           0 :   END SUBROUTINE NC_VAR_WRITE_R8_1D
    4084             : !EOC
    4085             : !------------------------------------------------------------------------------
    4086             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4087             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4088             : !------------------------------------------------------------------------------
    4089             : !BOP
    4090             : !
    4091             : ! !IROUTINE: Nc_Var_Write_R8_2d
    4092             : !
    4093             : ! !DESCRIPTION: Writes data of a 2-D double precision variable.
    4094             : !\\
    4095             : !\\
    4096             : ! !INTERFACE:
    4097             : !
    4098           0 :   SUBROUTINE NC_VAR_WRITE_R8_2D( fId, VarName, Arr2D )
    4099             : !
    4100             : ! !INPUT PARAMETERS:
    4101             : !
    4102             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4103             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4104             :     REAL(kind=dp),    POINTER    :: Arr2D(:,:)     ! array to be written
    4105             : !
    4106             : ! !REMARKS:
    4107             : !  Assumes that you have:
    4108             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4109             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4110             : !                                                                             .
    4111             : !  Although this routine was generated automatically, some further
    4112             : !  hand-editing may be required.
    4113             : !
    4114             : ! !REVISION HISTORY:
    4115             : !  See https://github.com/geoschem/hemco for complete history
    4116             : !EOP
    4117             : !------------------------------------------------------------------------------
    4118             : !BOC
    4119             : !
    4120             : ! !LOCAL VARIABLES:
    4121             : !
    4122             :     ! Arrays
    4123             :     INTEGER :: St2d(2), Ct2d(2)
    4124             : 
    4125             :     ! Scalars
    4126             :     INTEGER :: I,       nDim
    4127             : 
    4128             :     !--------------------------------
    4129             :     ! WRITE DATA
    4130             :     !--------------------------------
    4131             : 
    4132             :     ! Set start & count arrays
    4133           0 :     nDim = 2
    4134           0 :     DO I =1, nDim
    4135           0 :        St2d(I) = 1
    4136           0 :        Ct2d(I) = SIZE( Arr2d, I )
    4137             :     ENDDO
    4138             : 
    4139             :     ! Write to netCDF file
    4140           0 :     CALL NcWr( Arr2d, fId, VarName, St2d, Ct2d )
    4141             : 
    4142           0 :   END SUBROUTINE NC_VAR_WRITE_R8_2D
    4143             : !EOC
    4144             : !------------------------------------------------------------------------------
    4145             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4146             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4147             : !------------------------------------------------------------------------------
    4148             : !BOP
    4149             : !
    4150             : ! !IROUTINE: Nc_Var_Write_R8_3D
    4151             : !
    4152             : ! !DESCRIPTION: Writes data of a 3-D double precision variable.
    4153             : !\\
    4154             : !\\
    4155             : ! !INTERFACE:
    4156             : !
    4157           0 :   SUBROUTINE NC_VAR_WRITE_R8_3D( fId, VarName, Arr3D )
    4158             : !
    4159             : ! !INPUT PARAMETERS:
    4160             : !
    4161             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4162             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4163             :     REAL(kind=dp),    POINTER    :: Arr3D(:,:,:)   ! array to be written
    4164             : !
    4165             : ! !REMARKS:
    4166             : !  Assumes that you have:
    4167             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4168             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4169             : !                                                                             .
    4170             : !  Although this routine was generated automatically, some further
    4171             : !  hand-editing may be required.
    4172             : !
    4173             : ! !REVISION HISTORY:
    4174             : !  See https://github.com/geoschem/hemco for complete history
    4175             : !EOP
    4176             : !------------------------------------------------------------------------------
    4177             : !BOC
    4178             : !
    4179             : ! !LOCAL VARIABLES:
    4180             : !
    4181             :     ! Arrays
    4182             :     INTEGER :: St3d(3), Ct3d(3)
    4183             : 
    4184             :     ! Scalars
    4185             :     INTEGER :: I,       nDim
    4186             : 
    4187             :     !--------------------------------
    4188             :     ! WRITE DATA
    4189             :     !--------------------------------
    4190             : 
    4191             :     ! Set start & count arrays
    4192           0 :     nDim = 3
    4193           0 :     DO I = 1, nDim
    4194           0 :        St3d(I) = 1
    4195           0 :        Ct3d(I) = SIZE( Arr3d, I )
    4196             :     ENDDO
    4197             : 
    4198             :     ! Write data to netCDF file
    4199           0 :     CALL NcWr( Arr3d, fId, VarName, St3d, Ct3d )
    4200             : 
    4201           0 :   END SUBROUTINE NC_VAR_WRITE_R8_3D
    4202             : !EOC
    4203             : !------------------------------------------------------------------------------
    4204             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4205             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4206             : !------------------------------------------------------------------------------
    4207             : !BOP
    4208             : !
    4209             : ! !IROUTINE: Nc_Var_Write_r8_4d
    4210             : !
    4211             : ! !DESCRIPTION: Writes data of a 4-D double precision variable.
    4212             : !\\
    4213             : !\\
    4214             : ! !INTERFACE:
    4215             : !
    4216           0 :   SUBROUTINE NC_VAR_WRITE_R8_4D( fId, VarName, Arr4D )
    4217             : !
    4218             : ! !INPUT PARAMETERS:
    4219             : !
    4220             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4221             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4222             :     REAL(kind=dp),    POINTER    :: Arr4D(:,:,:,:) ! array to be written
    4223             : !
    4224             : ! !REMARKS:
    4225             : !  Assumes that you have:
    4226             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4227             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4228             : !                                                                             .
    4229             : !  Although this routine was generated automatically, some further
    4230             : !  hand-editing may be required.
    4231             : !
    4232             : ! !REVISION HISTORY:
    4233             : !  See https://github.com/geoschem/hemco for complete history
    4234             : !EOP
    4235             : !------------------------------------------------------------------------------
    4236             : !BOC
    4237             : !
    4238             : ! !LOCAL VARIABLES:
    4239             : !
    4240             :     ! Arrays
    4241             :     INTEGER :: St4d(4), Ct4d(4)
    4242             : 
    4243             :     ! Scalars
    4244             :     INTEGER :: I,       nDim
    4245             : 
    4246             :     !--------------------------------
    4247             :     ! WRITE DATA
    4248             :     !--------------------------------
    4249             : 
    4250             :     ! Set start & count arrays
    4251           0 :     nDim = 4
    4252           0 :     DO I = 1, nDim
    4253           0 :        St4d(I) = 1
    4254           0 :        Ct4d(I) = SIZE( Arr4d, I )
    4255             :     ENDDO
    4256             : 
    4257             :     ! Write to netCDF file
    4258           0 :     CALL NcWr( Arr4d, fId, VarName, St4d, Ct4d )
    4259             : 
    4260           0 :   END SUBROUTINE NC_VAR_WRITE_R8_4D
    4261             : !EOC
    4262             : !------------------------------------------------------------------------------
    4263             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4264             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4265             : !------------------------------------------------------------------------------
    4266             : !BOP
    4267             : !
    4268             : ! !IROUTINE: Nc_Var_Write_R4_0d
    4269             : !
    4270             : ! !DESCRIPTION: Writes data of a 0-D single-precision variable.
    4271             : !\\
    4272             : !\\
    4273             : ! !INTERFACE:
    4274             : !
    4275           0 :   SUBROUTINE NC_VAR_WRITE_R4_0d( fId, VarName, Var )
    4276             : !
    4277             : ! !INPUT PARAMETERS:
    4278             : !
    4279             :     INTEGER,          INTENT(IN)  :: fId           ! file ID
    4280             :     CHARACTER(LEN=*), INTENT(IN)  :: VarName       ! variable name
    4281             :     REAL(kind=sp)                 :: Var           ! Variable to be written
    4282             : !
    4283             : ! !REMARKS:
    4284             : !  Assumes that you have:
    4285             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4286             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4287             : !                                                                             .
    4288             : !  Although this routine was generated automatically, some further
    4289             : !  hand-editing may be required.
    4290             : !
    4291             : ! !REVISION HISTORY:
    4292             : !  See https://github.com/geoschem/hemco for complete history
    4293             : !EOP
    4294             : !------------------------------------------------------------------------------
    4295             : !BOC
    4296             : !
    4297             : ! !LOCAL VARIABLES:
    4298             : !
    4299             :     !--------------------------------
    4300             :     ! WRITE DATA
    4301             :     !--------------------------------
    4302             : 
    4303             :     ! Write to netCDF file
    4304           0 :     CALL NcWr( Var, fId, VarName )
    4305             : 
    4306           0 :   END SUBROUTINE NC_VAR_WRITE_R4_0D
    4307             : !EOC
    4308             : !------------------------------------------------------------------------------
    4309             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4310             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4311             : !------------------------------------------------------------------------------
    4312             : !BOP
    4313             : !
    4314             : ! !IROUTINE: Nc_Var_Write_r4_1d
    4315             : !
    4316             : ! !DESCRIPTION: Writes data of a single precision variable.
    4317             : !\\
    4318             : !\\
    4319             : ! !INTERFACE:
    4320             : !
    4321           0 :   SUBROUTINE NC_VAR_WRITE_R4_1D( fId, VarName, Arr1D )
    4322             : !
    4323             : ! !INPUT PARAMETERS:
    4324             : !
    4325             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4326             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4327             :     REAL(kind=sp),    POINTER    :: Arr1D(:)       ! array to be written
    4328             : !
    4329             : ! !REMARKS:
    4330             : !  Assumes that you have:
    4331             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4332             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4333             : !                                                                             .
    4334             : !  Although this routine was generated automatically, some further
    4335             : !  hand-editing may be required.
    4336             : !
    4337             : ! !REVISION HISTORY:
    4338             : !  See https://github.com/geoschem/hemco for complete history
    4339             : !EOP
    4340             : !------------------------------------------------------------------------------
    4341             : !BOC
    4342             : !
    4343             : ! !LOCAL VARIABLES:
    4344             : !
    4345             :     ! Arrays
    4346             :     INTEGER :: St1d(1), Ct1d(1)
    4347             : 
    4348             :     !--------------------------------
    4349             :     ! WRITE DATA
    4350             :     !--------------------------------
    4351             : 
    4352             :     ! Set start & count arrays
    4353           0 :     St1d(1) = 1
    4354           0 :     Ct1d(1) = SIZE( Arr1d, 1 )
    4355             : 
    4356             :     ! Write to netCDF file
    4357           0 :     CALL NcWr( Arr1d, fId, VarName, St1d, Ct1d )
    4358             : 
    4359           0 :   END SUBROUTINE NC_VAR_WRITE_R4_1D
    4360             : !EOC
    4361             : !------------------------------------------------------------------------------
    4362             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4363             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4364             : !------------------------------------------------------------------------------
    4365             : !BOP
    4366             : !
    4367             : ! !IROUTINE: Nc_Var_Write_r4_2D
    4368             : !
    4369             : ! !DESCRIPTION: Writes data of a 2-D single precision variable.
    4370             : !\\
    4371             : !\\
    4372             : ! !INTERFACE:
    4373             : !
    4374           0 :   SUBROUTINE NC_VAR_WRITE_R4_2D( fId, VarName, Arr2D )
    4375             : !
    4376             : ! !INPUT PARAMETERS:
    4377             : !
    4378             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4379             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4380             :     REAL(kind=sp),    POINTER    :: Arr2D(:,:)     ! array to be written
    4381             : !
    4382             : ! !REMARKS:
    4383             : !  Assumes that you have:
    4384             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4385             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4386             : !                                                                             .
    4387             : !  Although this routine was generated automatically, some further
    4388             : !  hand-editing may be required.
    4389             : !
    4390             : ! !REVISION HISTORY:
    4391             : !  See https://github.com/geoschem/hemco for complete history
    4392             : !EOP
    4393             : !------------------------------------------------------------------------------
    4394             : !BOC
    4395             : !
    4396             : ! !LOCAL VARIABLES:
    4397             : !
    4398             :     ! Arrays
    4399             :     INTEGER :: St2d(2), Ct2d(2)
    4400             : 
    4401             :     ! Scalars
    4402             :     INTEGER :: I,       nDim
    4403             : 
    4404             :     !--------------------------------
    4405             :     ! WRITE DATA
    4406             :     !--------------------------------
    4407             : 
    4408             :     ! Set start & count arrays
    4409           0 :     nDim = 2
    4410           0 :     DO I = 1, nDim
    4411           0 :        St2d(I) = 1
    4412           0 :        Ct2d(I) = SIZE( Arr2d, I )
    4413             :     ENDDO
    4414             : 
    4415             :     ! Write to netCDF file
    4416           0 :     CALL NcWr( Arr2d, fId, VarName, St2d, Ct2d )
    4417             : 
    4418           0 :   END SUBROUTINE NC_VAR_WRITE_R4_2D
    4419             : !EOC
    4420             : !------------------------------------------------------------------------------
    4421             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4422             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4423             : !------------------------------------------------------------------------------
    4424             : !BOP
    4425             : !
    4426             : ! !IROUTINE: Nc_Var_Write_r4_3d
    4427             : !
    4428             : ! !DESCRIPTION: Writes data of a 3-D single precision variable.
    4429             : !\\
    4430             : !\\
    4431             : ! !INTERFACE:
    4432             : !
    4433           0 :   SUBROUTINE NC_VAR_WRITE_R4_3D( fId, VarName, Arr3D )
    4434             : !
    4435             : ! !INPUT PARAMETERS:
    4436             : !
    4437             :     INTEGER,          INTENT(IN)  :: fId            ! file ID
    4438             :     CHARACTER(LEN=*), INTENT(IN)  :: VarName        ! variable name
    4439             :     REAL(kind=sp),    POINTER     :: Arr3D(:,:,:)   ! array to be written
    4440             : !
    4441             : ! !REMARKS:
    4442             : !  Assumes that you have:
    4443             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4444             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4445             : !                                                                             .
    4446             : !  Although this routine was generated automatically, some further
    4447             : !  hand-editing may be required.
    4448             : !
    4449             : ! !REVISION HISTORY:
    4450             : !  See https://github.com/geoschem/hemco for complete history
    4451             : !EOP
    4452             : !------------------------------------------------------------------------------
    4453             : !BOC
    4454             : !
    4455             : ! !LOCAL VARIABLES:
    4456             : !
    4457             :     ! Arrays
    4458             :     INTEGER :: St3d(3), Ct3d(3)
    4459             : 
    4460             :     ! Scalars
    4461             :     INTEGER :: I, nDim
    4462             : 
    4463             :     !--------------------------------
    4464             :     ! WRITE DATA
    4465             :     !--------------------------------
    4466             : 
    4467             :     ! Set start & count arrays
    4468           0 :     nDim = 3
    4469           0 :     DO I = 1, nDim
    4470           0 :        St3d(I) = 1
    4471           0 :        Ct3d(I) = SIZE( Arr3d, I )
    4472             :     ENDDO
    4473             : 
    4474             :     ! Write to netCDF file
    4475           0 :     CALL NcWr( Arr3d, fId, VarName, St3d, Ct3d )
    4476             : 
    4477           0 :   END SUBROUTINE NC_VAR_WRITE_R4_3D
    4478             : !EOC
    4479             : !------------------------------------------------------------------------------
    4480             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4481             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4482             : !------------------------------------------------------------------------------
    4483             : !BOP
    4484             : !
    4485             : ! !IROUTINE: Nc_Var_Write_r4_4d
    4486             : !
    4487             : ! !DESCRIPTION: Writes data of a 4-D single precision variable.
    4488             : !\\
    4489             : !\\
    4490             : ! !INTERFACE:
    4491             : !
    4492           0 :   SUBROUTINE NC_VAR_WRITE_R4_4D( fId, VarName, Arr4D )
    4493             : !
    4494             : ! !INPUT PARAMETERS:
    4495             : !
    4496             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4497             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4498             :     REAL(kind=sp),    POINTER    :: Arr4D(:,:,:,:) ! array to be written
    4499             : !
    4500             : ! !REMARKS:
    4501             : !  Assumes that you have:
    4502             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4503             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4504             : !                                                                             .
    4505             : !  Although this routine was generated automatically, some further
    4506             : !  hand-editing may be required.
    4507             : !
    4508             : ! !REVISION HISTORY:
    4509             : !  See https://github.com/geoschem/hemco for complete history
    4510             : !EOP
    4511             : !------------------------------------------------------------------------------
    4512             : !BOC
    4513             : !
    4514             : ! !LOCAL VARIABLES:
    4515             : !
    4516             :     ! Arrays
    4517             :     INTEGER :: St4d(4), Ct4d(4)
    4518             : 
    4519             :     ! Scalars
    4520             :     INTEGER :: I,       nDim
    4521             : 
    4522             :     !--------------------------------
    4523             :     ! WRITE DATA
    4524             :     !--------------------------------
    4525             : 
    4526           0 :     nDim = 4
    4527           0 :     DO I = 1, nDim
    4528           0 :        St4d(I) = 1
    4529           0 :        Ct4d(I) = SIZE( Arr4d, I )
    4530             :     ENDDO
    4531             : 
    4532             :     ! Write to netCDF file
    4533           0 :     CALL NcWr( Arr4d, fId, VarName, St4d, Ct4d )
    4534             : 
    4535           0 :   END SUBROUTINE NC_VAR_WRITE_R4_4D
    4536             : !EOC
    4537             : !------------------------------------------------------------------------------
    4538             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4539             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4540             : !------------------------------------------------------------------------------
    4541             : !BOP
    4542             : !
    4543             : ! !IROUTINE: Nc_Var_Write_Int_0d
    4544             : !
    4545             : ! !DESCRIPTION: Writes data of a 0-D integer variable.
    4546             : !\\
    4547             : !\\
    4548             : ! !INTERFACE:
    4549             : !
    4550           0 :   SUBROUTINE NC_VAR_WRITE_INT_0d( fId, VarName, Var )
    4551             : !
    4552             : ! !INPUT PARAMETERS:
    4553             : !
    4554             :     INTEGER,          INTENT(IN)  :: fId           ! file ID
    4555             :     CHARACTER(LEN=*), INTENT(IN)  :: VarName       ! variable name
    4556             :     INTEGER                       :: Var           ! Variable to be written
    4557             : !
    4558             : ! !REMARKS:
    4559             : !  Assumes that you have:
    4560             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4561             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4562             : !                                                                             .
    4563             : !  Although this routine was generated automatically, some further
    4564             : !  hand-editing may be required.
    4565             : !
    4566             : ! !REVISION HISTORY:
    4567             : !  See https://github.com/geoschem/hemco for complete history
    4568             : !EOP
    4569             : !------------------------------------------------------------------------------
    4570             : !BOC
    4571             : !
    4572             : ! !LOCAL VARIABLES:
    4573             : !
    4574             :     !--------------------------------
    4575             :     ! WRITE DATA
    4576             :     !--------------------------------
    4577             : 
    4578             :     ! Write to netCDF file
    4579           0 :     CALL NcWr( Var, fId, VarName )
    4580             : 
    4581           0 :   END SUBROUTINE NC_VAR_WRITE_INT_0D
    4582             : !EOC
    4583             : !------------------------------------------------------------------------------
    4584             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4585             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4586             : !------------------------------------------------------------------------------
    4587             : !BOP
    4588             : !
    4589             : ! !IROUTINE: Nc_Var_Write_int_1d
    4590             : !
    4591             : ! !DESCRIPTION: Writes data of an 1-D integer variable.
    4592             : !\\
    4593             : !\\
    4594             : ! !INTERFACE:
    4595             : !
    4596           0 :   SUBROUTINE NC_VAR_WRITE_INT_1D( fId, VarName, Arr1D )
    4597             : !
    4598             : ! !INPUT PARAMETERS:
    4599             : !
    4600             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4601             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4602             :     INTEGER,          POINTER    :: Arr1D(:)       ! array to be written
    4603             : !
    4604             : ! !REMARKS:
    4605             : !  Assumes that you have:
    4606             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4607             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4608             : !                                                                             .
    4609             : !  Although this routine was generated automatically, some further
    4610             : !  hand-editing may be required.
    4611             : !
    4612             : ! !REVISION HISTORY:
    4613             : !  See https://github.com/geoschem/hemco for complete history
    4614             : !EOP
    4615             : !------------------------------------------------------------------------------
    4616             : !BOC
    4617             : !
    4618             : ! !LOCAL VARIABLES:
    4619             : !
    4620             :     ! Arrays
    4621             :     INTEGER :: St1d(1), Ct1d(1)
    4622             : 
    4623             :     !--------------------------------
    4624             :     ! WRITE DATA
    4625             :     !--------------------------------
    4626             : 
    4627             :     ! Set start & count arrays
    4628           0 :     St1d(1) = 1
    4629           0 :     Ct1d(1) = SIZE( Arr1d, 1 )
    4630             : 
    4631             :     ! Write to netCDF file
    4632           0 :     CALL NcWr( Arr1d, fId, VarName, St1d, Ct1d )
    4633             : 
    4634           0 :   END SUBROUTINE NC_VAR_WRITE_INT_1D
    4635             : !EOC
    4636             : !------------------------------------------------------------------------------
    4637             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4638             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4639             : !------------------------------------------------------------------------------
    4640             : !BOP
    4641             : !
    4642             : ! !IROUTINE: Nc_Var_Write_int_2d
    4643             : !
    4644             : ! !DESCRIPTION: writes data of an 2-D integer variable.
    4645             : !\\
    4646             : !\\
    4647             : ! !INTERFACE:
    4648             : !
    4649           0 :   SUBROUTINE NC_VAR_WRITE_INT_2D( fId, VarName, Arr2D )
    4650             : !
    4651             : ! !INPUT PARAMETERS:
    4652             : !
    4653             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4654             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4655             :     INTEGER,          POINTER    :: Arr2D(:,:)     ! array to be written
    4656             : !
    4657             : ! !REMARKS:
    4658             : !  Assumes that you have:
    4659             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4660             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4661             : !                                                                             .
    4662             : !  Although this routine was generated automatically, some further
    4663             : !  hand-editing may be required.
    4664             : !
    4665             : ! !REVISION HISTORY:
    4666             : !  See https://github.com/geoschem/hemco for complete history
    4667             : !EOP
    4668             : !------------------------------------------------------------------------------
    4669             : !BOC
    4670             : !
    4671             : ! !LOCAL VARIABLES:
    4672             : !
    4673             :     ! Arrays
    4674             :     INTEGER :: St2d(2), Ct2d(2)
    4675             : 
    4676             :     ! Scalars
    4677             :     INTEGER :: I,       nDim
    4678             : 
    4679             :     !--------------------------------
    4680             :     ! WRITE DATA
    4681             :     !--------------------------------
    4682             : 
    4683             :     ! Set start & count arrays
    4684           0 :     nDim = 2
    4685           0 :     DO I = 1, nDim
    4686           0 :        St2d(I) = 1
    4687           0 :        Ct2d(I) = SIZE( Arr2d, I )
    4688             :     ENDDO
    4689             : 
    4690             :     ! Write to netCDF file
    4691           0 :     CALL NcWr( Arr2d, fId, VarName, St2d, Ct2d )
    4692             : 
    4693           0 :   END SUBROUTINE NC_VAR_WRITE_INT_2D
    4694             : !EOC
    4695             : !------------------------------------------------------------------------------
    4696             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4697             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4698             : !------------------------------------------------------------------------------
    4699             : !BOP
    4700             : !
    4701             : ! !IROUTINE: Nc_Var_Write_int_3d
    4702             : !
    4703             : ! !DESCRIPTION: writes data of an 3-D integer variable.
    4704             : !\\
    4705             : !\\
    4706             : ! !INTERFACE:
    4707             : !
    4708           0 :   SUBROUTINE NC_VAR_WRITE_INT_3D( fId, VarName, Arr3D )
    4709             : !
    4710             : ! !INPUT PARAMETERS:
    4711             : !
    4712             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4713             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4714             :     INTEGER,          POINTER    :: Arr3D(:,:,:)   ! array to be written
    4715             : !
    4716             : ! !REMARKS:
    4717             : !  Assumes that you have:
    4718             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4719             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4720             : !                                                                             .
    4721             : !  Although this routine was generated automatically, some further
    4722             : !  hand-editing may be required.
    4723             : !
    4724             : ! !REVISION HISTORY:
    4725             : !  See https://github.com/geoschem/hemco for complete history
    4726             : !EOP
    4727             : !------------------------------------------------------------------------------
    4728             : !BOC
    4729             : !
    4730             : ! !LOCAL VARIABLES:
    4731             : !
    4732             :     ! Arrays
    4733             :     INTEGER :: St3d(3), Ct3d(3)
    4734             : 
    4735             :     ! Scalars
    4736             :     INTEGER :: I,       nDim
    4737             : 
    4738             :     !--------------------------------
    4739             :     ! WRITE DATA
    4740             :     !--------------------------------
    4741             : 
    4742             :     ! Set start & count arrays
    4743           0 :     nDim = 3
    4744           0 :     DO I = 1, nDim
    4745           0 :        St3d(I) = 1
    4746           0 :        Ct3d(I) = SIZE( Arr3d, I )
    4747             :     ENDDO
    4748             : 
    4749             :     ! Write to netCDF file
    4750           0 :     CALL NcWr( Arr3d, fId, trim(VarName), St3d, Ct3d )
    4751             : 
    4752           0 :   END SUBROUTINE NC_VAR_WRITE_INT_3D
    4753             : !EOC
    4754             : !------------------------------------------------------------------------------
    4755             : !       NcdfUtilities: by Harvard Atmospheric Chemistry Modeling Group        !
    4756             : !                      and NASA/GSFC, SIVO, Code 610.3                        !
    4757             : !------------------------------------------------------------------------------
    4758             : !BOP
    4759             : !
    4760             : ! !IROUTINE: Nc_Var_Write_int_4d
    4761             : !
    4762             : ! !DESCRIPTION: writes data of an 4-Dinteger variable.
    4763             : !\\
    4764             : !\\
    4765             : ! !INTERFACE:
    4766             : !
    4767           0 :   SUBROUTINE NC_VAR_WRITE_INT_4D( fId, VarName, Arr4D )
    4768             : !
    4769             : ! !INPUT PARAMETERS:
    4770             : !
    4771             :     INTEGER,          INTENT(IN) :: fId            ! file ID
    4772             :     CHARACTER(LEN=*), INTENT(IN) :: VarName        ! variable name
    4773             :     INTEGER,          POINTER    :: Arr4D(:,:,:,:) ! array to be written
    4774             : !
    4775             : ! !REMARKS:
    4776             : !  Assumes that you have:
    4777             : !  (1) A netCDF library (either v3 or v4) installed on your system
    4778             : !  (2) The NcdfUtilities package (from Bob Yantosca) source code
    4779             : !                                                                             .
    4780             : !  Although this routine was generated automatically, some further
    4781             : !  hand-editing may be required.
    4782             : !
    4783             : ! !REVISION HISTORY:
    4784             : !  See https://github.com/geoschem/hemco for complete history
    4785             : !EOP
    4786             : !------------------------------------------------------------------------------
    4787             : !BOC
    4788             : !
    4789             : ! !LOCAL VARIABLES:
    4790             : !
    4791             :     ! Arrays
    4792             :     INTEGER :: St4d(4), Ct4d(4)
    4793             : 
    4794             :     ! Scalars
    4795             :     INTEGER :: I, nDim
    4796             : 
    4797             :     !--------------------------------
    4798             :     ! WRITE DATA
    4799             :     !--------------------------------
    4800             : 
    4801             :     ! Set start & count arrays
    4802           0 :     nDim = 4
    4803           0 :     DO I = 1, nDim
    4804           0 :        St4d(I) = 1
    4805           0 :        Ct4d(I) = SIZE( Arr4d, I )
    4806             :     ENDDO
    4807             : 
    4808             :     ! Write to netCDF file
    4809           0 :     CALL NcWr( Arr4d, fId, VarName, St4d, Ct4d )
    4810             : 
    4811           0 :   END SUBROUTINE NC_VAR_WRITE_INT_4D
    4812             : !EOC
    4813             : !------------------------------------------------------------------------------
    4814             : !                  GEOS-Chem Global Chemical Transport Model                  !
    4815             : !------------------------------------------------------------------------------
    4816             : !BOP
    4817             : !
    4818             : ! !IROUTINE: Get_Tau0
    4819             : !
    4820             : ! !DESCRIPTION: Function GET\_TAU0\_6A returns the corresponding TAU0 value
    4821             : !  for the first day of a given MONTH of a given YEAR.  This is necessary to
    4822             : !  index monthly mean binary punch files, which are used as input to GEOS-Chem.
    4823             : !\\
    4824             : !\\
    4825             : !  This function takes 3 mandatory arguments (MONTH, DAY, YEAR) and 3
    4826             : !  optional arguments (HOUR, MIN, SEC).  It is intended to replace the current
    4827             : !  2-argument version of GET\_TAU0.  The advantage being that GET\_TAU0\_6A
    4828             : !  can compute a TAU0 for any date and time in the GEOS-Chem epoch, rather
    4829             : !  than just the first day of each month.  Overload this w/ an interface so
    4830             : !  that the user can also choose the version of GET\_TAU0 w/ 2 arguments
    4831             : !  (MONTH, YEAR), which is the prior version.
    4832             : !\\
    4833             : !\\
    4834             : ! !INTERFACE:
    4835             : !
    4836           0 :   FUNCTION GET_TAU0( MONTH, DAY, YEAR, HOUR, MIN, SEC ) RESULT( THIS_TAU0 )
    4837             : !
    4838             : ! !USES:
    4839             : !
    4840             :     USE HCO_JULDAY_MOD, ONLY : JULDAY
    4841             : !
    4842             : ! !INPUT PARAMETERS:
    4843             : !
    4844             :     INTEGER, INTENT(IN)           :: MONTH
    4845             :     INTEGER, INTENT(IN)           :: DAY
    4846             :     INTEGER, INTENT(IN)           :: YEAR
    4847             :     INTEGER, INTENT(IN), OPTIONAL :: HOUR
    4848             :     INTEGER, INTENT(IN), OPTIONAL :: MIN
    4849             :     INTEGER, INTENT(IN), OPTIONAL :: SEC
    4850             : !
    4851             : ! !RETURN VALUE:
    4852             : !
    4853             :     REAL*8                        :: THIS_TAU0   ! TAU0 timestamp
    4854             : !
    4855             : ! !REMARKS:
    4856             : !  TAU0 is hours elapsed since 00:00 GMT on 01 Jan 1985.
    4857             : !
    4858             : ! !REVISION HISTORY:
    4859             : !  See https://github.com/geoschem/hemco for complete history
    4860             : !EOP
    4861             : !------------------------------------------------------------------------------
    4862             : !BOC
    4863             : !
    4864             : ! !LOCAL VARIABLES:
    4865             : !
    4866             :     INTEGER :: TMP_HOUR, TMP_MIN, TMP_SEC
    4867             :     REAL*8  :: DAYS
    4868             : 
    4869             :     !=======================================================================
    4870             :     ! GET_TAU0 begins here!
    4871             :     !=======================================================================
    4872             : 
    4873             :     ! Error checking
    4874           0 :     IF ( MONTH < 1 .or. MONTH > 12 ) THEN
    4875           0 :        WRITE( 6, 100 )
    4876             : 100    FORMAT( 'Invalid MONTH selection!  STOP in GET_TAU0 (ncdf_mod.F90)!' )
    4877           0 :        STOP
    4878             :     ENDIF
    4879             : 
    4880             :     ! Error checking
    4881           0 :     IF ( DAY < 1 .or. DAY > 31 ) THEN
    4882           0 :        WRITE( 6, 110 )
    4883             : 110    FORMAT( 'Invalid DAY selection!  STOP in GET_TAU0 (ncdf_mod.F90)!' )
    4884           0 :        STOP
    4885             :     ENDIF
    4886             : 
    4887             :     ! If HOUR isn't passed, default to 0
    4888           0 :     IF ( PRESENT( HOUR ) ) THEN
    4889           0 :        TMP_HOUR = HOUR
    4890             :     ELSE
    4891             :        TMP_HOUR = 0
    4892             :     ENDIF
    4893             : 
    4894             :     ! If MIN isn't passed, default to 0
    4895           0 :     IF ( PRESENT( MIN ) ) THEN
    4896           0 :        TMP_MIN = MIN
    4897             :     ELSE
    4898             :        TMP_MIN = 0
    4899             :     ENDIF
    4900             : 
    4901             :     ! If SEC isn't passed, default to 0
    4902           0 :     IF ( PRESENT( SEC ) ) THEN
    4903           0 :        TMP_SEC = SEC
    4904             :     ELSE
    4905             :        TMP_SEC = 0
    4906             :     ENDIF
    4907             : 
    4908             :     ! Number of days since midnight on 1/1/1985
    4909           0 :     THIS_TAU0 = JULDAY( YEAR, MONTH, DBLE( DAY ) ) - 2446066.5d0
    4910             : 
    4911             :     ! Multiply by 24 to get hours since 1/1/1985
    4912             :     ! Also add in the hours elapsed since midnight on this date
    4913             :     THIS_TAU0 = ( THIS_TAU0 * 24d0 ) + ( TMP_HOUR         ) + &
    4914           0 :                 ( TMP_MIN   / 60d0 ) + ( TMP_SEC / 3600d0 )
    4915             : 
    4916           0 :   END FUNCTION GET_TAU0
    4917             : END MODULE HCO_NCDF_MOD

Generated by: LCOV version 1.14