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

          Line data    Source code
       1             : !------------------------------------------------------------------------------
       2             : !                   Harmonized Emissions Component (HEMCO)                    !
       3             : !------------------------------------------------------------------------------
       4             : !BOP
       5             : !
       6             : ! !MODULE: hco_calc_mod.F90
       7             : !
       8             : ! !DESCRIPTION: Module HCO\_Calc\_Mod contains routines to calculate
       9             : ! HEMCO core emissions based on the content of the HEMCO EmisList
      10             : ! object. All emissions are in [kg/m2/s].
      11             : !\\
      12             : !\\
      13             : ! Emissions for the current datetime are calculated by multiplying base
      14             : ! emissions fields with the associated scale factors. Different
      15             : ! inventories are merged/overlayed based upon the category and hierarchy
      16             : ! attributes assigned to the individual base fields. Within the same
      17             : ! category, fields of higher hierarchy overwrite lower-hierarchy fields.
      18             : ! Emissions of different categories are always added.
      19             : !\\
      20             : !\\
      21             : ! The assembled emission array is written into the corresponding emission
      22             : ! rates array of the HEMCO state object: HcoState%Spc(HcoID)%Emis, where
      23             : ! HcoID denotes the corresponding species ID. Emis covers dimension lon,
      24             : ! lat, lev on the HEMCO grid, i.e. unlike the emission arrays in EmisList
      25             : ! that only cover the levels defined in the source files, Emis extends
      26             : ! over all vertical model levels.
      27             : !\\
      28             : !\\
      29             : ! Negative emissions are not supported and are ignored. Surface
      30             : ! deposition velocities are stored in HcoState%Spc(HcoID)%Depv and can
      31             : ! be added therein.
      32             : !\\
      33             : !\\
      34             : ! In addition to emissions and surface deposition rates, HEMCO also
      35             : ! supports concentrations (kg/m3). Data is automatically written into
      36             : ! the concentration array HcoState%Spc(HcoID)%Conc if the source data
      37             : ! is marked as being concentration data (i.e. if Dta%IsConc is .TRUE.).
      38             : ! The latter is automatically determined by HEMCO based upon the data
      39             : ! units.
      40             : !\\
      41             : !\\
      42             : ! All emission calculation settings are passed through the HcoState
      43             : ! options object (HcoState%Options). These include:
      44             : !
      45             : ! \begin{itemize}
      46             : !  \item ExtNr: extension number to be considered.
      47             : !  \item SpcMin: lower species ID (HEMCO ID) to be considered.
      48             : !  \item SpcMax: upper species ID (HEMCO ID) to be considered. If set
      49             : !        to -1, all species above or equal to SpcMin are considered.
      50             : !  \item CatMin: lower emission category to be considered.
      51             : !  \item CatMax: upper emission category to be considered. If set to
      52             : !        -1, all categories above or equal to CatMin are considered.
      53             : !  \item FillBuffer: if set to TRUE, the emissions will be written into
      54             : !        buffer array HcoState%Buffer3D instead of HcoState%Spc(ID)%Emis.
      55             : !        If this option is enabled, only one species can be calculated at
      56             : !        a time (by setting SpcMin/SpcMax, CatMin/CatMax and/or ExtNr
      57             : !        accordingly). This option is useful for extensions, e.g. if
      58             : !        additional scalings need to be done on some emission fields
      59             : !        assembled by HEMCO (e.g. PARANOX extension).
      60             : ! \end{itemize}
      61             : !
      62             : ! !INTERFACE:
      63             : !
      64             : MODULE HCO_Calc_Mod
      65             : !
      66             : ! !USES:
      67             : !
      68             :   USE HCO_Diagn_Mod
      69             :   USE HCO_Error_Mod
      70             :   USE HCO_Types_Mod
      71             :   USE HCO_DataCont_Mod, ONLY : Pnt2DataCont
      72             : 
      73             :   IMPLICIT NONE
      74             :   PRIVATE
      75             : !
      76             : ! !PUBLIC MEMBER FUNCTIONS:
      77             : !
      78             :   PUBLIC  :: HCO_CalcEmis
      79             :   PUBLIC  :: HCO_CheckDepv
      80             :   PUBLIC  :: HCO_EvalFld
      81             :   PUBLIC  :: HCO_MaskFld
      82             : #ifdef ADJOINT
      83             :   PUBLIC  :: GET_CURRENT_EMISSIONS_ADJ
      84             : #endif
      85             : !
      86             : ! !PRIVATE MEMBER FUNCTIONS:
      87             : !
      88             :   PRIVATE :: GET_CURRENT_EMISSIONS
      89             :   PRIVATE :: GetMaskVal
      90             :   PRIVATE :: GetDilFact
      91             :   PRIVATE :: GetVertIndx
      92             :   PRIVATE :: GetIdx
      93             : !
      94             : ! !PARAMETER
      95             : !
      96             :   ! Mask threshold. All mask values below this value will be evaluated
      97             :   ! as zero (= outside of mask), and all values including and above this
      98             :   ! value as inside the mask. This is only of relevance if the MaskFractions
      99             :   ! option is false. If MaskFractions is true, the fractional mask values are
     100             :   ! considered, e.g. a grid box can contribute 40% to a mask region, etc.
     101             :   ! The MaskFractions toggle can be set in the settings section of the HEMCO
     102             :   ! configuration file (Use mask fractions: true/false). It defaults to false.
     103             :   REAL(sp), PARAMETER  :: MASK_THRESHOLD = 0.5_sp
     104             : !
     105             : ! ============================================================================
     106             : !
     107             : ! !REVISION HISTORY:
     108             : !  25 Aug 2012 - C. Keller   - Initial version.
     109             : !  See https://github.com/geoschem/hemco for complete history
     110             : !EOP
     111             : !------------------------------------------------------------------------------
     112             : !BOC
     113             :   INTERFACE HCO_EvalFld
     114             :      MODULE PROCEDURE HCO_EvalFld_2D
     115             :      MODULE PROCEDURE HCO_EvalFld_3D
     116             :   END INTERFACE HCO_EvalFld
     117             : 
     118             : CONTAINS
     119             : !EOC
     120             : !------------------------------------------------------------------------------
     121             : !                   Harmonized Emissions Component (HEMCO)                    !
     122             : !------------------------------------------------------------------------------
     123             : !BOP
     124             : !
     125             : ! !IROUTINE: HCO_CalcEmis
     126             : !
     127             : ! !DESCRIPTION: Subroutine HCO\_CalcEmis calculates the 3D emission
     128             : ! fields at current datetime for the specified species, categories, and
     129             : ! extension number.
     130             : !\\
     131             : !\\
     132             : ! !INTERFACE:
     133             : !
     134           0 :   SUBROUTINE HCO_CalcEmis( HcoState, UseConc, RC )
     135             : !
     136             : ! !USES:
     137             : !
     138             :     USE HCO_STATE_MOD,    ONLY : HCO_State
     139             :     USE HCO_ARR_MOD,      ONLY : HCO_ArrAssert
     140             :     USE HCO_DATACONT_MOD, ONLY : ListCont_NextCont
     141             :     USE HCO_FILEDATA_MOD, ONLY : FileData_ArrIsDefined
     142             :     USE HCO_Scale_Mod,    ONLY : HCO_ScaleArr
     143             : !
     144             : ! !INPUT PARAMETERS:
     145             : !
     146             :     LOGICAL,         INTENT(IN   )  :: UseConc    ! Use concentration fields?
     147             : !
     148             : ! !INPUT/OUTPUT PARAMETERS:
     149             : !
     150             :     TYPE(HCO_State), POINTER        :: HcoState   ! HEMCO state object
     151             :     INTEGER,         INTENT(INOUT)  :: RC         ! Return code
     152             : !
     153             : ! !REVISION HISTORY:
     154             : !  25 Aug 2012 - C. Keller   - Initial Version
     155             : !  See https://github.com/geoschem/hemco for complete history
     156             : !EOP
     157             : !------------------------------------------------------------------------------
     158             : !BOC
     159             : !
     160             : ! !LOCAL VARIABLES:
     161             : !
     162             :     ! Working pointers: list and data container
     163             :     TYPE(ListCont), POINTER :: Lct
     164             :     TYPE(DataCont), POINTER :: Dct
     165             : 
     166             :     ! Temporary emission arrays
     167             :     REAL(hp), POINTER       :: OutArr(:,:,:) => NULL()
     168             :     REAL(hp), TARGET        :: SpcFlx( HcoState%NX, &
     169             :                                        HcoState%NY, &
     170           0 :                                        HcoState%NZ   )
     171             :     REAL(hp), TARGET        :: CatFlx( HcoState%NX, &
     172             :                                        HcoState%NY, &
     173           0 :                                        HcoState%NZ   )
     174             :     REAL(hp), TARGET        :: TmpFlx( HcoState%NX, &
     175             :                                        HcoState%NY, &
     176           0 :                                        HcoState%NZ   )
     177             :     REAL(hp)                :: Mask  ( HcoState%NX, &
     178             :                                        HcoState%NY, &
     179           0 :                                        HcoState%NZ   )
     180             :     REAL(hp)                :: HirFlx( HcoState%NX, &
     181             :                                        HcoState%NY, &
     182           0 :                                        HcoState%NZ   )
     183             :     REAL(hp)                :: HirMsk( HcoState%NX, &
     184             :                                        HcoState%NY, &
     185           0 :                                        HcoState%NZ   )
     186             : 
     187             :     ! Integers
     188             :     INTEGER             :: ThisSpc, PrevSpc ! current and previous species ID
     189             :     INTEGER             :: ThisCat, PrevCat ! current and previous category
     190             :     INTEGER             :: ThisHir, PrevHir ! current and previous hierarchy
     191             :     INTEGER             :: SpcMin,  SpcMax  ! range of species to be considered
     192             :     INTEGER             :: CatMin,  CatMax  ! range of categories to be considered
     193             :     INTEGER             :: ExtNr            ! Extension Nr to be used
     194             :     INTEGER             :: nI, nJ, nL
     195             :     INTEGER             :: nnSpec, FLAG
     196             : 
     197             :     LOGICAL             :: Found, DoDiagn, EOL, UpdateCat
     198             : 
     199             :     ! For error handling & verbose mode
     200             :     CHARACTER(LEN=255)  :: MSG, LOC
     201             : 
     202             :     ! testing / debugging
     203             :     integer :: ix,iy
     204             : 
     205             :     !=================================================================
     206             :     ! HCO_CalcEmis begins here!
     207             :     !=================================================================
     208             : 
     209             :     ! testing only
     210           0 :     ix = 30
     211           0 :     iy = 34
     212             : 
     213             :     ! Initialize
     214           0 :     LOC = 'HCO_CalcEmis (HCO_CALC_MOD.F90)'
     215           0 :     Lct => NULL()
     216           0 :     Dct => NULL()
     217             : 
     218             :     ! Enter routine
     219           0 :     CALL HCO_ENTER (HcoState%Config%Err, LOC, RC )
     220           0 :     IF(RC /= HCO_SUCCESS) RETURN
     221             : 
     222             :     !-----------------------------------------------------------------
     223             :     ! Initialize variables
     224             :     !-----------------------------------------------------------------
     225             : 
     226             :     ! Initialize
     227           0 :     SpcFlx(:,:,:)    = 0.0_hp
     228           0 :     CatFlx(:,:,:)    = 0.0_hp
     229           0 :     HirFlx(:,:,:)    = 0.0_hp
     230           0 :     HirMsk(:,:,:)    = 0.0_hp
     231           0 :     PrevSpc          = -1
     232           0 :     PrevHir          = -1
     233           0 :     PrevCat          = -1
     234           0 :     nnSpec           = 0
     235             : 
     236             :     ! Pass emission grid dimensions
     237           0 :     nI = HcoState%NX
     238           0 :     nJ = HcoState%NY
     239           0 :     nL = HcoState%NZ
     240             : 
     241             :     ! Pass calculation options
     242           0 :     SpcMin  = HcoState%Options%SpcMin        !Lower species ID
     243           0 :     SpcMax  = HcoState%Options%SpcMax        !Upper species ID
     244           0 :     CatMin  = HcoState%Options%CatMin        !Lower emission category
     245           0 :     CatMax  = HcoState%Options%CatMax        !Upper emission category
     246           0 :     ExtNr   = HcoState%Options%ExtNr         !Extension number
     247           0 :     DoDiagn = HcoState%Options%AutoFillDiagn !Write AutoFill diagnostics?
     248             : 
     249             :     ! Verbose mode
     250           0 :     IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
     251           0 :        WRITE (MSG, *) 'Run HEMCO calculation w/ following options:'
     252           0 :        CALL HCO_MSG ( HcoState%Config%Err, MSG )
     253           0 :        WRITE (MSG, "(A20,I5)")    'Extension number:', ExtNr
     254           0 :        CALL HCO_MSG ( HcoState%Config%Err, MSG )
     255           0 :        WRITE (MSG, "(A20,I5,I5)") 'Tracer range:', SpcMin, SpcMax
     256           0 :        CALL HCO_MSG ( HcoState%Config%Err, MSG )
     257           0 :        WRITE (MSG, "(A20,I5,I5)") 'Category range:', CatMin, CatMax
     258           0 :        CALL HCO_MSG ( HcoState%Config%Err, MSG )
     259           0 :        WRITE (MSG, *) 'Auto diagnostics: ', DoDiagn
     260           0 :        CALL HCO_MSG ( HcoState%Config%Err, MSG )
     261             :     ENDIF
     262             : 
     263             :     !=================================================================
     264             :     ! Walk through all containers of EmisList and determine the
     265             :     ! emissions for all containers that qualify for calculation.
     266             :     ! The containers in EmisList are sorted by species, category and
     267             :     ! hierarchy. This enables a straightforward, piece-by-piece
     268             :     ! assembly of the final emission array (start with lowest
     269             :     ! hierarchy emissions, then overwrite piece-by-piece with higher
     270             :     ! hierarchy values).
     271             :     !=================================================================
     272             : 
     273             :     ! Point to the head of the emissions linked list
     274           0 :     EOL = .FALSE. ! End of list
     275           0 :     Lct => NULL()
     276           0 :     CALL ListCont_NextCont ( HcoState%EmisList, Lct, FLAG )
     277             : 
     278             :     ! Do until end of EmisList (==> loop over all emission containers)
     279             :     DO
     280             :        ! Have we reached the end of the list?
     281           0 :        EOL = .FALSE.
     282           0 :        IF ( FLAG /= HCO_SUCCESS ) EOL = .TRUE.
     283             : 
     284             :        ! ------------------------------------------------------------
     285             :        ! Select container and update all working variables & arrays.
     286             :        ! ------------------------------------------------------------
     287             :        IF ( .NOT. EOL ) THEN
     288             : 
     289             :           ! Dct is the current data container
     290           0 :           Dct => Lct%Dct
     291             : 
     292             :           ! Check if this is a base field
     293           0 :           IF ( Dct%DctType /= HCO_DCTTYPE_BASE ) THEN
     294           0 :              CALL ListCont_NextCont ( HcoState%EmisList, Lct, FLAG )
     295           0 :              CYCLE
     296             :           ENDIF
     297             : 
     298             :           ! Sanity check: Make sure this container holds data.
     299             :           ! 'Empty' containers are possible if the simulation time
     300             :           ! is outside of the specified data time range and time
     301             :           ! slice cycling is deactivated (CycleFlag > 1).
     302           0 :           IF( .NOT. FileData_ArrIsDefined(Lct%Dct%Dta) ) THEN
     303           0 :              CALL ListCont_NextCont ( HcoState%EmisList, Lct, FLAG )
     304           0 :              CYCLE
     305             :           ENDIF
     306             : 
     307             :           ! Check if this is the specified extension number
     308           0 :           IF ( Dct%ExtNr /= ExtNr ) THEN
     309           0 :              CALL ListCont_NextCont ( HcoState%EmisList, Lct, FLAG )
     310           0 :              CYCLE
     311             :           ENDIF
     312             : 
     313             :           ! Advance to next container if the species ID is outside
     314             :           ! the specified species range (SpcMin - SpcMax). Consider
     315             :           ! all species above SpcMin if SpcMax is negative!
     316           0 :           IF( (  Dct%HcoID < SpcMin                     ) .OR. &
     317             :               ( (Dct%HcoID > SpcMax) .AND. (SpcMax > 0) ) ) THEN
     318           0 :              CALL ListCont_NextCont ( HcoState%EmisList, Lct, FLAG )
     319           0 :              CYCLE
     320             :           ENDIF
     321             : 
     322             :           ! Advance to next emission field if the emission category of
     323             :           ! the current container is outside of the specified species
     324             :           ! range (CatMin - CatMax). Consider all categories above CatMin
     325             :           ! if CatMax is negative!
     326           0 :           IF( (  Dct%Cat < CatMin                     ) .OR. &
     327             :               ( (Dct%Cat > CatMax) .AND. (CatMax > 0) ) ) THEN
     328           0 :              CALL ListCont_NextCont ( HcoState%EmisList, Lct, FLAG )
     329           0 :              CYCLE
     330             :           ENDIF
     331             : 
     332             :           ! Check if this container holds data in the desired unit format,
     333             :           ! i.e. concentration data if UseConc is enabled, emission data
     334             :           ! otherwise.
     335           0 :           IF ( UseConc .NEQV. Dct%Dta%IsConc ) THEN
     336           0 :              CALL ListCont_NextCont ( HcoState%EmisList, Lct, FLAG )
     337           0 :              CYCLE
     338             :           ENDIF
     339             : 
     340             :           ! Update working variables
     341           0 :           ThisSpc = Dct%HcoID
     342           0 :           ThisCat = Dct%Cat
     343           0 :           ThisHir = Dct%Hier
     344             : 
     345             :        ! If end of list, use dummy values for ThisSpc, ThisCat and ThisHir
     346             :        ! to make sure that emissions are added to HEMCO in the section
     347             :        ! below!
     348             :        ELSE
     349           0 :           ThisSpc = -1
     350           0 :           ThisCat = -1
     351           0 :           ThisHir = -1
     352             :        ENDIF
     353             : 
     354             :        !--------------------------------------------------------------------
     355             :        ! Before computing emissions of current data container make sure that
     356             :        ! emissions of previous container are properly archived.
     357             :        !--------------------------------------------------------------------
     358             : 
     359             :        ! Add emissions on hierarchy level to the category flux array. Do
     360             :        ! this only if this is a new species, a new category or a new
     361             :        ! hierarchy level.
     362             :        ! Note: no need to add to diagnostics because hierarchy level
     363             :        ! diagnostics are filled right after computing the emissions of
     364             :        ! a given data container (towards the end of the DO loop).
     365             :        IF ( (ThisHir /= PrevHir) .OR. &
     366           0 :             (ThisSpc /= PrevSpc) .OR. &
     367             :             (ThisCat /= PrevCat)        ) THEN
     368             : 
     369             :           ! Add hierarchy level emissions to category array over the
     370             :           ! covered regions.
     371           0 :           CatFlx = ( (1.0_hp - HirMsk) * CatFlx ) + HirFlx
     372             : 
     373             :           ! Reset
     374           0 :           HirFlx = 0.0_hp
     375           0 :           HirMsk = 0.0_hp
     376             :        ENDIF
     377             : 
     378             :        !--------------------------------------------------------------------
     379             :        ! If this is a new species or category, pass the previously collected
     380             :        ! emissions to the species array. Update diagnostics at category level.
     381             :        ! Skip this step for first species, i.e. if PrevSpc is still -1.
     382             :        !--------------------------------------------------------------------
     383           0 :        UpdateCat = .FALSE.
     384           0 :        IF ( ThisCat /= PrevCat ) UpdateCat = .TRUE.
     385           0 :        IF ( ThisSpc /= PrevSpc ) UpdateCat = .TRUE.
     386           0 :        IF ( PrevCat <= 0 .OR. PrevSpc <= 0 ) UpdateCat = .FALSE.
     387           0 :        IF ( UpdateCat ) THEN
     388             : 
     389             :           ! CatFlx holds the emissions for this category. Pass this to
     390             :           ! the species array SpcFlx.
     391           0 :           SpcFlx(:,:,:) = SpcFlx(:,:,:) + CatFlx(:,:,:)
     392             : 
     393             :           ! verbose
     394           0 :           IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
     395           0 :              WRITE(MSG,*) 'Added category emissions to species array: '
     396           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     397           0 :              WRITE(MSG,*) 'Species       : ', PrevSpc
     398           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     399           0 :              WRITE(MSG,*) 'Category      : ', PrevCat
     400           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     401           0 :              WRITE(MSG,*) 'Cat. emissions: ', SUM(CatFlx)
     402           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     403           0 :              WRITE(MSG,*) 'Spc. emissions: ', SUM(SpcFlx)
     404           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     405             :           ENDIF
     406             : 
     407             :           ! Add category emissions to diagnostics at category level
     408             :           ! (only if defined in the diagnostics list).
     409           0 :           IF ( Diagn_AutoFillLevelDefined(HcoState%Diagn,3) .AND. DoDiagn ) THEN
     410             :              ! Bug fix: Make sure to pass COL=-1 to ensure all HEMCO diagnostics
     411             :              ! are updated, including those manually defined in other models
     412             :              ! (mps, 11/30/21)
     413             :              CALL Diagn_Update( HcoState,    ExtNr=ExtNr,   &
     414             :                                 Cat=PrevCat, Hier=-1,  HcoID=PrevSpc, &
     415           0 :                                 AutoFill=1,  Array3D=CatFlx, COL=-1, RC=RC )
     416           0 :              IF ( RC /= HCO_SUCCESS ) THEN
     417           0 :                  CALL HCO_ERROR( 'ERROR 0', RC, THISLOC=LOC )
     418           0 :                  RETURN
     419             :              ENDIF
     420             : #ifdef ADJOINT
     421             :              IF (HcoState%IsAdjoint) THEN
     422             :                 CALL Diagn_Update( HcoState,    ExtNr=ExtNr,             &
     423             :                                    Cat=PrevCat, Hier=-1,  HcoID=PrevSpc, &
     424             :                                    AutoFill=1,  Array3D=CatFlx,          &
     425             :                                    COL=HcoState%Diagn%HcoDiagnIDAdjoint, RC=RC )
     426             :                 IF ( RC /= HCO_SUCCESS ) THEN
     427             :                     CALL HCO_ERROR( 'ERROR 1', RC, THISLOC=LOC )
     428             :                     RETURN
     429             :                 ENDIF
     430             :              ENDIF
     431             : #endif
     432             :           ENDIF
     433             : 
     434             :           ! Reset CatFlx array and the previously used hierarchy
     435             :           ! ==> Emission hierarchies are only important within the
     436             :           ! same category, hence always start over at lowest hierarchy
     437             :           ! when entering a new category.
     438           0 :           CatFlx(:,:,:)  = 0.0_hp
     439             :           PrevHir        = -1
     440             :        ENDIF
     441             : 
     442             :        !--------------------------------------------------------------------
     443             :        ! If this is a new species, pass previously calculated emissions
     444             :        ! to the final emissions array in HcoState.
     445             :        ! Update diagnostics at extension number level.
     446             :        ! Don't do before first emission calculation, i.e. if PrevSpc
     447             :        ! is still the initialized value of -1!
     448             :        !--------------------------------------------------------------------
     449           0 :        IF ( ThisSpc /= PrevSpc .AND. PrevSpc > 0 ) THEN
     450             : 
     451             :           ! Add to OutArr
     452           0 :           OutArr(:,:,:) = OutArr(:,:,:) + SpcFlx(:,:,:)
     453             : 
     454             :           ! testing only
     455           0 :           IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
     456           0 :              WRITE(MSG,*) 'Added total emissions to output array: '
     457           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     458           0 :              WRITE(MSG,*) 'Species: ', PrevSpc
     459           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     460           0 :              WRITE(MSG,*) 'SpcFlx : ', SUM(SpcFlx)
     461           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     462           0 :              WRITE(MSG,*) 'OutArr : ', SUM(OutArr)
     463           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
     464             :           ENDIF
     465             : 
     466             :           ! Add to diagnostics at extension number level.
     467             :           ! The same diagnostics may be updated multiple times during
     468             :           ! the same time step, continuously adding emissions to it.
     469           0 :           IF ( Diagn_AutoFillLevelDefined(HcoState%Diagn,2) .AND. DoDiagn ) THEN
     470             :              ! Bug fix: Make sure to pass COL=-1 to ensure all HEMCO diagnostics
     471             :              ! are updated, including those manually defined in other models
     472             :              ! (mps, 11/30/21)
     473             :              CALL Diagn_Update( HcoState,  ExtNr=ExtNr,  &
     474             :                                 Cat=-1,    Hier=-1,  HcoID=PrevSpc, &
     475           0 :                                AutoFill=1,Array3D=SpcFlx, COL=-1, RC=RC )
     476           0 :              IF ( RC /= HCO_SUCCESS ) THEN
     477           0 :                  CALL HCO_ERROR( 'ERROR 2', RC, THISLOC=LOC )
     478           0 :                  RETURN
     479             :              ENDIF
     480             : #ifdef ADJOINT
     481             :              IF (HcoState%IsAdjoint) THEN
     482             :                 CALL Diagn_Update( HcoState,  ExtNr=ExtNr,             &
     483             :                                    Cat=-1,    Hier=-1,  HcoID=PrevSpc, &
     484             :                                    AutoFill=1,Array3D=SpcFlx,          &
     485             :                                    COL=HcoState%Diagn%HcoDiagnIDAdjoint, RC=RC )
     486             :                 IF ( RC /= HCO_SUCCESS ) THEN
     487             :                     CALL HCO_ERROR( 'ERROR 3', RC, THISLOC=LOC )
     488             :                     RETURN
     489             :                 ENDIF
     490             :              ENDIF
     491             : #endif
     492             :           ENDIF
     493             : 
     494             :           ! Reset arrays and previous hierarchy.
     495           0 :           SpcFlx(:,:,:)  =  0.0_hp
     496           0 :           PrevCat        =  -1
     497           0 :           PrevHir        =  -1
     498           0 :           OutArr         => NULL()
     499             :        ENDIF
     500             : 
     501             :        !--------------------------------------------------------------------
     502             :        ! Exit DO loop here if end of list
     503             :        !--------------------------------------------------------------------
     504           0 :        IF ( EOL ) EXIT
     505             : 
     506             :        !--------------------------------------------------------------------
     507             :        ! Update/archive information on species level if needed
     508             :        !--------------------------------------------------------------------
     509           0 :        IF ( ThisSpc /= PrevSpc .AND. ThisSpc > 0 ) THEN
     510             : 
     511             :           ! Update number of species for which emissions have been
     512             :           ! calculated.
     513           0 :           nnSpec = nnSpec + 1
     514             : 
     515             :           ! To write emissions into temporary array, make OutArr point
     516             :           ! to the buffer array HcoState%Buffer3D.
     517           0 :           IF ( HcoState%Options%FillBuffer ) THEN
     518             : 
     519             :              ! Cannot use temporary array for more than one species!
     520           0 :              IF ( nnSpec > 1 ) THEN
     521           0 :                 MSG = 'Cannot fill buffer for more than one species!'
     522           0 :                 CALL HCO_ERROR( MSG, RC )
     523           0 :                 RETURN
     524             :              ENDIF
     525             : 
     526             :              ! Point to array and check allocation status as well as
     527             :              ! array size.
     528           0 :              OutArr => HcoState%Buffer3D%Val
     529           0 :              IF ( .NOT. ASSOCIATED( OutArr ) ) THEN
     530           0 :                 MSG = 'Buffer array is not associated'
     531           0 :                 CALL HCO_ERROR( MSG, RC )
     532           0 :                 RETURN
     533             :              ENDIF
     534             :              IF ( (SIZE(OutArr,1) /= nI) .OR. &
     535           0 :                   (SIZE(OutArr,2) /= nJ) .OR. &
     536             :                   (SIZE(OutArr,3) /= nL)       ) THEN
     537           0 :                 MSG = 'Buffer array has wrong dimension!'
     538           0 :                 CALL HCO_ERROR( MSG, RC )
     539           0 :                 RETURN
     540             :              ENDIF
     541             : 
     542             :           ! To write emissions directly into HcoState, make OutArr
     543             :           ! point to current species' array in HcoState. Use emission
     544             :           ! array for emissions, and concentration array for concentrations.
     545             :           ELSE
     546             : 
     547             :              ! For concentrations:
     548           0 :              IF ( UseConc ) THEN
     549           0 :                 CALL HCO_ArrAssert( HcoState%Spc(ThisSpc)%Conc, &
     550           0 :                                     nI, nJ, nL, RC             )
     551           0 :                 IF ( RC /= HCO_SUCCESS ) THEN
     552           0 :                     CALL HCO_ERROR( 'ERROR 4', RC, THISLOC=LOC )
     553           0 :                     RETURN
     554             :                 ENDIF
     555           0 :                 OutArr => HcoState%Spc(ThisSpc)%Conc%Val
     556             : 
     557             :              ! For emissions:
     558             :              ELSE
     559           0 :                 CALL HCO_ArrAssert( HcoState%Spc(ThisSpc)%Emis, &
     560           0 :                                     nI, nJ, nL, RC             )
     561           0 :                 IF ( RC /= HCO_SUCCESS ) THEN
     562           0 :                     CALL HCO_ERROR( 'ERROR 5', RC, THISLOC=LOC )
     563           0 :                     RETURN
     564             :                 ENDIF
     565           0 :                 OutArr => HcoState%Spc(ThisSpc)%Emis%Val
     566             :              ENDIF
     567             : 
     568             :           ENDIF
     569             : 
     570             :           ! verbose mode
     571           0 :           IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
     572           0 :              WRITE(MSG,*) 'Calculating emissions for species ', &
     573           0 :                            TRIM(HcoState%Spc(ThisSpc)%SpcName)
     574           0 :              CALL HCO_MSG( HcoState%Config%Err, MSG, SEP1='-', SEP2='-' )
     575             :           ENDIF
     576             :        ENDIF
     577             : 
     578             :        !--------------------------------------------------------------------
     579             :        ! Get current emissions and write into TmpFlx array. The array Mask
     580             :        ! denotes all valid grid boxes for this inventory.
     581             :        !--------------------------------------------------------------------
     582           0 :        TmpFlx(:,:,:) = 0.0_hp
     583           0 :        CALL GET_CURRENT_EMISSIONS( HcoState, Dct, nI, nJ, nL, TmpFlx, Mask, RC )
     584           0 :        IF ( RC /= HCO_SUCCESS ) THEN
     585           0 :            CALL HCO_ERROR( 'ERROR 6', RC, THISLOC=LOC )
     586           0 :            RETURN
     587             :        ENDIF
     588             : 
     589             :        ! Eventually add universal scale factor
     590           0 :        CALL HCO_ScaleArr( HcoState, ThisSpc, TmpFlx, RC )
     591           0 :        IF ( RC /= HCO_SUCCESS ) THEN
     592           0 :            CALL HCO_ERROR( 'ERROR 7', RC, THISLOC=LOC )
     593           0 :            RETURN
     594             :        ENDIF
     595             : 
     596             :        ! Check for negative values according to the corresponding setting
     597             :        ! in the configuration file: 2 means allow negative values, 1 means
     598             :        ! set to zero and prompt a warning, else return with error.
     599           0 :        IF ( HcoState%Options%NegFlag /= 2 ) THEN
     600             : 
     601           0 :           IF ( ANY(TmpFlx < 0.0_hp) ) THEN
     602             : 
     603             :              ! Set to zero and prompt warning
     604           0 :              IF ( HcoState%Options%NegFlag == 1 ) THEN
     605           0 :                 WHERE ( TmpFlx < 0.0_hp ) TmpFlx = 0.0_hp
     606           0 :                 MSG = 'Negative emissions set to zero: '// TRIM(Dct%cName)
     607           0 :                 CALL HCO_WARNING( HcoState%Config%Err, MSG, RC )
     608             : 
     609             :              ! Return with error
     610             :              ELSE
     611             :                 MSG = 'Negative emissions in: '// TRIM(Dct%cName) // '. ' // &
     612           0 :                 'To allow negatives, edit settings in the configuration file.'
     613           0 :                 CALL HCO_ERROR( MSG, RC )
     614           0 :                 RETURN
     615             :              ENDIF
     616             :           ENDIF
     617             :        ENDIF
     618             : 
     619             :        ! ------------------------------------------------------------
     620             :        ! Collect all emissions of the same category (and species) on
     621             :        ! the hierarchy level into array HirFlx. HirMsk contains the
     622             :        ! combined covered region. That is, if there are two regional
     623             :        ! inventories with the same hierarchy HirMsk will cover both
     624             :        ! of these regions.
     625             :        ! The specified field hierarchies determine whether the
     626             :        ! temporary emissions are added (if hierarchy is the same
     627             :        ! as the previously used hierarchy), or if they overwrite the
     628             :        ! previous values in HirFlx (if hierarchy is higher than the
     629             :        ! previous hierarchy).
     630             :        ! ------------------------------------------------------------
     631             : 
     632             :        ! Add emissions to the hierarchy array HirFlx if this hierarchy
     633             :        ! is the same as previous hierarchy
     634           0 :        IF ( ThisHir == PrevHir ) THEN
     635           0 :           HirFlx = HirFlx + TmpFlx
     636           0 :           HirMsk = HirMsk + Mask
     637             : 
     638             :           ! Make sure mask values do not exceed 1.0
     639           0 :           WHERE(HirMsk > 1.0 ) HirMsk = 1.0
     640             : 
     641             :        ! If hierarchy is larger than those of the previously used
     642             :        ! fields, overwrite HirFlx with new values.
     643             :        ELSE
     644             : 
     645           0 :           HirFlx = TmpFlx
     646           0 :           HirMsk = Mask
     647             : 
     648             :        ENDIF
     649             : 
     650             :        ! Update diagnostics at hierarchy level. Make sure that only
     651             :        ! positive values are used.
     652             :        ! The same diagnostics may be updated multiple times
     653             :        ! during the same time step, continuously adding
     654             :        ! emissions to it.
     655             :        ! Now remove PosOnly flag. TmpFlx is initialized to zero, so it's
     656             :        ! ok to keep negative values (ckeller, 7/12/15).
     657           0 :        IF ( Diagn_AutoFillLevelDefined(HcoState%Diagn,4) .AND. DoDiagn ) THEN
     658             :              ! Bug fix: Make sure to pass COL=-1 to ensure all HEMCO diagnostics
     659             :              ! are updated, including those manually defined in other models
     660             :              ! (mps, 11/30/21)
     661             :           CALL Diagn_Update( HcoState,       ExtNr=ExtNr,   &
     662             :                              Cat=ThisCat,Hier=ThisHir,   HcoID=ThisSpc, &
     663             :                              AutoFill=1, Array3D=TmpFlx, &
     664           0 :                              COL=-1, RC=RC )
     665           0 :           IF ( RC /= HCO_SUCCESS ) THEN
     666           0 :               CALL HCO_ERROR( 'ERROR 8', RC, THISLOC=LOC )
     667           0 :               RETURN
     668             :           ENDIF
     669             : #ifdef ADJOINT
     670             :           IF (HcoState%IsAdjoint) THEN
     671             :              ! I don't know why I chose collection=-1 instead of
     672             :              ! collection=HcoState%Diagn%HcoDiagnIDAdjoint like in the other
     673             :              ! parts of the adjoint code here, but it's what worked in the
     674             :              ! old repo so I'm keeping it for now. May need to change
     675             :              CALL Diagn_Update( HcoState,       ExtNr=ExtNr,               &
     676             :                                 Cat=ThisCat,Hier=ThisHir,   HcoID=ThisSpc, &
     677             :                                 AutoFill=1, Array3D=TmpFlx,                &
     678             :                                 COL=-1, RC=RC )
     679             :              IF ( RC /= HCO_SUCCESS ) THEN
     680             :                  CALL HCO_ERROR( 'ERROR 9', RC, THISLOC=LOC )
     681             :                  RETURN
     682             :              ENDIF
     683             :           ENDIF
     684             : 
     685             : #endif
     686             :        ENDIF
     687             : 
     688             :        ! Update previously used species, category and hierarchy
     689           0 :        PrevSpc = ThisSpc
     690           0 :        PrevCat = ThisCat
     691           0 :        PrevHir = ThisHir
     692             : 
     693             :        ! Advance to next emission container
     694           0 :        CALL ListCont_NextCont( HcoState%EmisList, Lct, FLAG )
     695             : 
     696             :     ENDDO ! Loop over EmisList
     697             : 
     698             :     ! Make sure internal pointers are nullified
     699           0 :     Lct    => NULL()
     700           0 :     Dct    => NULL()
     701           0 :     OutArr => NULL()
     702             : 
     703             :     ! verbose
     704           0 :     IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
     705           0 :        WRITE (MSG, *) 'HEMCO emissions successfully calculated!'
     706           0 :        CALL HCO_MSG ( HcoState%Config%Err, MSG )
     707             :     ENDIF
     708             : 
     709             :     ! Leave w/ success
     710           0 :     CALL HCO_LEAVE ( HcoState%Config%Err, RC )
     711             : 
     712             :   END SUBROUTINE HCO_CalcEmis
     713             : !EOC
     714             : !------------------------------------------------------------------------------
     715             : !                   Harmonized Emissions Component (HEMCO)                    !
     716             : !------------------------------------------------------------------------------
     717             : !BOP
     718             : !
     719             : ! !IROUTINE: HCO_CheckDepv
     720             : !
     721             : ! !DESCRIPTION: Subroutine HCO\_CheckDepv is a simple routine to check the
     722             : ! dry deposition frequency value. This is to avoid unrealistically high
     723             : ! deposition frequencies that may occur if grid box concentrations are very
     724             : ! low. The deposition frequency is limited to a value that will make sure
     725             : ! that the drydep exponent ( exp( -depfreq * dt ) ) is still small enough to
     726             : ! remove all species mass. The maximum limit of depfreq * dt can be defined
     727             : ! as a HEMCO option (MaxDepExp). Its default value is 20.0.
     728             : !\\
     729             : !\\
     730             : ! !INTERFACE:
     731             : !
     732           0 :   SUBROUTINE HCO_CheckDepv( HcoState, Depv, RC )
     733             : !
     734             : ! !USES:
     735             : !
     736             :     USE HCO_STATE_MOD,    ONLY : HCO_State
     737             : !
     738             : ! !INPUT/OUTPUT PARAMETERS:
     739             : !
     740             :     TYPE(HCO_State), POINTER        :: HcoState   ! HEMCO state object
     741             :     REAL(hp),        INTENT(INOUT)  :: Depv       ! Deposition velocity
     742             :     INTEGER,         INTENT(INOUT)  :: RC         ! Return code
     743             : !
     744             : ! !REVISION HISTORY:
     745             : !  11 Mar 2015 - C. Keller   - Initial Version
     746             : !  See https://github.com/geoschem/hemco for complete history
     747             : !EOP
     748             : !------------------------------------------------------------------------------
     749             : !BOC
     750             : !
     751             : ! !LOCAL VARIABLES:
     752             : !
     753             :     REAL(hp)  :: ExpVal
     754             : 
     755             :     !=================================================================
     756             :     ! HCO_CheckDepv begins here!
     757             :     !=================================================================
     758             : 
     759           0 :     ExpVal = Depv * HcoState%TS_EMIS
     760           0 :     IF ( ExpVal > HcoState%Options%MaxDepExp ) THEN
     761           0 :        Depv = HcoState%Options%MaxDepExp / HcoState%TS_EMIS
     762             :     ENDIF
     763             : 
     764           0 :   END SUBROUTINE HCO_CheckDepv
     765             : !EOC
     766             : !------------------------------------------------------------------------------
     767             : !                   Harmonized Emissions Component (HEMCO)                    !
     768             : !------------------------------------------------------------------------------
     769             : !BOP
     770             : !
     771             : ! !IROUTINE: Get_Current_Emissions
     772             : !
     773             : ! !DESCRIPTION: Subroutine Get\_Current\_Emissions calculates the current
     774             : !  emissions for the specified emission container.
     775             : !  This subroutine is only called by HCO\_CalcEmis and for base emission
     776             : !  containers, i.e. containers of type 1.
     777             : !\\
     778             : !\\
     779             : ! !INTERFACE:
     780             : !
     781           0 :   SUBROUTINE Get_Current_Emissions( HcoState, BaseDct,   nI,   nJ,           &
     782           0 :                                     nL,       OUTARR_3D, MASK, RC, UseLL    )
     783             : !
     784             : ! !USES:
     785             : !
     786             :     USE HCO_State_Mod,    ONLY : HCO_State
     787             :     USE HCO_tIdx_MOD,     ONLY : tIDx_GetIndx
     788             :     USE HCO_FileData_Mod, ONLY : FileData_ArrIsDefined
     789             : !
     790             : ! !INPUT PARAMETERS:
     791             : !
     792             :     INTEGER,           INTENT(IN)  :: nI                  ! # of lons
     793             :     INTEGER,           INTENT(IN)  :: nJ                  ! # of lats
     794             :     INTEGER,           INTENT(IN)  :: nL                  ! # of levs
     795             : !
     796             : ! !INPUT/OUTPUT PARAMETERS:
     797             : !
     798             : 
     799             :     TYPE(HCO_State), POINTER       :: HcoState            ! HEMCO state object
     800             :     TYPE(DataCont),  POINTER       :: BaseDct             ! base emission
     801             :                                                           !  container
     802             :     REAL(hp),        INTENT(INOUT) :: outArr_3D(nI,nJ,nL) ! output array
     803             :     REAL(hp),        INTENT(INOUT) :: mask     (nI,nJ,nL) ! mask array
     804             :     INTEGER,         INTENT(INOUT) :: RC
     805             : !
     806             : ! !OUTPUT PARAMETERS:
     807             : !
     808             :     INTEGER,         INTENT(  OUT), OPTIONAL :: UseLL
     809             : !
     810             : ! !REMARKS:
     811             : !  This routine uses multiple loops over all grid boxes (base emissions
     812             : !  and scale factors use separate loops). In an OMP environment, this approach
     813             : !  seems to be faster than using only one single loop (but repeated calls to
     814             : !  point to containers, etc.). The alternative approach is used in routine
     815             : !  Get\_Current\_Emissions\_B at the end of this module and may be employed
     816             : !  on request.
     817             : !
     818             : ! !REVISION HISTORY:
     819             : !  25 Aug 2012 - C. Keller   - Initial Version
     820             : !  See https://github.com/geoschem/hemco for complete history
     821             : !EOP
     822             : !------------------------------------------------------------------------------
     823             : !BOC
     824             : !
     825             : ! !LOCAL VARIABLES:
     826             : !
     827             :     ! Pointers
     828             :     TYPE(DataCont), POINTER :: ScalDct
     829             :     TYPE(DataCont), POINTER :: MaskDct
     830             :     TYPE(DataCont), POINTER :: LevDct1
     831             :     TYPE(DataCont), POINTER :: LevDct2
     832             : 
     833             :     ! Scalars
     834             :     REAL(sp)                :: tmpVal, MaskScale
     835             :     REAL(hp)                :: outData
     836             :     REAL(hp)                :: ScalFact
     837             :     INTEGER                 :: tIDx,  IDX
     838             :     INTEGER                 :: totLL, nnLL
     839             :     INTEGER                 :: I,     J,     L,      N
     840             :     INTEGER                 :: LowLL, UppLL, ScalLL, TmpLL
     841             :     INTEGER                 :: EC,    ERROR
     842             :     CHARACTER(LEN=255)      :: MSG,   thisLoc
     843             :     LOGICAL                 :: NegScalExist
     844             :     LOGICAL                 :: MaskFractions
     845             :     LOGICAL                 :: isLevDct1
     846             :     LOGICAL                 :: isLevDct2
     847             :     LOGICAL                 :: isMaskDct
     848             :     LOGICAL                 :: isPblHt
     849             :     LOGICAL                 :: isBoxHt
     850             :     INTEGER                 :: LevDct1_Unit
     851             :     INTEGER                 :: LevDct2_Unit
     852             : 
     853             :     ! testing only
     854             :     INTEGER, PARAMETER      :: IX=25, IY=25
     855             : 
     856             :     !=================================================================
     857             :     ! GET_CURRENT_EMISSIONS begins here
     858             :     !=================================================================
     859             : 
     860             :     ! Initialize
     861           0 :     ScalDct => NULL()
     862           0 :     MaskDct => NULL()
     863           0 :     msg     = ''
     864           0 :     thisLoc = 'GET_CURRENT_EMISSIONS (hco_calc_mod.F90)'
     865             : 
     866             :     ! Enter
     867           0 :     CALL HCO_Enter( HcoState%Config%Err, thisLoc, RC )
     868           0 :     IF ( RC /= HCO_SUCCESS ) RETURN
     869             : 
     870             :     ! Check if container contains data
     871           0 :     IF ( .NOT. FileData_ArrIsDefined(BaseDct%Dta) ) THEN
     872           0 :        msg = 'Array not defined: ' // TRIM(BaseDct%cName)
     873           0 :        CALL HCO_Error( msg, RC, thisLoc )
     874           0 :        RETURN
     875             :     ENDIF
     876             : 
     877             :     ! Initialize mask. By default, assume that we use all grid boxes.
     878           0 :     MASK          = 1.0_hp
     879           0 :     MaskFractions = HcoState%Options%MaskFractions
     880             : 
     881             :     ! Verbose output
     882           0 :     IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
     883           0 :        WRITE(msg,*) 'Evaluate field ', TRIM(BaseDct%cName)
     884           0 :        CALL HCO_Msg( HcoState%Config%Err, msg, sep1=' ' )
     885             :     ENDIF
     886             : 
     887             : #if !defined ( ESMF_ )
     888             :     ! Put check for PBLHEIGHT here, if not running in ESMF/MAPL
     889           0 :     IF ( .NOT. ASSOCIATED( HcoState%Grid%PBLHEIGHT%Val ) ) THEN
     890           0 :        msg = 'PBLHEIGHT (in meters) is missing in HEMCO state'
     891           0 :        CALL HCO_Error( msg, RC, thisLoc )
     892           0 :        RETURN
     893             :     ENDIF
     894             : #endif
     895             : 
     896             :     !========================================================================
     897             :     ! Set base emissions
     898             :     !========================================================================
     899             : 
     900             :     ! Check for level index containers
     901             :     ! Move error checks here, outside of the parallel DO loop
     902             :     ! Remove ELSE blocks for efficiency
     903           0 :     LevDct1 => NULL()
     904           0 :     IF ( BaseDct%levScalID1 > 0 ) THEN
     905           0 :        CALL Pnt2DataCont( HcoState, BaseDct%levScalID1, LevDct1, RC )
     906           0 :        IF ( RC /= HCO_SUCCESS ) THEN
     907           0 :           msg = 'Could not get a pointer to LevDct1 from HcoState!'
     908           0 :           CALL HCO_Error( msg, RC, thisLoc )
     909           0 :           RETURN
     910             :        ENDIF
     911             :     ENDIF
     912             : 
     913           0 :     LevDct2 => NULL()
     914           0 :     IF ( BaseDct%levScalID2 > 0 ) THEN
     915           0 :        CALL Pnt2DataCont( HcoState, BaseDct%levScalID2, LevDct2, RC )
     916           0 :        IF ( RC /= HCO_SUCCESS ) THEN
     917           0 :           msg = 'Could not get a pointer to LevDct2 in HcoState!'
     918           0 :           CALL HCO_Error( msg, RC, thisLoc )
     919           0 :           RETURN
     920             :        ENDIF
     921             :     ENDIF
     922             : 
     923             :     ! Test whether LevDct1 and LevDct2 are associated
     924           0 :     isLevDct1 = ASSOCIATED( LevDct1 )
     925           0 :     isLevDct2 = ASSOCIATED( LevDct2 )
     926             : 
     927             :     ! Get the units of LevDct1 (if it exists)
     928           0 :     LevDct1_Unit = -1
     929           0 :     IF ( isLevDct1 ) THEN
     930           0 :        LevDct1_Unit = GetEmisLUnit( HcoState, LevDct1 )
     931           0 :        IF ( LevDct1_Unit < 0 ) THEN
     932           0 :           MSG = 'LevDct1 units are not defined!'
     933           0 :           CALL HCO_Error( msg, RC, thisLoc )
     934           0 :           RETURN
     935             :        ENDIF
     936             :     ENDIF
     937             : 
     938             :     ! Get the units of LevDct2 (if it exists)
     939           0 :     LevDct2_Unit = -1
     940           0 :     IF ( isLevDct2 ) THEN
     941           0 :        LevDct2_Unit = GetEmisLUnit( HcoState, LevDct2 )
     942           0 :        IF ( LevDct2_Unit < 0 ) THEN
     943           0 :           MSG = 'LevDct2_Units are not defined!'
     944           0 :           CALL HCO_Error( msg, RC, thisLoc )
     945           0 :           RETURN
     946             :        ENDIF
     947             :     ENDIF
     948             : 
     949             :     ! Throw an error if boxheight is missing and the units are in meters
     950           0 :     IF ( LevDct1_Unit == HCO_EMISL_M  .or.                                  &
     951             :          LevDct2_Unit == HCO_EMISL_M ) THEN
     952           0 :        IF ( .not. ASSOCIATED( HcoState%Grid%BXHEIGHT_M%Val ) ) THEN
     953           0 :           MSG = 'Boxheight (in meters) is missing in HEMCO state'
     954           0 :           CALL HCO_Error( msg, RC, thisLoc )
     955           0 :           RETURN
     956             :        ENDIF
     957             :     ENDIF
     958             : 
     959             :     ! Throw an error if boxheight is missing and the units are in PBL frac
     960           0 :     IF ( LevDct1_Unit == HCO_EMISL_PBL  .or.                                &
     961             :          LevDct2_Unit == HCO_EMISL_PBL ) THEN
     962           0 :        IF ( .not. ASSOCIATED( HcoState%Grid%PBLHEIGHT%Val ) ) THEN
     963           0 :           MSG = 'Boundary layer height is missing in HEMCO state'
     964           0 :           CALL HCO_Error( msg, RC, thisLoc )
     965           0 :           RETURN
     966             :        ENDIF
     967             :     ENDIF
     968             : 
     969             :     ! Initialize non-private loop variables here
     970           0 :     error = 0
     971           0 :     totLL = 0.0
     972           0 :     nnLL  = 0.0
     973             : 
     974             :     ! Loop over all latitudes and longitudes
     975             :     !$OMP PARALLEL DO                                                        &
     976             :     !$OMP DEFAULT( SHARED                                                   )&
     977             :     !$OMP PRIVATE( I, J, L, tIdx, tmpVal, LowLL, UppLL, EC                  )&
     978             :     !$OMP REDUCTION( +:totLL                                                )&
     979             :     !$OMP REDUCTION( +:nnLL                                                 )&
     980             :     !$OMP COLLAPSE( 2                                                       )&
     981             :     !$OMP SCHEDULE( DYNAMIC, 8                                              )
     982           0 :     DO J = 1, nJ
     983           0 :     DO I = 1, nI
     984             : 
     985             :        ! Continue to end of loop if an error has occurred
     986             :        ! (we cannot exit from a parallel loop)
     987           0 :        IF ( error > 0 ) CYCLE
     988             : 
     989             :        ! Zero private variables for safety's sake
     990           0 :        tmpVal  = 0.0_hp
     991           0 :        lowLL   = 0
     992           0 :        uppLL   = 0
     993           0 :        EC      = HCO_SUCCESS
     994             : 
     995             :        !---------------------------------------------------------------------
     996             :        ! Get current time index for this container and at this location
     997             :        !---------------------------------------------------------------------
     998           0 :        tIDx = tIDx_GetIndx( HcoState, BaseDct%Dta, I, J )
     999           0 :        IF ( tIDx < 1 ) THEN
    1000           0 :           WRITE( msg, * ) 'Cannot get time slice index at location ',I,J,    &
    1001           0 :                           ': ', TRIM(BaseDct%cName), tIDx
    1002           0 :           error = 1
    1003           0 :           CYCLE
    1004             :        ENDIF
    1005             : 
    1006             :        !---------------------------------------------------------------------
    1007             :        ! Get lower and upper vertical index
    1008             :        !---------------------------------------------------------------------
    1009             :        CALL GetVertIndx( HcoState,     BaseDct,   isLevDct1, LevDct1,        &
    1010             :                          LevDct1_Unit, isLevDct2, LevDct2,   LevDct2_Unit,   &
    1011             :                          I,            J,         LowLL,     UppLL,          &
    1012           0 :                          RC=EC                                              )
    1013             : 
    1014             :        ! Trap error
    1015           0 :        IF ( EC /= HCO_SUCCESS ) THEN
    1016           0 :           WRITE(MSG,*) 'Error getting vertical index at location ',I,J,&
    1017           0 :                        ': ', TRIM(BaseDct%cName)
    1018           0 :           error = 1
    1019           0 :           CYCLE
    1020             :        ENDIF
    1021             : 
    1022             :        !---------------------------------------------------------------------
    1023             :        ! Apply vertical dilution factor (if necessary)
    1024             :        !---------------------------------------------------------------------
    1025             : 
    1026             :        ! Update variables for computing the average level
    1027           0 :        totLL = totLL + UppLL
    1028           0 :        nnLL  = nnLL  + 1
    1029             : 
    1030             :        ! Loop over all levels
    1031           0 :        DO L = LowLL, UppLL
    1032             : 
    1033             :           ! Get base value. Use uniform value if scalar field.
    1034           0 :           tmpVal = Get_Value_From_DataCont( I, J, L, tIdx, BaseDct )
    1035             : 
    1036             :           ! If it's a missing value, mask box as unused
    1037             :           ! and set value to zero.
    1038           0 :           IF ( tmpVal == HCO_MISSVAL ) THEN
    1039           0 :              mask(I,J,:)      = 0.0_hp
    1040           0 :              outArr_3D(I,J,L) = 0.0_hp
    1041           0 :              CYCLE
    1042             :           ENDIF
    1043             : 
    1044             :           ! Otherwise, apply the vertical dilution factor (if necessary)
    1045             :           CALL Apply_Dilution_Factor( I        = I,                          &
    1046             :                                       J        = J,                          &
    1047             :                                       L        = L,                          &
    1048             :                                       LowLL    = LowLL,                      &
    1049             :                                       UppLL    = UppLL,                      &
    1050             :                                       HcoState = HcoState,                   &
    1051             :                                       BaseDct  = BaseDct,                    &
    1052             :                                       inData   = tmpVal,                     &
    1053           0 :                                       outData  = outArr_3D(I,J,L),           &
    1054           0 :                                       RC       = EC                         )
    1055             : 
    1056             :           ! Trap errors
    1057           0 :           IF ( EC /= HCO_SUCCESS ) THEN
    1058           0 :              error = 1
    1059           0 :              msg   = 'Error encountered in routine "Apply_Dilution_Factor"!'
    1060           0 :              CYCLE
    1061             :           ENDIF
    1062             : 
    1063             :        ENDDO !L
    1064             : 
    1065             :     ENDDO !I
    1066             :     ENDDO !J
    1067             :     !$OMP END PARALLEL DO
    1068             : 
    1069             :     !------------------------------------------------------------------------
    1070             :     ! Return if an error occurred in the parallel loop above
    1071             :     !------------------------------------------------------------------------
    1072           0 :     IF ( error == 1 ) THEN
    1073           0 :        CALL HCO_Error( msg, RC, thisLoc )
    1074           0 :        RETURN
    1075             :     ENDIF
    1076             : 
    1077             :     !========================================================================
    1078             :     ! Apply scale factors to base emissions
    1079             :     !
    1080             :     ! The container IDs of all scale factors associated with this base
    1081             :     ! container are stored in vector Scal_cID.
    1082             :     !========================================================================
    1083           0 :     IF ( BaseDct%nScalID > 0 ) THEN
    1084             : 
    1085             :        ! Loop over all scale factors for this base emissions
    1086           0 :        DO N = 1, BaseDct%nScalID
    1087             : 
    1088             :           !------------------------------------------------------------------
    1089             :           ! Get a pointer to the data container holding this scale factor
    1090             :           !------------------------------------------------------------------
    1091             : 
    1092             :           ! Get the Nth scale factor container ID
    1093           0 :           IDX = BaseDct%Scal_cID(N)
    1094             : 
    1095             :           ! Point to data container with the given container ID
    1096           0 :           CALL Pnt2DataCont( HcoState, IDX, ScalDct, RC )
    1097           0 :           IF ( RC /= HCO_SUCCESS ) THEN
    1098             :              msg = 'Could not get scale factor for base emissions field ' // &
    1099           0 :                    TRIM( BaseDct%cName )
    1100           0 :              CALL HCO_Error( msg, RC, thisLoc )
    1101           0 :              RETURN
    1102             :           ENDIF
    1103             : 
    1104             :           ! Sanity check: scale field cannot be a base field
    1105           0 :           IF ( ScalDct%DctType == HCO_DCTTYPE_BASE ) THEN
    1106           0 :              msg = 'Wrong scale field type: ' // TRIM(ScalDct%cName)
    1107           0 :              CALL HCO_Error( msg, RC, thisLoc )
    1108           0 :              RETURN
    1109             :           ENDIF
    1110             : 
    1111             :           !------------------------------------------------------------------
    1112             :           ! Skip this scale factor if no data defined. This is possible
    1113             :           ! if scale factors are only defined for a given time range and
    1114             :           ! the simulation datetime is outside of this range.
    1115             :           !------------------------------------------------------------------
    1116           0 :           IF ( .not. FileData_ArrIsDefined( ScalDct%Dta ) ) THEN
    1117           0 :              IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    1118             :                 msg = 'Skip scale factor ' // TRIM( ScalDct%cName )       // &
    1119           0 :                      ' because it is not defined for this datetime.'
    1120           0 :                 CALL HCO_MSG( HcoState%Config%Err, msg )
    1121             :              ENDIF
    1122             :              CYCLE
    1123             :           ENDIF
    1124             : 
    1125             :           ! Verbose printout
    1126           0 :           IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
    1127           0 :              MSG = 'Applying scale factor ' // TRIM(ScalDct%cName)
    1128           0 :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    1129             :           ENDIF
    1130             : 
    1131             :           !------------------------------------------------------------------
    1132             :           ! Get vertical extension of this scale factor array.
    1133             :           !------------------------------------------------------------------
    1134           0 :           ScalLL = 1
    1135           0 :           IF ( ScalDct%Dta%SpaceDim == 3 ) THEN
    1136           0 :              ScalLL = SIZE( ScalDct%Dta%V3(1)%Val, 3 )
    1137             :           ENDIF
    1138             : 
    1139             :           !------------------------------------------------------------------
    1140             :           ! Check if there is a mask field associated with this scale
    1141             :           ! factor. In this case, get a pointer to the corresponding
    1142             :           ! mask field and evaluate scale factors only inside the mask
    1143             :           ! region.
    1144             :           !------------------------------------------------------------------
    1145           0 :           IF ( ASSOCIATED(ScalDct%Scal_cID) ) THEN
    1146           0 :              CALL Pnt2DataCont( HcoState, ScalDct%Scal_cID(1), MaskDct, RC )
    1147           0 :              IF ( RC /= HCO_SUCCESS ) THEN
    1148             :                 msg = 'Could not get mask field for scale factor: ' //       &
    1149           0 :                       TRIM( ScalDct%cName )
    1150           0 :                 CALL HCO_Error( msg, RC, thisLoc )
    1151           0 :                 RETURN
    1152             :              ENDIF
    1153             : 
    1154             :              ! Sanity check: The data container MaskDct must be a mask!
    1155           0 :              IF ( MaskDct%DctType /= HCO_DCTTYPE_MASK ) THEN
    1156             :                 MSG = 'Invalid mask for scale factor: '                   // &
    1157             :                       TRIM( ScalDct%cName ) // '; mask: '                 // &
    1158           0 :                       TRIM( MaskDct%cName )
    1159           0 :                 CALL HCO_Error( msg, RC, thisLoc )
    1160           0 :                 RETURN
    1161             :              ENDIF
    1162             :           ENDIF
    1163             : 
    1164             :           ! Set a flag to denote whether MaskDct is associated
    1165             :           ! This can be done outside of the parallel loops below
    1166           0 :           isMaskDct = ASSOCIATED( MaskDct )
    1167             : 
    1168             :           !------------------------------------------------------------------
    1169             :           ! Apply the mask to the scale factor
    1170             :           !------------------------------------------------------------------
    1171             : 
    1172             :           ! Reinitialize error flag. Will be set to > 0 if error occurs,
    1173             :           ! and to -1 if negative scale factor is ignored.
    1174           0 :           error = 0
    1175             : 
    1176             :           ! Loop over all latitudes and longitudes
    1177             :           !$OMP PARALLEL DO                                                  &
    1178             :           !$OMP DEFAULT( SHARED                                             )&
    1179             :           !$OMP PRIVATE( I,     J,     tIdx,  tmpVal,    L                  )&
    1180             :           !$OMP PRIVATE( LowLL, UppLL, tmpLL, MaskScale, EC                 )&
    1181             :           !$OMP COLLAPSE( 2                                                 )&
    1182             :           !$OMP SCHEDULE( DYNAMIC, 8                                        )
    1183           0 :           DO J = 1, nJ
    1184           0 :           DO I = 1, nI
    1185             : 
    1186             :              ! Continue to end of loop if an error has occurred
    1187             :              ! (we cannot exit from a parallel loop)
    1188           0 :              IF ( error > 0 ) CYCLE
    1189             : 
    1190             :              !---------------------------------------------------------------
    1191             :              ! If there is a mask associated with this scale factors, check
    1192             :              ! if this grid box is within or outside of the mask region.
    1193             :              ! Values that partially fall into the mask region are either
    1194             :              ! treated as binary (100% inside or outside), or partially
    1195             :              ! (using the real grid area fractions), depending on the
    1196             :              ! HEMCO options.
    1197             :              !---------------------------------------------------------------
    1198             : 
    1199             :              ! Default mask scaling is 1.0 (no mask applied)
    1200           0 :              maskScale = 1.0_sp
    1201             : 
    1202             :              ! If there is a mask applied to this scale factor ...
    1203           0 :              IF ( isMaskDct ) THEN
    1204             :                 CALL GetMaskVal ( MaskDct,   I,             J,               &
    1205           0 :                                   MaskScale, MaskFractions, EC              )
    1206           0 :                 IF ( EC /= HCO_SUCCESS ) THEN
    1207             :                    error = 4
    1208             :                    CYCLE
    1209             :                 ENDIF
    1210             :              ENDIF
    1211             : 
    1212             :              ! We continue an skip this grid box if mask is completely zero
    1213           0 :              IF ( maskScale <= 0.0_sp ) CYCLE
    1214             : 
    1215             :              ! Get current time index for this container and at this location
    1216           0 :              tIDx = tIDx_GetIndx( HcoState, ScalDct%Dta, I, J )
    1217           0 :              IF ( tIDx < 1 ) THEN
    1218           0 :                 WRITE(*,*) 'Cannot get time slice index at location ',I,J,   &
    1219           0 :                            ': ', TRIM(ScalDct%cName), tIDx
    1220           0 :                 error = 3
    1221           0 :                 CYCLE
    1222             :              ENDIF
    1223             : 
    1224             :              !---------------------------------------------------------------
    1225             :              ! Check if this is a mask. If so, add mask values to the MASK
    1226             :              ! array. For now, we assume masks to be binary, i.e. 0 or 1.
    1227             :              ! We may want to change that in future to also support values
    1228             :              ! in between. This is especially important when regridding
    1229             :              ! high resolution masks onto coarser grids!
    1230             :              !---------------------------------------------------------------
    1231           0 :              IF ( ScalDct%DctType == HCO_DCTTYPE_MASK ) THEN
    1232             : 
    1233             :                 ! Get mask value
    1234           0 :                 CALL GetMaskVal( ScalDct, I, J, TMPVAL, MaskFractions, EC )
    1235           0 :                 IF ( EC /= HCO_SUCCESS ) THEN
    1236             :                    error = 4
    1237             :                    CYCLE
    1238             :                 ENDIF
    1239             : 
    1240             :                 ! Pass to output mask
    1241           0 :                 mask(I,J,:) = mask(I,J,:) * TMPVAL
    1242             : 
    1243             :                 ! Verbose printout
    1244             :                 IF ( HCO_IsVerb(HcoState%Config%Err) .and.                   &
    1245           0 :                      I==1 .AND. J==1                       ) THEN
    1246             :                    msg = 'Mask field ' // TRIM( ScalDct%cName )           // &
    1247           0 :                          ' found and added to temporary mask.'
    1248           0 :                    CALL HCO_Msg( HcoState%Config%Err, msg )
    1249             :                 ENDIF
    1250             : 
    1251             :                 ! Advance to next grid box
    1252             :                 CYCLE
    1253             :              ENDIF
    1254             : 
    1255             :              !---------------------------------------------------------------
    1256             :              ! For non-mask fields, apply scale factors to all levels
    1257             :              ! of the base field individually. If the scale factor
    1258             :              ! field has more than one vertical level, use the
    1259             :              ! vertical level closest to the corresponding vertical
    1260             :              ! level of the base emission field
    1261             :              !---------------------------------------------------------------
    1262             : 
    1263             :              ! Get lower and upper vertical index
    1264             :              CALL GetVertIndx( HcoState, BaseDct,       isLevDct1,           &
    1265             :                                LevDct1,  LevDct1_Unit,  isLevDct2,           &
    1266             :                                LevDct2,  LevDct2_Unit,  I,                   &
    1267           0 :                                J,        LowLL,         UppLL,     EC       )
    1268             : 
    1269             :              ! Trap errors
    1270           0 :              IF ( EC /= HCO_SUCCESS ) THEN
    1271             :                 error = 1
    1272             :                 CYCLE
    1273             :              ENDIF
    1274             : 
    1275             :              ! Loop over all vertical levels of the base field
    1276           0 :              DO L = LowLL,UppLL
    1277             : 
    1278             :                 ! If the vertical level exceeds the number of available
    1279             :                 ! scale factor levels, use the highest available level.
    1280             :                 ! Otherwise use the same vertical level index.
    1281           0 :                 TmpLL = L
    1282           0 :                 IF ( L > ScalLL ) TmpLL = ScalLL
    1283             : 
    1284             :                 !------------------------------------------------------------
    1285             :                 ! Get scale factor for this grid box. Use same uniform
    1286             :                 ! value if it's a scalar field.
    1287             :                 !------------------------------------------------------------
    1288           0 :                 tmpVal = Get_Value_From_DataCont( I, J, L, tIdX, ScalDct )
    1289             : 
    1290             :                 ! Set missing value to one
    1291           0 :                 IF ( tmpVal == HCO_MISSVAL ) tmpVal = 1.0_sp
    1292             : 
    1293             :                 ! Eventually apply mask scaling
    1294           0 :                 IF ( maskScale /= 1.0_sp ) THEN
    1295           0 :                    tmpVal = tmpVal * MaskScale
    1296             :                 ENDIF
    1297             : 
    1298             :                 !------------------------------------------------------------
    1299             :                 ! Negative scale factors: proceed according to the "negative
    1300             :                 ! value" setting specified in the HEMCO configuration file
    1301             :                 ! NegFlag = 2: Use this value (i.e. pass thru this IF stmt)
    1302             :                 ! NegFlag = 1: Ignore ands how warning
    1303             :                 ! NegFlag = 0: Return with error
    1304             :                 !------------------------------------------------------------
    1305           0 :                 IF ( tmpVal < 0.0_sp .and. HcoState%Options%NegFlag /= 2 ) THEN
    1306             : 
    1307             :                    ! NegFlag = 1: ignore and show warning
    1308             :                    ! Otherwise return with error
    1309           0 :                    IF ( HcoState%Options%NegFlag == 1 ) THEN
    1310             :                       error = -1
    1311             :                       CYCLE
    1312             :                    ELSE
    1313           0 :                       WRITE( 6, * ) 'Negative scale factor at ',             &
    1314           0 :                                      I, J, TmpLL, tidx, ': ',                &
    1315           0 :                                      TRIM(ScalDct%cName), TMPVAL
    1316           0 :                       error = 1
    1317           0 :                       CYCLE
    1318             :                    ENDIF
    1319             :                 ENDIF
    1320             : 
    1321             :                 !------------------------------------------------------------
    1322             :                 ! Apply scale factor in accordance to field operator
    1323             :                 !------------------------------------------------------------
    1324             :                 CALL Apply_Scale_Factor( I       = I,                        &
    1325             :                                          J       = J,                        &
    1326             :                                          L       = L,                        &
    1327             :                                          ScalDct = ScalDct,                  &
    1328             :                                          scalFac = tmpVal,                   &
    1329           0 :                                          dataVal = outArr_3D(I,J,L),         &
    1330           0 :                                          RC      = EC                       )
    1331             : 
    1332             :                 ! Trap errors
    1333           0 :                 IF ( EC /= HCO_SUCCESS ) THEN
    1334           0 :                    error = 2
    1335           0 :                    CYCLE
    1336             :                 ENDIF
    1337             : 
    1338             :              ENDDO
    1339             : 
    1340             :              !---------------------------------------------------------------
    1341             :              ! Verbose printout
    1342             :              !----------------------------------------------------------------
    1343             :              IF ( HCO_IsVerb(HcoState%Config%Err)  .and.                     &
    1344           0 :                   I == ix .and. J == iy           ) THEN
    1345           0 :                 write(MSG,*) 'Scale field ', TRIM(ScalDct%cName)
    1346           0 :                 CALL HCO_MSG(HcoState%Config%Err,MSG)
    1347           0 :                 write(MSG,*) 'Time slice: ', tIdx
    1348           0 :                 CALL HCO_MSG(HcoState%Config%Err,MSG)
    1349           0 :                 write(MSG,*) 'IX, IY: ', IX, IY
    1350           0 :                 CALL HCO_MSG(HcoState%Config%Err,MSG)
    1351           0 :                 write(MSG,*) 'Scale factor (IX,IY,L1): ', TMPVAL
    1352           0 :                 CALL HCO_MSG(HcoState%Config%Err,MSG)
    1353           0 :                 write(MSG,*) 'Mathematical operation : ', ScalDct%Oper
    1354           0 :                 CALL HCO_MSG(HcoState%Config%Err,MSG)
    1355             :              ENDIF
    1356             : 
    1357             :           ENDDO !I
    1358             :           ENDDO !J
    1359             :           !$OMP END PARALLEL DO
    1360             : 
    1361             :           !------------------------------------------------------------------
    1362             :           ! Return with error if an error was encountered in the loop above
    1363             :           !------------------------------------------------------------------
    1364           0 :           IF ( error > 0 ) THEN
    1365             : 
    1366             :              ! Construct the appropriate error message
    1367           0 :              SELECT CASE( error )
    1368             :                 CASE( 1 )
    1369           0 :                    msg = 'Negative scale factor found (aborted): '
    1370             :                 CASE( 2 )
    1371           0 :                    msg = 'Illegal mathematical operator for scale factor: '
    1372             :                 CASE( 3 )
    1373           0 :                    msg = 'Encountered negative time index for scale factor: '
    1374             :                 CASE( 4 )
    1375           0 :                    msg = 'Error applying mask to scale factor: '
    1376             :                 CASE DEFAULT
    1377           0 :                    msg = 'Error when applying scale factor: '
    1378             :              END SELECT
    1379             : 
    1380             :              ! Append name of scale factor to error message
    1381           0 :              msg = TRIM( msg ) // TRIM( ScalDct%cName )
    1382             : 
    1383             :              ! Exit with error message
    1384           0 :              ScalDct => NULL()
    1385           0 :              CALL HCO_Error( msg, RC, thisLoc )
    1386           0 :              RETURN
    1387             :           ENDIF
    1388             : 
    1389             :           ! eventually prompt warning for negative values
    1390           0 :           IF ( ERROR == -1 ) THEN
    1391             :              msg = 'Negative scale factor found (ignored): '              // &
    1392           0 :                     TRIM( ScalDct%cName )
    1393           0 :              CALL HCO_WARNING( HcoState%Config%Err, msg, RC )
    1394             :           ENDIF
    1395             : 
    1396             :           ! Free pointer
    1397           0 :           MaskDct => NULL()
    1398             : 
    1399             :        ENDDO ! N
    1400             :     ENDIF    ! N > 0
    1401             : 
    1402             :     !========================================================================
    1403             :     ! Update optional variables
    1404             :     !========================================================================
    1405           0 :     IF ( PRESENT( UseLL) ) THEN
    1406           0 :        UseLL = 1
    1407           0 :        IF ( nnLL > 0 ) UseLL = NINT(REAL(TotLL,kind=sp)/REAL(nnLL,kind=sp))
    1408             :     ENDIF
    1409             : 
    1410             :     ! Weight output emissions by mask
    1411           0 :     outArr_3D = outArr_3D * mask
    1412             : 
    1413             :     ! Cleanup and leave w/ success
    1414           0 :     ScalDct => NULL()
    1415           0 :     CALL HCO_Leave( HcoState%Config%Err, RC )
    1416             : 
    1417             :   END SUBROUTINE Get_Current_Emissions
    1418             : !EOC
    1419             : !------------------------------------------------------------------------------
    1420             : !                  GEOS-Chem Global Chemical Transport Model                  !
    1421             : !------------------------------------------------------------------------------
    1422             : !BOP
    1423             : !
    1424             : ! !IROUTINE: Get_Value_From_DataCont
    1425             : !
    1426             : ! !DESCRIPTION: Returns a data value stored in a data container at a given
    1427             : !  grid box and time.
    1428             : !\\
    1429             : !\\
    1430             : ! !INTERFACE:
    1431             : !
    1432           0 :   FUNCTION Get_Value_From_DataCont( I, J, L, tIdx, Dct ) RESULT( dataVal )
    1433             : !
    1434             : ! !INPUT PARAMETERS:
    1435             : !
    1436             :     INTEGER,        INTENT(IN) :: I        ! Longitude (or X-dim) index
    1437             :     INTEGER,        INTENT(IN) :: J        ! Latitude  (or Y-dim) index
    1438             :     INTEGER,        INTENT(IN) :: L        ! Vertical level index
    1439             :     INTEGER,        INTENT(IN) :: tIdx     ! Time index
    1440             :     TYPE(DataCont), POINTER    :: Dct      ! Data Container object
    1441             : !
    1442             : ! !RETURN VALUE:
    1443             : !
    1444             :     REAL(sp)                   :: dataVal  ! Data at this grid box and time
    1445             : !
    1446             : ! !REMARKS:
    1447             : !  This code was abstracted out of Get_Current_Emisssions for clarity.
    1448             : !  We have refactored the code to remove ELSE blocks for better efficiency.
    1449             : !EOP
    1450             : !------------------------------------------------------------------------------
    1451             : !BOC
    1452             : 
    1453             :     ! Data is a 1-D scaler: Return a uniform value
    1454           0 :     IF ( Dct%Dta%SpaceDim == 1 ) THEN
    1455           0 :        dataVal = Dct%Dta%V2(tIDx)%Val(1,1)
    1456           0 :        RETURN
    1457             :     ENDIF
    1458             : 
    1459             :     ! Data is a 2-D array: Return value at (I,J)
    1460           0 :     IF ( Dct%Dta%SpaceDim == 2 ) THEN
    1461           0 :        dataVal = Dct%Dta%V2(tIDx)%Val(I,J)
    1462           0 :        RETURN
    1463             :     ENDIF
    1464             : 
    1465             :     ! Data is a 3-D array: Return value at (I,J,L)
    1466           0 :     dataVal = Dct%Dta%V3(tIDx)%Val(I,J,L)
    1467             : 
    1468           0 :   END FUNCTION Get_Value_From_DataCont
    1469             : !EOC
    1470             : !------------------------------------------------------------------------------
    1471             : !                  GEOS-Chem Global Chemical Transport Model                  !
    1472             : !------------------------------------------------------------------------------
    1473             : !BOP
    1474             : !
    1475             : ! !IROUTINE: Apply_Dilution_Factor
    1476             : !
    1477             : ! !DESCRIPTION: Applies the dilution factor to input data.  This algorithm
    1478             : !  has been abstracted out of Get_Current_Emissions for computational
    1479             : !  efficiency.
    1480             : !\\
    1481             : !\\
    1482             : ! !INTERFACE:
    1483             : !
    1484           0 :   SUBROUTINE Apply_Dilution_Factor( I,       J,         L,      LowLL,       &
    1485             :                                     UppLL,   HcoState, BaseDct, inData,      &
    1486             :                                     outData, RC                             )
    1487             : !
    1488             : ! !USES:
    1489             : !
    1490             :     USE HCO_Error_Mod
    1491             :     USE HCO_State_Mod, ONLY : HCO_State
    1492             : !
    1493             : ! !INPUT PARAMETERS:
    1494             : !
    1495             :     INTEGER,         INTENT(IN)    :: I         ! Longitude (or X-dim) index
    1496             :     INTEGER,         INTENT(IN)    :: J         ! Latitude  (or Y-dim) index
    1497             :     INTEGER,         INTENT(IN)    :: L         ! Vertical level index
    1498             :     INTEGER,         INTENT(IN)    :: LowLL     ! Lower level for emissions
    1499             :     INTEGER,         INTENT(IN)    :: UppLL     ! Upper level for emissions
    1500             :     TYPE(DataCont),  POINTER       :: BaseDct   ! Base data container
    1501             :     REAL(sp),        INTENT(IN)    :: inData    ! Input data
    1502             : !
    1503             : ! !INPUT/OUTPUT PARAMETERS:
    1504             : !
    1505             :     TYPE(HCO_State), POINTER       :: HcoState  ! HEMCO state object
    1506             :     REAL(hp),        INTENT(INOUT) :: outData   ! Data w/ dil. factor applied
    1507             : !
    1508             : ! !OUTPUT PARAMETERS:
    1509             : !
    1510             :     INTEGER,         INTENT(OUT)   :: RC        ! Success or failure
    1511             : !
    1512             : !
    1513             : ! !REMARKS:
    1514             : !  This code was abstracted out of Get_Current_Emisssions for clarity.  We
    1515             : !  have also refactored the code to remove ELSE blocks for better efficiency.
    1516             : !EOP
    1517             : !------------------------------------------------------------------------------
    1518             : !BOC
    1519             : !
    1520             : ! !LOCAL VARIABLES:
    1521             : !
    1522             :     ! Scalars
    1523             :     REAL(hp)           :: dilFact
    1524             : 
    1525             :     ! Strings
    1526             :     CHARACTER(LEN=255) :: errMsg, thisLoc
    1527             : 
    1528             :     !========================================================================
    1529             :     ! Apply_Dilution_Factor begins here!
    1530             :     !========================================================================
    1531             : 
    1532             :     ! Initialize
    1533           0 :     RC      = HCO_SUCCESS
    1534           0 :     errMsg  = ''
    1535           0 :     thisLoc = 'Apply_Dilution_Factor (in src/Core/hco_calc_mod.F90)'
    1536           0 :     dilFact = 0.0_hp
    1537             : 
    1538             :     !========================================================================
    1539             :     ! Get dilution factor. Never dilute 3D emissions.
    1540             :     !========================================================================
    1541           0 :     IF ( BaseDct%Dta%SpaceDim == 3 ) THEN
    1542           0 :        outData = inData
    1543           0 :        RETURN
    1544             :     ENDIF
    1545             : 
    1546             :     !========================================================================
    1547             :     ! If emission level mode is 2, copy emissions to all level
    1548             :     ! A separate scale factor should be used to distribute vertically
    1549             :     !========================================================================
    1550           0 :     IF ( BaseDct%Dta%EmisLmode == 2 ) THEN
    1551           0 :        outData = inData
    1552           0 :        RETURN
    1553             :     ENDIF
    1554             : 
    1555             :     !========================================================================
    1556             :     ! Otherwise, compute the vertical dilution factor
    1557             :     ! and apply it to the input data.
    1558             :     !========================================================================
    1559             :     CALL GetDilFact( I          = I,                                         &
    1560             :                      J          = J,                                         &
    1561             :                      L          = L,                                         &
    1562             :                      LowLL      = LowLL,                                     &
    1563             :                      UppLL      = UppLL,                                     &
    1564             :                      HcoState   = HcoState,                                  &
    1565             :                      EmisL1     = BaseDct%Dta%EmisL1,                        &
    1566             :                      EmisL1Unit = BaseDct%Dta%EmisL1Unit,                    &
    1567             :                      EmisL2     = BaseDct%Dta%EmisL2,                        &
    1568             :                      EmisL2Unit = BaseDct%Dta%EmisL2Unit,                    &
    1569             :                      DilFact    = dilFact,                                   &
    1570           0 :                      RC         = RC                                        )
    1571             : 
    1572             :     ! Trap error
    1573           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    1574           0 :        WRITE(*,*) 'Error getting dilution factor at ',I,J,&
    1575           0 :             ': ', TRIM(BaseDct%cName)
    1576           0 :        RC = 1
    1577           0 :        RETURN
    1578             :     ENDIF
    1579             : 
    1580             :     ! Scale base emission by dilution factor
    1581           0 :     outData = dilFact * inData
    1582             : 
    1583             :   END SUBROUTINE Apply_Dilution_Factor
    1584             : !EOC
    1585             : !------------------------------------------------------------------------------
    1586             : !                  GEOS-Chem Global Chemical Transport Model                  !
    1587             : !------------------------------------------------------------------------------
    1588             : !BOP
    1589             : !
    1590             : ! !IROUTINE: Apply_Scale_Factor
    1591             : !
    1592             : ! !DESCRIPTION: Applies scale factors to the input
    1593             : !\\
    1594             : !\\
    1595             : ! !INTERFACE:
    1596             : !
    1597           0 :   SUBROUTINE Apply_Scale_Factor( I, J, L, ScalDct, scalFac, dataVal, RC )
    1598             : !
    1599             : ! !USES:
    1600             : !
    1601             :     USE HCO_Error_Mod
    1602             : !
    1603             : ! !INPUT PARAMETERS:
    1604             : !
    1605             :     INTEGER,        INTENT(IN)    :: I        ! Longitude (or X-dim) index
    1606             :     INTEGER,        INTENT(IN)    :: J        ! Latitude  (or Y-dim) index
    1607             :     INTEGER,        INTENT(IN)    :: L        ! Vertical level index
    1608             :     TYPE(DataCont), POINTER       :: ScalDct  ! Scale Factor data container
    1609             :     REAL(sp),       INTENT(IN)    :: scalFac  ! Scale factor
    1610             : !
    1611             : ! !INPUT/OUTPUT PARAMETERS:
    1612             : !
    1613             :     REAL(hp),       INTENT(INOUT) :: dataVal  ! Data to be scaled
    1614             : !
    1615             : ! !OUTPUT PARAMETERS:
    1616             : !
    1617             :     INTEGER,        INTENT(OUT)   :: RC       ! Success or failure
    1618             : !
    1619             : ! !REMARKS:
    1620             : !  This code was abstracted out of Get_Current_Emisssions for clarity.  We
    1621             : !  have also refactored the code to remove ELSE blocks for better efficiency.
    1622             : !EOP
    1623             : !------------------------------------------------------------------------------
    1624             : !BOC
    1625             : !
    1626             : ! !LOCAL VARIABLES:
    1627             : !
    1628             :     ! Strings
    1629             :     CHARACTER(LEN=255) :: errMsg, thisLoc
    1630             : 
    1631             :     !========================================================================
    1632             :     ! Apply_Scale_Factor begins here!
    1633             :     !========================================================================
    1634             : 
    1635             :     ! Initialize
    1636           0 :     RC      = HCO_SUCCESS
    1637           0 :     errMsg  = ''
    1638           0 :     thisLoc = 'Apply_Scale_Factor (src/Core/hco_calc_mod.F90)'
    1639             : 
    1640             :     !------------------------------------------------------------------------
    1641             :     ! Operation = 1: multiply
    1642             :     !------------------------------------------------------------------------
    1643           0 :     IF ( ScalDct%Oper == 1 ) THEN
    1644           0 :        dataVal = dataVal * scalFac
    1645           0 :        RETURN
    1646             :     ENDIF
    1647             : 
    1648             :     !------------------------------------------------------------------------
    1649             :     ! Operation = -1: divide
    1650             :     !------------------------------------------------------------------------
    1651           0 :     IF ( ScalDct%Oper == -1 ) THEN
    1652           0 :        IF ( scalFac /= 0.0_sp ) THEN
    1653           0 :            dataVal = dataVal / scalFac
    1654             :        ENDIF
    1655           0 :        RETURN
    1656             :     ENDIF
    1657             : 
    1658             :     !------------------------------------------------------------------------
    1659             :     ! Operation = 2: square
    1660             :     !------------------------------------------------------------------------
    1661           0 :     IF ( ScalDct%Oper == 2 ) THEN
    1662           0 :        dataVal = dataVal * scalFac * scalFac
    1663           0 :        RETURN
    1664             :     ENDIF
    1665             : 
    1666             :     !------------------------------------------------------------------------
    1667             :     ! Return w/ error otherwise (Oper 3 is only allowed for masks!)
    1668             :     !------------------------------------------------------------------------
    1669           0 :     WRITE( errMsg, * ) 'Illegal operator for: ', TRIM( ScalDct%cName ),      &
    1670           0 :                        ' operation: ', ScalDct%Oper
    1671           0 :     CALL HCO_Error( ErrMsg, RC, thisLoc )
    1672           0 :     RC = 2
    1673             : 
    1674             :   END SUBROUTINE Apply_Scale_Factor
    1675             : !EOC
    1676             : !------------------------------------------------------------------------------
    1677             : !                   Harmonized Emissions Component (HEMCO)                    !
    1678             : !------------------------------------------------------------------------------
    1679             : !BOP
    1680             : !
    1681             : ! !IROUTINE: HCO_EvalFld_3D
    1682             : !
    1683             : ! !DESCRIPTION: Subroutine HCO\_EvalFld\_3D returns the 3D data field belonging
    1684             : !  to the emissions list data container with field name 'cName'. The returned
    1685             : !  data field is the completely evaluated field, e.g. the base field multiplied
    1686             : !  by all scale factors and with all masking being applied (as specified in the
    1687             : !  HEMCO configuration file). This distinguished this routine from HCO\_GetPtr
    1688             : !  in hco\_emislist\_mod.F90, which returns a reference to the unevaluated data
    1689             : !  field.
    1690             : !\\
    1691             : !\\
    1692             : ! !INTERFACE:
    1693             : !
    1694           0 :   SUBROUTINE HCO_EvalFld_3D( HcoState, cName, Arr3D, RC, FOUND )
    1695             : !
    1696             : ! !USES:
    1697             : !
    1698             :     USE HCO_STATE_MOD,    ONLY : HCO_State
    1699             :     USE HCO_DATACONT_MOD, ONLY : ListCont_Find
    1700             : !
    1701             : ! !INPUT PARAMETERS:
    1702             : !
    1703             :     CHARACTER(LEN=*), INTENT(IN   )  :: cName
    1704             : !
    1705             : ! !INPUT/OUTPUT PARAMETERS:
    1706             : !
    1707             :     TYPE(HCO_State),  POINTER        :: HcoState     ! HEMCO state object
    1708             :     REAL(hp),         INTENT(INOUT)  :: Arr3D(:,:,:) ! 3D array
    1709             :     INTEGER,          INTENT(INOUT)  :: RC           ! Return code
    1710             : !
    1711             : ! !OUTPUT PARAMETERS:
    1712             : !
    1713             :     LOGICAL,          INTENT(  OUT), OPTIONAL  :: FOUND
    1714             : !
    1715             : ! !REVISION HISTORY:
    1716             : !  11 May 2015 - C. Keller   - Initial Version
    1717             : !  See https://github.com/geoschem/hemco for complete history
    1718             : !EOP
    1719             : !------------------------------------------------------------------------------
    1720             : !BOC
    1721             : !
    1722             : ! !LOCAL VARIABLES:
    1723             : !
    1724             :     ! Scalars
    1725             :     LOGICAL                 :: FND
    1726             :     INTEGER                 :: AS, nI, nJ, nL, FLAG
    1727             : 
    1728             :     ! Arrays
    1729           0 :     REAL(hp), ALLOCATABLE   :: Mask(:,:,:)
    1730             : 
    1731             :     ! Working pointers: list and data container
    1732             :     TYPE(ListCont), POINTER :: Lct
    1733             : 
    1734             :     ! For error handling & verbose mode
    1735             :     CHARACTER(LEN=255)      :: MSG
    1736             :     CHARACTER(LEN=255)      :: LOC = "HCO_EvalFld_3d (HCO_calc_mod.F90)"
    1737             : 
    1738             :     !=================================================================
    1739             :     ! HCO_EvalFld_3D begins here!
    1740             :     !=================================================================
    1741             : 
    1742             :     ! Init
    1743           0 :     RC    = HCO_SUCCESS
    1744           0 :     Lct   => NULL()
    1745           0 :     IF ( PRESENT(FOUND) ) FOUND = .FALSE.
    1746             : 
    1747             :     ! Search for base container
    1748           0 :     CALL ListCont_Find ( HcoState%EmisList, TRIM(cName), FND, Lct )
    1749           0 :     IF ( PRESENT(FOUND) ) FOUND = FND
    1750             : 
    1751             :     ! If not found, return here
    1752           0 :     IF ( .NOT. FND ) THEN
    1753           0 :        IF ( PRESENT(FOUND) ) THEN
    1754           0 :           RETURN
    1755             :        ELSE
    1756           0 :           MSG = 'Cannot find in EmisList: ' // TRIM(cName)
    1757           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    1758           0 :           RETURN
    1759             :        ENDIF
    1760             :     ENDIF
    1761             : 
    1762             :     ! Init
    1763           0 :     Arr3D = 0.0_hp
    1764             : 
    1765             :     ! Define output dimensions
    1766           0 :     nI = SIZE(Arr3D,1)
    1767           0 :     nJ = SIZE(Arr3D,2)
    1768           0 :     nL = SIZE(Arr3D,3)
    1769             : 
    1770             :     ! Sanity check: horizontal grid dimensions are expected to be on HEMCO grid
    1771           0 :     IF ( nI /= HcoState%NX .OR. nJ /= HcoState%nY ) THEN
    1772           0 :        WRITE(MSG,*) "Horizontal dimension error: ", TRIM(cName), nI, nJ
    1773           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    1774           0 :        RETURN
    1775             :     ENDIF
    1776             : 
    1777             :     ! Make sure mask array is defined
    1778           0 :     ALLOCATE(MASK(nI,nJ,nL),STAT=AS)
    1779           0 :     IF ( AS /= 0 ) THEN
    1780           0 :        CALL HCO_ERROR( 'Cannot allocate MASK', RC, THISLOC=LOC )
    1781           0 :        RETURN
    1782             :     ENDIF
    1783           0 :     mask = 0.0_hp
    1784             : 
    1785             :     ! Calculate emissions for base container
    1786             :     CALL GET_CURRENT_EMISSIONS( HcoState, Lct%Dct, nI,   nJ,                 &
    1787           0 :                                 nL,       Arr3D,   Mask, RC                 )
    1788           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    1789           0 :         CALL HCO_ERROR( 'ERROR 14', RC, THISLOC=LOC )
    1790           0 :         RETURN
    1791             :     ENDIF
    1792             : 
    1793             :     ! All done
    1794           0 :     IF (ALLOCATED(MASK) ) DEALLOCATE(MASK)
    1795           0 :     Lct => NULL()
    1796             : 
    1797           0 :   END SUBROUTINE HCO_EvalFld_3D
    1798             : !EOC
    1799             : !------------------------------------------------------------------------------
    1800             : !                   Harmonized Emissions Component (HEMCO)                    !
    1801             : !------------------------------------------------------------------------------
    1802             : !BOP
    1803             : !
    1804             : ! !IROUTINE: HCO_EvalFld_2D
    1805             : !
    1806             : ! !DESCRIPTION: Subroutine HCO\_EvalFld\_2D returns the 2D data field belonging
    1807             : !  to the emissions list data container with field name 'cName'. The returned
    1808             : !  data field is the completely evaluated field, e.g. the base field multiplied
    1809             : !  by all scale factors and with all masking being applied (as specified in the
    1810             : !  HEMCO configuration file). This distinguished this routine from HCO\_GetPtr
    1811             : !  in hco\_emislist\_mod.F90, which returns a reference to the unevaluated data
    1812             : !  field.
    1813             : !\\
    1814             : !\\
    1815             : !\\
    1816             : ! !INTERFACE:
    1817             : !
    1818           0 :   SUBROUTINE HCO_EvalFld_2D( HcoState, cName, Arr2D, RC, FOUND )
    1819             : !
    1820             : ! !USES:
    1821             : !
    1822             :     USE HCO_STATE_MOD,    ONLY : HCO_State
    1823             :     USE HCO_DATACONT_MOD, ONLY : ListCont_Find
    1824             : !
    1825             : ! !INPUT PARAMETERS:
    1826             : !
    1827             :     CHARACTER(LEN=*), INTENT(IN   )  :: cName
    1828             : !
    1829             : ! !INPUT/OUTPUT PARAMETERS:
    1830             : !
    1831             :     TYPE(HCO_State),  POINTER        :: HcoState     ! HEMCO state object
    1832             :     REAL(hp),         INTENT(INOUT)  :: Arr2D(:,:)   ! 2D array
    1833             :     INTEGER,          INTENT(INOUT)  :: RC           ! Return code
    1834             : !
    1835             : ! !OUTPUT PARAMETERS:
    1836             : !
    1837             :     LOGICAL,          INTENT(  OUT), OPTIONAL  :: FOUND
    1838             : !
    1839             : ! !REVISION HISTORY:
    1840             : !  11 May 2015 - C. Keller   - Initial Version
    1841             : !  See https://github.com/geoschem/hemco for complete history
    1842             : !EOP
    1843             : !------------------------------------------------------------------------------
    1844             : !BOC
    1845             : !
    1846             : ! !LOCAL VARIABLES:
    1847             : !
    1848             :     ! Scalars
    1849             :     LOGICAL                 :: FND
    1850             :     INTEGER                 :: AS, nI, nJ, nL, UseLL, FLAG
    1851             : 
    1852             :     ! Arrays
    1853           0 :     REAL(hp), ALLOCATABLE   :: Mask (:,:,:)
    1854           0 :     REAL(hp), ALLOCATABLE   :: Arr3D(:,:,:)
    1855             : 
    1856             :     ! Working pointers: list and data container
    1857             :     TYPE(ListCont), POINTER :: Lct
    1858             : 
    1859             :     ! For error handling & verbose mode
    1860             :     CHARACTER(LEN=255)      :: MSG
    1861             :     CHARACTER(LEN=255)      :: LOC = "HCO_EvalFld_2d (HCO_calc_mod.F90)"
    1862             : 
    1863             :     !=================================================================
    1864             :     ! HCO_EvalFld_2D begins here!
    1865             :     !=================================================================
    1866             : 
    1867             :     ! Init
    1868           0 :     RC    = HCO_SUCCESS
    1869           0 :     Lct   => NULL()
    1870           0 :     IF ( PRESENT(FOUND) ) FOUND = .FALSE.
    1871             : 
    1872             :     ! Search for base container
    1873           0 :     CALL ListCont_Find ( HcoState%EmisList, TRIM(cName), FND, Lct )
    1874           0 :     IF ( PRESENT(FOUND) ) FOUND = FND
    1875             : 
    1876             :     ! If not found, return here
    1877           0 :     IF ( .NOT. FND ) THEN
    1878           0 :        IF ( PRESENT(FOUND) ) THEN
    1879           0 :           RETURN
    1880             :        ELSE
    1881           0 :           MSG = 'Cannot find in EmisList: ' // TRIM(cName)
    1882           0 :           CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    1883           0 :           RETURN
    1884             :        ENDIF
    1885             :     ENDIF
    1886             : 
    1887             :     ! Init Arr2D
    1888           0 :     Arr2D = 0.0_hp
    1889             : 
    1890             :     ! Define output dimensions
    1891           0 :     nI = SIZE(Arr2D,1)
    1892           0 :     nJ = SIZE(Arr2D,2)
    1893           0 :     nL = 1
    1894             : 
    1895             :     ! Sanity check: horizontal grid dimensions are expected to be on HEMCO grid
    1896           0 :     IF ( nI /= HcoState%NX .OR. nJ /= HcoState%nY ) THEN
    1897           0 :        WRITE(MSG,*) "Horizontal dimension error: ", TRIM(cName), nI, nJ
    1898           0 :        CALL HCO_ERROR( MSG, RC, THISLOC=LOC )
    1899           0 :        RETURN
    1900             :     ENDIF
    1901             : 
    1902             :     ! Make sure mask array is defined
    1903           0 :     ALLOCATE(MASK(nI,nJ,nL),Arr3D(nI,nJ,nL),STAT=AS)
    1904           0 :     IF ( AS /= 0 ) THEN
    1905           0 :        CALL HCO_ERROR( 'Cannot allocate MASK', RC, THISLOC=LOC )
    1906           0 :        RETURN
    1907             :     ENDIF
    1908           0 :     Arr3D = 0.0_hp
    1909           0 :     Mask  = 0.0_hp
    1910             : 
    1911             :     ! Calculate emissions for base container
    1912             :     CALL GET_CURRENT_EMISSIONS( HcoState, Lct%Dct, nI,   nJ,                 &
    1913           0 :                                 nL,       Arr3D,   Mask, RC, UseLL=UseLL    )
    1914           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    1915           0 :         CALL HCO_ERROR( 'ERROR 15', RC, THISLOC=LOC )
    1916           0 :         RETURN
    1917             :     ENDIF
    1918             : 
    1919             :     ! Place 3D array into 2D array. UseLL returns the vertical level into which
    1920             :     ! emissions have been added within GET_CURRENT_EMISSIONS. This should be
    1921             :     ! level 1 for most cases but it can be another level if specified so.
    1922             :     ! Return a warning if level is not 1 (ckeller, 11/1/16).
    1923           0 :     UseLL = MIN( MAX(useLL,1), SIZE(Arr3D,3) )
    1924           0 :     IF ( UseLL /= 1 ) THEN
    1925           0 :        WRITE(MSG,*) "2D data was emitted above surface - this information might be lost: " , TRIM(cName), UseLL
    1926           0 :        CALL HCO_WARNING( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    1927             :     ENDIF
    1928             : 
    1929             :     ! Pass 3D data to 2D array
    1930           0 :     Arr2D = Arr3D(:,:,UseLL)
    1931             : 
    1932             :     ! All done
    1933           0 :     IF (ALLOCATED(MASK ) ) DEALLOCATE(MASK )
    1934           0 :     IF (ALLOCATED(Arr3D) ) DEALLOCATE(Arr3D)
    1935           0 :     Lct => NULL()
    1936             : 
    1937           0 :   END SUBROUTINE HCO_EvalFld_2D
    1938             : !EOC
    1939             : !------------------------------------------------------------------------------
    1940             : !                   Harmonized Emissions Component (HEMCO)                    !
    1941             : !------------------------------------------------------------------------------
    1942             : !BOP
    1943             : !
    1944             : ! !IROUTINE: GetMaskVal
    1945             : !
    1946             : ! !DESCRIPTION: Subroutine GetMaskVal is a helper routine to get the mask
    1947             : !  value at a given location.
    1948             : !\\
    1949             : !\\
    1950             : ! !INTERFACE:
    1951             : !
    1952           0 :   SUBROUTINE GetMaskVal ( Dct, I, J, MaskVal, Fractions, RC )
    1953             : !
    1954             : ! !USES:
    1955             : !
    1956             : !
    1957             : ! !INPUT PARAMETERS:
    1958             : !
    1959             :     INTEGER,         INTENT(IN   ) :: I                   ! # of lons
    1960             :     INTEGER,         INTENT(IN   ) :: J                   ! # of lats
    1961             :     LOGICAL,         INTENT(IN   ) :: Fractions           ! Use fractions?
    1962             : !
    1963             : ! !INPUT/OUTPUT PARAMETERS:
    1964             : !
    1965             :     TYPE(DataCont),  POINTER       :: Dct                 ! Mask container
    1966             :     REAL(sp),        INTENT(INOUT) :: MaskVal
    1967             :     INTEGER,         INTENT(INOUT) :: RC
    1968             : !
    1969             : ! !REVISION HISTORY:
    1970             : !  09 Apr 2015 - C. Keller   - Initial Version
    1971             : !  See https://github.com/geoschem/hemco for complete history
    1972             : !EOP
    1973             : !------------------------------------------------------------------------------
    1974             : !BOC
    1975             : !
    1976             : ! !LOCAL VARIABLES:
    1977             : !
    1978             : 
    1979             :     !=================================================================
    1980             :     ! GetMaskVal begins here
    1981             :     !=================================================================
    1982             : 
    1983             :     ! Mask value over this grid box
    1984           0 :     MaskVal = Dct%Dta%V2(1)%Val(I,J)
    1985             : 
    1986             :     ! Negative mask values are treated as zero (exclude).
    1987           0 :     IF ( (MaskVal <= 0.0_sp) .OR. (MaskVal == HCO_MISSVAL) ) THEN
    1988           0 :        MaskVal = 0.0_sp
    1989           0 :     ELSEIF ( MaskVal > 1.0_sp ) THEN
    1990           0 :        MaskVal = 1.0_sp
    1991             :     ENDIF
    1992             : 
    1993             :     ! For operator set to 3, mirror value
    1994             :     ! MaskVal=1 becomes 0 and MaskVal=0/missing becomes 1
    1995           0 :     IF ( Dct%Oper == 3 ) THEN
    1996           0 :        IF ( (MaskVal == 0.0_sp) .OR. (MaskVal == HCO_MISSVAL) ) THEN
    1997           0 :           MaskVal = 1.0_sp
    1998           0 :        ELSEIF ( MaskVal == 1.0_sp ) THEN
    1999           0 :           MaskVal = 1.0_sp - MaskVal
    2000             :        ENDIF
    2001             :     ENDIF
    2002             : 
    2003             :     ! Treat as binary?
    2004           0 :     IF ( .NOT. Fractions ) THEN
    2005           0 :        IF ( MaskVal < MASK_THRESHOLD ) THEN
    2006           0 :           MaskVal = 0.0_sp
    2007             :        ELSE
    2008           0 :           MaskVal = 1.0_sp
    2009             :        ENDIF
    2010             :     ENDIF
    2011             : 
    2012             :     ! Return w/ success
    2013           0 :     RC = HCO_SUCCESS
    2014             : 
    2015           0 :   END SUBROUTINE GetMaskVal
    2016             : !EOC
    2017             : !------------------------------------------------------------------------------
    2018             : !                   Harmonized Emissions Component (HEMCO)                    !
    2019             : !------------------------------------------------------------------------------
    2020             : !BOP
    2021             : !
    2022             : ! !IROUTINE: HCO_MaskFld
    2023             : !
    2024             : ! !DESCRIPTION: Subroutine HCO\_MaskFld is a helper routine to get the mask
    2025             : ! field with the given name. The returned mask field is fully evaluated,
    2026             : ! e.g. the data operation flag associated with this mask field is already
    2027             : ! taken into account. For instance, if the data operator of a mask field is
    2028             : ! set to 3, the returned array contains already the mirrored mask values.
    2029             : !\\
    2030             : !\\
    2031             : ! !INTERFACE:
    2032             : !
    2033           0 :   SUBROUTINE HCO_MaskFld ( HcoState, MaskName, Mask, RC, FOUND )
    2034             : !
    2035             : ! !USES:
    2036             : !
    2037             :     USE HCO_STATE_MOD,    ONLY : HCO_State
    2038             :     USE HCO_DATACONT_MOD, ONLY : ListCont_Find
    2039             : !
    2040             : ! !INPUT PARAMETERS:
    2041             : !
    2042             :     TYPE(HCO_STATE), POINTER                 :: HcoState
    2043             :     CHARACTER(LEN=*),INTENT(IN   )           :: MaskName
    2044             : !
    2045             : ! !INPUT/OUTPUT PARAMETERS:
    2046             : !
    2047             :     REAL(sp),        INTENT(INOUT)           :: Mask(:,:)
    2048             :     INTEGER,         INTENT(INOUT)           :: RC
    2049             : !
    2050             : ! !OUTPUT PARAMETERS:
    2051             : !
    2052             :     LOGICAL,         INTENT(  OUT), OPTIONAL :: FOUND
    2053             : !
    2054             : ! !REVISION HISTORY:
    2055             : !  11 Jun 2015 - C. Keller   - Initial Version
    2056             : !  See https://github.com/geoschem/hemco for complete history
    2057             : !EOP
    2058             : !------------------------------------------------------------------------------
    2059             : !BOC
    2060             : !
    2061             : ! !LOCAL VARIABLES:
    2062             : !
    2063             :     INTEGER                 :: I, J, FLAG
    2064             : 
    2065             :     LOGICAL                 :: FND, ERR
    2066             :     LOGICAL                 :: Fractions
    2067             : 
    2068             :     TYPE(ListCont), POINTER :: MaskLct
    2069             : 
    2070             :     CHARACTER(LEN=255)      :: MSG
    2071             :     CHARACTER(LEN=255)      :: LOC = 'HCO_MaskFld (hco_calc_mod.F90)'
    2072             : 
    2073             :     !=================================================================
    2074             :     ! HCO_MaskFld begins here
    2075             :     !=================================================================
    2076             : 
    2077             :     ! Nullify
    2078           0 :     MaskLct  => NULL()
    2079             : 
    2080             :     ! Init: default is mask value of 1
    2081           0 :     MASK = 1.0_sp
    2082           0 :     ERR  = .FALSE.
    2083           0 :     FND  = .FALSE.
    2084             : 
    2085             :     ! Search for mask field within EmisList
    2086           0 :     CALL ListCont_Find ( HcoState%EmisList, TRIM(MaskName), FND, MaskLct )
    2087             : 
    2088           0 :     IF ( .NOT. FND .AND. .NOT. PRESENT(FOUND) ) THEN
    2089           0 :        MSG = 'Cannot find mask field ' // TRIM(MaskName)
    2090           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG,SEP1='!')
    2091             :        MSG = 'Make sure this field is listed in the mask section '  // &
    2092             :            'of the HEMCO configuration file. You may also need to ' // &
    2093           0 :            'set the optional attribute `ReadAlways` to `yes`, e.g.'
    2094           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
    2095           0 :        MSG = '5000 TESTMASK     -140/10/-40/90 - - - xy 1 1 -140/10/-40/90 yes'
    2096           0 :        CALL HCO_MSG(HcoState%Config%Err,MSG)
    2097             :        CALL HCO_ERROR ( &
    2098           0 :                         'Error reading mask '//TRIM(MaskName), RC, THISLOC=LOC )
    2099           0 :        RETURN
    2100             :     ENDIF
    2101           0 :     IF ( PRESENT(FOUND) ) FOUND = FND
    2102             : 
    2103             :     ! Do only if found
    2104           0 :     IF ( FND ) THEN
    2105             : 
    2106             :        ! Use mask fractions?
    2107           0 :        Fractions = HcoState%Options%MaskFractions
    2108             : 
    2109             :        ! Make sure mask array has correct dimensions
    2110           0 :        IF ( SIZE(MASK,1) /= HcoState%NX .OR. SIZE(MASK,2) /= HcoState%NY ) THEN
    2111           0 :           WRITE(MSG,*) 'Input mask array has wrong dimensions. Must be ', &
    2112           0 :              HcoState%NX, HcoState%NY, ' but found ', SIZE(MASK,1), SIZE(MASK,2)
    2113           0 :           CALL HCO_ERROR ( MSG, RC, THISLOC=LOC )
    2114           0 :           RETURN
    2115             :        ENDIF
    2116             : 
    2117             :        ! Do for every grid box
    2118             :        !$OMP PARALLEL DO            &
    2119             :        !$OMP DEFAULT( SHARED      ) &
    2120             :        !$OMP PRIVATE( I, J        )
    2121           0 :        DO J = 1, HcoState%NY
    2122           0 :        DO I = 1, HcoState%NX
    2123           0 :           CALL GetMaskVal( MaskLct%Dct, I, J, Mask(I,J), Fractions, RC )
    2124           0 :           IF ( RC /= HCO_SUCCESS ) THEN
    2125             :              ERR = .TRUE.
    2126             :              EXIT
    2127             :           ENDIF
    2128             :        ENDDO
    2129             :        ENDDO
    2130             :        !$OMP END PARALLEL DO
    2131             : 
    2132             :        ! Error check
    2133           0 :        IF ( ERR ) THEN
    2134           0 :           MSG = 'Error in GetMaskVal'
    2135           0 :           CALL HCO_ERROR ( MSG, RC, THISLOC=LOC )
    2136           0 :           RETURN
    2137             :        ENDIF
    2138             : 
    2139             :     ENDIF
    2140             : 
    2141             :     ! Free pointer
    2142           0 :     MaskLct  => NULL()
    2143             : 
    2144             :     ! Return w/ success
    2145           0 :     RC = HCO_SUCCESS
    2146             : 
    2147             :   END SUBROUTINE HCO_MaskFld
    2148             : !EOC
    2149             : !------------------------------------------------------------------------------
    2150             : !                   Harmonized Emissions Component (HEMCO)                    !
    2151             : !------------------------------------------------------------------------------
    2152             : !BOP
    2153             : !
    2154             : ! !IROUTINE: GetVertIndx
    2155             : !
    2156             : ! !DESCRIPTION: Subroutine GetVertIndx is a helper routine to get the vertical
    2157             : !  index range of the given data field.
    2158             : !\\
    2159             : !\\
    2160             : ! !INTERFACE:
    2161             : !
    2162           0 :   SUBROUTINE GetVertIndx( HcoState, Dct,           isLevDct1,                &
    2163             :                           LevDct1,  LevDct1_Unit,  isLevDct2,                &
    2164             :                           LevDct2,  LevDct2_Unit,  I,                        &
    2165             :                           J,        LowLL,         UppLL,     RC            )
    2166             : !
    2167             : ! !USES:
    2168             : !
    2169             :     USE HCO_State_Mod, ONLY : HCO_State
    2170             : !
    2171             : ! !INPUT PARAMETERS:
    2172             : !
    2173             :     TYPE(HCO_State), POINTER       :: HcoState      ! HEMCO state object
    2174             :     LOGICAL,         INTENT(IN)    :: isLevDct1     ! Is LevDct1 not null?
    2175             :     TYPE(DataCont),  POINTER       :: LevDct1       ! Level index 1 container
    2176             :     INTEGER,         INTENT(IN)    :: LevDct1_Unit  ! LevDct1 unit code
    2177             :     LOGICAL,         INTENT(IN)    :: isLevDct2     ! Is LevDct2 not null?
    2178             :     TYPE(DataCont),  POINTER       :: LevDct2       ! Level index 2 container
    2179             :     INTEGER,         INTENT(IN)    :: LevDct2_Unit  ! LevDct2 unit code
    2180             :     INTEGER,         INTENT(IN)    :: I             ! lon index
    2181             :     INTEGER,         INTENT(IN)    :: J             ! lat index
    2182             : !
    2183             : ! !INPUT/OUTPUT PARAMETERS:
    2184             : !
    2185             :     TYPE(DataCont),  POINTER       :: Dct           ! Mask container
    2186             :     INTEGER,         INTENT(INOUT) :: LowLL         ! lower level index
    2187             :     INTEGER,         INTENT(INOUT) :: UppLL         ! upper level index
    2188             :     INTEGER,         INTENT(INOUT) :: RC
    2189             : !
    2190             : ! !REVISION HISTORY:
    2191             : !  06 May 2016 - C. Keller   - Initial Version
    2192             : !  See https://github.com/geoschem/hemco for complete history
    2193             : !EOP
    2194             : !------------------------------------------------------------------------------
    2195             : !BOC
    2196             : !
    2197             : ! !LOCAL VARIABLES:
    2198             : !
    2199             :     INTEGER             :: EmisLUnit
    2200             :     REAL(hp)            :: EmisL
    2201             :     CHARACTER(LEN=255)  :: errMsg, thisLoc
    2202             : 
    2203             :     !=======================================================================
    2204             :     ! GetVertIndx begins here
    2205             :     !=======================================================================
    2206             : 
    2207             :     ! Initialize
    2208           0 :     RC      = HCO_SUCCESS
    2209           0 :     errMsg  = ''
    2210           0 :     thisLoc = 'GetVertIndx (src/Core/hco_calc_mod.F90)'
    2211             : 
    2212             :     !-----------------------------------------------------------------------
    2213             :     ! Get vertical extension of base emission array.
    2214             :     !
    2215             :     ! Unlike the output array OUTARR_3D, the data containers do not
    2216             :     ! necessarily extent over the entire troposphere but only cover
    2217             :     ! the effectively filled vertical levels. For most inventories,
    2218             :     ! this is only the first model level.
    2219             :     !-----------------------------------------------------------------------
    2220           0 :     IF ( Dct%Dta%SpaceDim == 3 ) THEN
    2221           0 :        LowLL = 1
    2222           0 :        UppLL = SIZE( Dct%Dta%V3(1)%Val, 3 )
    2223           0 :        RC    = HCO_SUCCESS
    2224           0 :        RETURN
    2225             :     ENDIF
    2226             : 
    2227             :     !-----------------------------------------------------------------------
    2228             :     ! For 2D field, check if it shall be spread out over multiple
    2229             :     ! levels. Possible to go from PBL to max. specified level.
    2230             :     !-----------------------------------------------------------------------
    2231             : 
    2232             :     ! Lower level
    2233             :     ! --> Check if scale factor is used to determine lower and/or
    2234             :     !     upper level
    2235             :     !
    2236             :     ! NOTE: Get rid of ELSE block for efficiency (bmy, 09 Mar 2023)
    2237           0 :     EmisL     = Dct%Dta%EmisL1
    2238           0 :     EmisLUnit = Dct%Dta%EmisL1Unit
    2239             : 
    2240           0 :     IF ( isLevDct1 ) THEN
    2241           0 :        EmisL = GetEmisL( HcoState, LevDct1, I, J )
    2242           0 :        IF ( EmisL < 0.0_hp ) THEN
    2243           0 :           RC = HCO_FAIL
    2244           0 :           RETURN
    2245             :        ENDIF
    2246           0 :        EmisLUnit = LevDct1_Unit
    2247             :     ENDIF
    2248             : 
    2249           0 :     CALL GetIdx( HcoState, I, J, EmisL, EmisLUnit, LowLL, RC )
    2250           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    2251           0 :        errMsg = 'Error encountered in rouitine "GetIdx" (for LevDct1)!'
    2252           0 :        CALL HCO_ERROR( errMsg, RC, thisLoc )
    2253           0 :        RETURN
    2254             :     ENDIF
    2255             : 
    2256             :     ! Upper level
    2257             :     ! NOTE: Get rid of ELSE block for efficiency (bmy, 09 Mar 2023)
    2258           0 :     EmisL     = Dct%Dta%EmisL2
    2259           0 :     EmisLUnit = Dct%Dta%EmisL2Unit
    2260             : 
    2261           0 :     IF ( isLevDct2 ) THEN
    2262           0 :        EmisL = GetEmisL( HcoState, LevDct2, I, J )
    2263           0 :        IF ( EmisL < 0.0_hp ) THEN
    2264           0 :           RC = HCO_FAIL
    2265           0 :           RETURN
    2266             :        ENDIF
    2267           0 :        EmisLUnit = LevDct2_Unit
    2268             :     ENDIF
    2269             : 
    2270           0 :     CALL GetIdx( HcoState, I, J, EmisL, EmisLUnit, UppLL, RC )
    2271           0 :     IF ( RC /= HCO_SUCCESS ) THEN
    2272           0 :        errMsg = 'Error encountered in rouitine "GetIdx" (for LevDct2)!'
    2273           0 :        CALL HCO_ERROR( errMsg, RC, thisLoc )
    2274           0 :        RETURN
    2275             :     ENDIF
    2276             : 
    2277             :     ! Upper level must not be lower than lower level
    2278           0 :     UppLL = MAX(LowLL, UppLL)
    2279             : 
    2280             :     ! Return w/ success
    2281           0 :     RC = HCO_SUCCESS
    2282             : 
    2283             :   END SUBROUTINE GetVertIndx
    2284             : !EOC
    2285             : !------------------------------------------------------------------------------
    2286             : !                   Harmonized Emissions Component (HEMCO)                    !
    2287             : !------------------------------------------------------------------------------
    2288             : !BOP
    2289             : !
    2290             : ! !FUNCTION: GetEmisL
    2291             : !
    2292             : ! !DESCRIPTION: Returns the emission level read from a scale factor.
    2293             : !\\
    2294             : !\\
    2295             : ! !INTERFACE:
    2296             : !
    2297           0 :   FUNCTION GetEmisL( HcoState, LevDct, I, J ) RESULT ( EmisL )
    2298             : !
    2299             : ! !USES:
    2300             : !
    2301             :     USE HCO_TYPES_MOD
    2302             :     USE HCO_STATE_MOD,    ONLY : HCO_State
    2303             :     USE HCO_tIdx_MOD,     ONLY : tIDx_GetIndx
    2304             : !
    2305             : ! !INPUT PARAMETERS:
    2306             : !
    2307             :     TYPE(HCO_State), POINTER        :: HcoState       ! HEMCO state object
    2308             :     TYPE(DataCont),  POINTER        :: LevDct         ! Level index 1 container
    2309             :     INTEGER,         INTENT(IN   )  :: I, J           ! horizontal index
    2310             : !
    2311             : ! !RETURN VALUE:
    2312             : !
    2313             :     REAL(hp)                        :: EmisL
    2314             : !
    2315             : ! !REVISION HISTORY:
    2316             : !  26 Jan 2018 - C. Keller - Initial version
    2317             : !  See https://github.com/geoschem/hemco for complete history
    2318             : !EOP
    2319             : !------------------------------------------------------------------------------
    2320             : !BOC
    2321             : !
    2322             : ! !LOCAL VARIABLES:
    2323             : !
    2324             :     INTEGER  :: levtidx
    2325             : 
    2326             :     !=================================================================
    2327             :     ! GetEmisL begins here
    2328             :     !=================================================================
    2329           0 :     levtidx = tIDx_GetIndx( HcoState, LevDct%Dta, I, J )
    2330           0 :     IF ( levtidx <= 0 ) THEN
    2331             :        WRITE(*,*)' Cannot get time slice for field '//&
    2332           0 :        TRIM(LevDct%cName)//': GetEmisL (hco_calc_mod.F90)'
    2333           0 :        EmisL = -1.0
    2334           0 :        RETURN
    2335             :     ENDIF
    2336             : 
    2337           0 :     IF ( LevDct%Dta%SpaceDim == 1 ) THEN
    2338           0 :        EmisL = LevDct%Dta%V2(levtidx)%Val(1,1)
    2339           0 :     ELSEIF ( LevDct%Dta%SpaceDim == 2 ) THEN
    2340           0 :        EmisL = LevDct%Dta%V2(levtidx)%Val(I,J)
    2341           0 :     ELSEIF ( LevDct%Dta%SpaceDim == 3 ) THEN
    2342           0 :        EmisL = LevDct%Dta%V3(levtidx)%Val(I,J,1)
    2343             :     ENDIF
    2344             : 
    2345           0 :     IF ( EmisL == HCO_MISSVAL ) EmisL = 0.0_hp
    2346             : 
    2347             : END FUNCTION GetEmisL
    2348             : !EOC
    2349             : !------------------------------------------------------------------------------
    2350             : !                   Harmonized Emissions Component (HEMCO)                    !
    2351             : !------------------------------------------------------------------------------
    2352             : !BOP
    2353             : !
    2354             : ! !FUNCTION: GetEmisLUnit
    2355             : !
    2356             : ! !DESCRIPTION: Returns the emission level unit read from a scale factor.
    2357             : !\\
    2358             : !\\
    2359             : ! !INTERFACE:
    2360             : !
    2361           0 :   FUNCTION GetEmisLUnit( HcoState, LevDct ) RESULT( EmisLUnit )
    2362             : !
    2363             : ! !USES:
    2364             : !
    2365             :     USE HCO_TYPES_MOD
    2366             :     USE HCO_STATE_MOD, ONLY : HCO_State
    2367             : !
    2368             : ! !INPUT PARAMETERS:
    2369             : !
    2370             :     TYPE(HCO_State), POINTER        :: HcoState       ! HEMCO state object
    2371             :     TYPE(DataCont),  POINTER        :: LevDct         ! Level index 1 container
    2372             : !
    2373             : ! !RETURN VALUE:
    2374             : !
    2375             :     INTEGER                         :: EmisLUnit
    2376             : !
    2377             : ! !REVISION HISTORY:
    2378             : !  26 Jan 2018 - C. Keller - Initial version
    2379             : !  See https://github.com/geoschem/hemco for complete history
    2380             : !EOP
    2381             : !------------------------------------------------------------------------------
    2382             : !BOC
    2383             : !
    2384             : ! !LOCAL VARIABLES:
    2385             : !
    2386             :     !=================================================================
    2387             :     ! GetEmisLUnit begins here
    2388             :     !=================================================================
    2389             : 
    2390             :     ! For now, only meters are supported
    2391           0 :     EmisLUnit = HCO_EMISL_M
    2392             : 
    2393             :     ! Dummy check that units on field are actually in meters
    2394           0 :     IF ( TRIM(LevDct%Dta%OrigUnit) /= 'm' .AND. &
    2395             :          TRIM(LevDct%Dta%OrigUnit) /= '1'        ) THEN
    2396             :        WRITE(*,*) TRIM(LevDct%cName)// &
    2397             :        ' must have units of `m`, instead found '//&
    2398           0 :        TRIM(LevDct%Dta%OrigUnit)//': GetEmisLUnit (hco_calc_mod.F90)'
    2399           0 :        EmisLUnit = -1
    2400             :     ENDIF
    2401             : 
    2402           0 : END FUNCTION GetEmisLUnit
    2403             : !EOC
    2404             : !------------------------------------------------------------------------------
    2405             : !                   Harmonized Emissions Component (HEMCO)                    !
    2406             : !------------------------------------------------------------------------------
    2407             : !BOP
    2408             : !
    2409             : ! !IROUTINE: GetIdx
    2410             : !
    2411             : ! !DESCRIPTION: Subroutine GetIdx is a helper routine to return the vertical
    2412             : !  level index for a given altitude. The altitude can be provided in level
    2413             : !  coordinates, in units of meters or as the 'PBL mixing height'.
    2414             : !\\
    2415             : !\\
    2416             : ! !INTERFACE:
    2417             : !
    2418           0 :   SUBROUTINE GetIdx( HcoState, I, J, alt, altu, lidx, RC )
    2419             : !
    2420             : ! !USES:
    2421             : !
    2422             :     USE HCO_TYPES_MOD
    2423             :     USE HCO_STATE_MOD,   ONLY : HCO_STATE
    2424             : !
    2425             : ! !INPUT PARAMETERS:
    2426             : !
    2427             :     TYPE(HCO_State), POINTER        :: HcoState       ! HEMCO state object
    2428             :     INTEGER,         INTENT(IN   )  :: I, J           ! horizontal index
    2429             :     INTEGER,         INTENT(IN   )  :: altu           ! altitude unit
    2430             : !
    2431             : ! !OUTPUT PARAMETERS:
    2432             : !
    2433             :     INTEGER,         INTENT(  OUT)  :: lidx           ! level index
    2434             : !
    2435             : ! !INPUT/OUTPUT PARAMETERS:
    2436             : !
    2437             :     REAL(hp),        INTENT(INOUT)  :: alt            ! altitude
    2438             :     INTEGER,         INTENT(INOUT)  :: RC
    2439             : !
    2440             : ! !REMARKS:
    2441             : !  The code was refactored to avoid ELSE blocks (which are computationally
    2442             : !  expensive) following the "never-nesting" technique. (Bob Y., 10 Mar 2023)
    2443             : !
    2444             : ! !REVISION HISTORY:
    2445             : !  09 May 2016 - C. Keller - Initial version
    2446             : !  See https://github.com/geoschem/hemco for complete history
    2447             : !EOP
    2448             : !------------------------------------------------------------------------------
    2449             : !BOC
    2450             : !
    2451             : ! !LOCAL VARIABLES:
    2452             : !
    2453             :     INTEGER                 :: L
    2454             :     REAL(hp)                :: altb, altt
    2455             :     CHARACTER(LEN=255)      :: MSG
    2456             :     CHARACTER(LEN=255)      :: LOC = 'GetIdx (hco_calc_mod.F90)'
    2457             : 
    2458             :     !=================================================================
    2459             :     ! HCO_GetIdx begins here
    2460             :     !=================================================================
    2461             : 
    2462             :     ! Init
    2463           0 :     RC = HCO_SUCCESS
    2464             : 
    2465             :     ! Input data is in level coordinates;
    2466             :     ! Return the corresponding level index
    2467           0 :     IF ( altu == HCO_EMISL_LEV ) THEN
    2468           0 :        lidx = INT( alt )
    2469           0 :        RETURN
    2470             :     ENDIF
    2471             : 
    2472             :     ! Input specifies the top-of-atmosphere;
    2473             :     ! Return the top-of-atmosphere level index
    2474           0 :     IF ( altu == HCO_EMISL_TOP ) THEN
    2475           0 :        lidx = HCOState%NZ
    2476           0 :        RETURN
    2477             :     ENDIF
    2478             : 
    2479             :     ! Input data is in meters or specifies the PBL top;
    2480             :     ! Find the corresponding level index
    2481           0 :     IF ( altu == HCO_EMISL_M .OR. altu == HCO_EMISL_PBL ) THEN
    2482             : 
    2483             :        ! Eventually get altitude from PBL height
    2484           0 :        IF ( altu == HCO_EMISL_PBL ) THEN
    2485           0 :           alt = HcoState%Grid%PBLHEIGHT%Val(I,J)
    2486             :        ENDIF
    2487             : 
    2488             :        ! Special case of negative height
    2489           0 :        IF ( alt <= 0.0_hp ) THEN
    2490           0 :           lidx = 1
    2491           0 :           RETURN
    2492             :        ENDIF
    2493             : 
    2494             :        ! Loop over data until we are within desired level
    2495             :        ! NOTE: This can be rewritten more efficiently (bmy, 3/5/21)
    2496           0 :        altt = 0.0_hp
    2497           0 :        altb = 0.0_hp
    2498           0 :        lidx = -1
    2499           0 :        DO L = 1, HcoState%NZ
    2500           0 :           altt = altb + HcoState%Grid%BXHEIGHT_M%Val(I,J,L)
    2501           0 :           IF ( alt >= altb .AND. alt < altt ) THEN
    2502           0 :              lidx = L
    2503           0 :              RETURN
    2504             :           ENDIF
    2505           0 :           altb = altt
    2506             :        ENDDO
    2507             : 
    2508             :        ! If altitude is above maximum level
    2509           0 :        IF ( lidx == -1 .AND. alt >= altt ) THEN
    2510           0 :           lidx = HcoState%NZ
    2511             :           WRITE(MSG,*)                                                       &
    2512           0 :                'Level is above max. grid box level - use top level ', alt
    2513           0 :           CALL HCO_WARNING ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2514           0 :           RETURN
    2515             :        ENDIF
    2516             : 
    2517             :        RETURN
    2518             :     ENDIF
    2519             : 
    2520             :     ! Error if we drop down to here
    2521           0 :     MSG = 'Illegal altitude unit'
    2522           0 :     CALL HCO_ERROR ( MSG, RC, THISLOC=LOC )
    2523             : 
    2524             :   END SUBROUTINE GetIdx
    2525             : !EOC
    2526             : !------------------------------------------------------------------------------
    2527             : !                   Harmonized Emissions Component (HEMCO)                    !
    2528             : !------------------------------------------------------------------------------
    2529             : !BOP
    2530             : !
    2531             : ! !IROUTINE: GetDilFact
    2532             : !
    2533             : ! !DESCRIPTION: Subroutine GetDilFact returns the vertical dilution factor,
    2534             : ! that is the factor that is to be applied to distribute emissions into
    2535             : ! multiple vertical levels. If grid box height information are available,
    2536             : ! these are used to compute the distribution factor. Otherwise, equal weight
    2537             : ! is given to all vertical levels.
    2538             : !\\
    2539             : !\\
    2540             : ! !TODO: Dilution factors are currently only weighted by grid box heights
    2541             : ! (if these information are available) but any pressure information are
    2542             : ! ignored.
    2543             : !\\
    2544             : !\\
    2545             : ! !INTERFACE:
    2546             : !
    2547           0 :   SUBROUTINE GetDilFact( HcoState,   EmisL1, EmisL1Unit, EmisL2,             &
    2548             :                          EmisL2Unit, I,      J,          L,                  &
    2549             :                          LowLL,      UppLL,  DilFact,    RC                 )
    2550             : !
    2551             : ! !USES:
    2552             : !
    2553             :     USE HCO_STATE_MOD,    ONLY : HCO_State
    2554             : !
    2555             : ! !INPUT PARAMETERS:
    2556             : !
    2557             :     TYPE(HCO_State), POINTER       :: HcoState    ! HEMCO state object
    2558             :     INTEGER,         INTENT(IN)    :: I           ! lon index
    2559             :     INTEGER,         INTENT(IN)    :: J           ! lat index
    2560             :     INTEGER,         INTENT(IN)    :: L           ! lev index
    2561             :     INTEGER,         INTENT(IN)    :: LowLL       ! lower level index
    2562             :     INTEGER,         INTENT(IN)    :: UppLL       ! upper level index
    2563             : !
    2564             : ! !OUTPUT PARAMETERS:
    2565             : !
    2566             :     REAL(hp),        INTENT(OUT)   :: DilFact     ! Dilution factor
    2567             : !
    2568             : ! !INPUT/OUTPUT PARAMETERS:
    2569             : !
    2570             :     REAL(hp),        INTENT(INOUT) :: EmisL1
    2571             :     INTEGER,         INTENT(INOUT) :: EmisL1Unit
    2572             :     REAL(hp),        INTENT(INOUT) :: EmisL2
    2573             :     INTEGER,         INTENT(INOUT) :: EmisL2Unit
    2574             :     INTEGER,         INTENT(INOUT) :: RC
    2575             : !
    2576             : ! !REVISION HISTORY:
    2577             : !  06 May 2016 - C. Keller   - Initial Version
    2578             : !  See https://github.com/geoschem/hemco for complete history
    2579             : !EOP
    2580             : !------------------------------------------------------------------------------
    2581             : !BOC
    2582             : !
    2583             : ! !LOCAL VARIABLES:
    2584             : !
    2585             :     INTEGER            :: L1
    2586             :     CHARACTER(LEN=255) :: MSG
    2587             :     CHARACTER(LEN=255) :: LOC = 'GetDilFact (hco_calc_mod.F90)'
    2588             :     REAL(hp)           :: h1, h2, dh, dh1, dh2
    2589             :     REAL(hp)           :: UppLLR, LowLLR
    2590             : 
    2591             :     !=================================================================
    2592             :     ! GetDilFact begins here
    2593             :     !=================================================================
    2594             : 
    2595             :     ! Init
    2596           0 :     DilFact = 1.0_hp
    2597           0 :     RC = HCO_SUCCESS
    2598             : 
    2599             :     ! Nothing to do if it's only one level
    2600           0 :     IF ( LowLL == UppLL ) RETURN
    2601             : 
    2602             :     ! Compute dilution factor based on boxheights if this information
    2603             :     ! is available
    2604           0 :     IF ( ASSOCIATED( HcoState%Grid%BXHEIGHT_M%Val ) ) THEN
    2605             : 
    2606             :        ! Get height of bottom level LowLL (in m)
    2607           0 :        IF ( EmisL1Unit == HCO_EMISL_M ) THEN
    2608           0 :           h1 = EmisL1
    2609           0 :        ELSEIF ( EmisL1Unit == HCO_EMISL_PBL ) THEN
    2610           0 :           h1 = HcoState%Grid%PBLHEIGHT%Val(I,J)
    2611             :        ELSE
    2612           0 :           IF ( LowLL > 1 ) THEN
    2613           0 :              h1 = SUM(HcoState%Grid%BXHEIGHT_M%Val(I,J,1:(LowLL-1)))
    2614             :           ELSE
    2615             :              h1 = 0.0_hp
    2616             :           ENDIF
    2617             :        ENDIF
    2618             : 
    2619             :        ! Get height of top level UppLL (in m)
    2620           0 :        IF ( EmisL2Unit == HCO_EMISL_M ) THEN
    2621           0 :           h2 = EmisL2
    2622           0 :        ELSEIF ( EmisL2Unit == HCO_EMISL_PBL ) THEN
    2623           0 :           h2 = HcoState%Grid%PBLHEIGHT%Val(I,J)
    2624             :        ELSE
    2625           0 :           h2 = SUM(HcoState%Grid%BXHEIGHT_M%Val(I,J,1:UppLL))
    2626             :        ENDIF
    2627             : 
    2628             :        ! If vertical weight option is enabled, calculate vertical
    2629             :        ! distribution factor relative to the grid cell heights. This
    2630             :        ! is the default (and recommended) option as this makes sure
    2631             :        ! that the same amount of mass is emitted into each layer.
    2632           0 :        IF ( HcoState%Options%VertWeight ) THEN
    2633             : 
    2634             :           ! Height of grid box of interest (in m)
    2635           0 :           dh = HcoState%Grid%BXHEIGHT_M%Val(I,J,L)
    2636             : 
    2637             :           ! Adjust dh if we are in lowest level
    2638           0 :           IF ( L == LowLL ) THEN
    2639           0 :              dh = SUM(HcoState%Grid%BXHEIGHT_M%Val(I,J,1:LowLL)) - h1
    2640             :           ENDIF
    2641             : 
    2642             :           ! Adjust dh if we are in top level
    2643           0 :           IF ( L == UppLL ) THEN
    2644           0 :              dh = h2 - SUM(HcoState%Grid%BXHEIGHT_M%Val(I,J,1:(UppLL-1)))
    2645             :           ENDIF
    2646             : 
    2647             :           ! compute dilution factor: the new flux should emit the same mass per
    2648             :           ! volume, i.e. flux_total/column_total = flux_level/column_level
    2649             :           ! --> flux_level = fluxtotal * column_level / column_total.
    2650           0 :           IF ( h2 > h1 ) THEN
    2651           0 :              DilFact = dh / ( h2 - h1 )
    2652             :           ELSE
    2653           0 :              MSG = 'GetDilFact h2 not greater than h1'
    2654           0 :              CALL HCO_ERROR ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2655           0 :              RETURN
    2656             :           ENDIF
    2657             : 
    2658             :        ! If VertWeight option is turned off, emit the same flux in each layer.
    2659             :        ! Since model layers have different depths, this will result in differnt
    2660             :        ! total emissions per layer.
    2661             :        ELSE
    2662             : 
    2663             :           ! Get fractional layer indeces for lower and upper level. This makes
    2664             :           ! sure that only fractions of the lower and upper level are being
    2665             :           ! considered, so that double-counting is avoided if a model layer
    2666             :           ! serves both as the top layer and the bottom layer (e.g., wildfire
    2667             :           ! emissions emitted from bottom to the top of PBL, and from the top
    2668             :           ! of PBL to 5000m).
    2669           0 :           LowLLR = REAL(LowLL,hp) - 1.0_hp
    2670           0 :           UppLLR = REAL(UppLL,hp)
    2671           0 :           dh1 = 0.0_hp
    2672           0 :           DO L1 = 1, HcoState%NZ
    2673           0 :              dh2 = SUM(HcoState%Grid%BXHEIGHT_M%Val(I,J,1:L1))
    2674           0 :              IF ( h1 >= dh1 .AND. h1 < dh2 ) THEN
    2675           0 :                 LowLLR = REAL(L1,hp) - ( (dh2-h1)/(dh2-dh1) )
    2676             :              ENDIF
    2677           0 :              IF ( h2 > dh1 .AND. h2 <= dh2 ) THEN
    2678           0 :                 UppLLR = REAL(L1,hp) - ( (dh2-h2)/(dh2-dh1) )
    2679             :              ENDIF
    2680             :              ! top layer is bottom layer in next loop
    2681           0 :              dh1 = dh2
    2682             :           ENDDO
    2683             : 
    2684             :           ! Dilution factor using fractional levels
    2685           0 :           IF ( UppLLR <= LowLLR ) THEN
    2686           0 :              DilFact = 1.0_hp / REAL(UppLL-LowLL+1,hp)
    2687             :           ELSE
    2688           0 :              DilFact = 1.0_hp / (UppLLR-LowLLR)
    2689             :           ENDIF
    2690             : 
    2691             :        ENDIF
    2692             : 
    2693             :     ! Approximate dilution factor otherwise
    2694             :     ELSE
    2695             : 
    2696           0 :        DilFact = 1.0_hp / REAL(UppLL-LowLL+1,hp)
    2697             :     ENDIF
    2698             : 
    2699             :     ! Return w/ success
    2700           0 :     RC = HCO_SUCCESS
    2701             : 
    2702             :   END SUBROUTINE GetDilFact
    2703             : #ifdef ADJOINT
    2704             : !BOP
    2705             : !
    2706             : ! !IROUTINE: Get_Current_Emissions
    2707             : !
    2708             : ! !DESCRIPTION: Subroutine Get\_Current\_Emissions calculates the current
    2709             : !  emissions for the specified emission container.
    2710             : !  This subroutine is only called by HCO\_CalcEmis and for base emission
    2711             : !  containers, i.e. containers of type 1.
    2712             : !\\
    2713             : !\\
    2714             : ! !INTERFACE:
    2715             : !
    2716             :   SUBROUTINE Get_Current_Emissions_Adj( HcoState, BaseDct,   &
    2717             :                                     nI, nJ, nL, OUTARR_3D, MASK, RC, UseLL )
    2718             : !
    2719             : ! !USES:
    2720             : !
    2721             :     USE HCO_State_Mod,    ONLY : HCO_State
    2722             :     USE HCO_tIdx_MOD,     ONLY : tIDx_GetIndx
    2723             :     USE HCO_FileData_Mod, ONLY : FileData_ArrIsDefined
    2724             : !
    2725             : ! !INPUT PARAMETERS:
    2726             : !
    2727             :     INTEGER,           INTENT(IN)  :: nI                  ! # of lons
    2728             :     INTEGER,           INTENT(IN)  :: nJ                  ! # of lats
    2729             :     INTEGER,           INTENT(IN)  :: nL                  ! # of levs
    2730             : !
    2731             : ! !INPUT/OUTPUT PARAMETERS:
    2732             : !
    2733             : 
    2734             :     TYPE(HCO_State), POINTER       :: HcoState            ! HEMCO state object
    2735             :     TYPE(DataCont),  POINTER       :: BaseDct             ! base emission
    2736             :                                                           !  container
    2737             :     REAL(hp),        INTENT(INOUT) :: OUTARR_3D(nI,nJ,nL) ! output array
    2738             :     REAL(hp),        INTENT(INOUT) :: MASK     (nI,nJ,nL) ! mask array
    2739             :     INTEGER,         INTENT(INOUT) :: RC
    2740             : !
    2741             : ! !OUTPUT PARAMETERS:
    2742             : !
    2743             :     INTEGER,         INTENT(  OUT), OPTIONAL :: UseLL
    2744             : !
    2745             : ! !REMARKS:
    2746             : !  This routine uses multiple loops over all grid boxes (base emissions
    2747             : !  and scale factors use separate loops). In an OMP environment, this approach
    2748             : !  seems to be faster than using only one single loop (but repeated calls to
    2749             : !  point to containers, etc.). The alternative approach is used in routine
    2750             : !  Get\_Current\_Emissions\_B at the end of this module and may be employed
    2751             : !  on request.
    2752             : !
    2753             : ! !REVISION HISTORY:
    2754             : !  25 Aug 2012 - C. Keller   - Initial Version
    2755             : !  09 Nov 2012 - C. Keller   - MASK update. Masks are now treated
    2756             : !                              separately so that multiple masks can be
    2757             : !                              added.
    2758             : !  06 Jun 2014 - R. Yantosca - Cosmetic changes in ProTeX headers
    2759             : !  07 Sep 2014 - C. Keller   - Mask update. Now set mask to zero as soon as
    2760             : !                              on of the applied masks is zero.
    2761             : !  03 Dec 2014 - C. Keller   - Now calculate time slice index on-the-fly.
    2762             : !  29 Dec 2014 - C. Keller   - Added scale factor masks.
    2763             : !  02 Mar 2015 - C. Keller   - Now check for missing values. Missing values are
    2764             : !                              excluded from emission calculation.
    2765             : !  26 Oct 2016 - R. Yantosca - Don't nullify local ptrs in declaration stmts
    2766             : !  11 May 2017 - C. Keller   - Added universal scaling
    2767             : !EOP
    2768             : !------------------------------------------------------------------------------
    2769             : !BOC
    2770             : !
    2771             : ! !LOCAL VARIABLES:
    2772             : !
    2773             :     ! Pointers
    2774             :     TYPE(DataCont), POINTER :: ScalDct
    2775             :     TYPE(DataCont), POINTER :: MaskDct
    2776             :     TYPE(DataCont), POINTER :: LevDct1
    2777             :     TYPE(DataCont), POINTER :: LevDct2
    2778             : 
    2779             :     ! Scalars
    2780             :     REAL(sp)                :: TMPVAL, MaskScale
    2781             :     REAL(hp)                :: DilFact
    2782             :     REAL(hp)                :: ScalFact
    2783             :     INTEGER                 :: tIDx, IDX
    2784             :     INTEGER                 :: I, J, L, N
    2785             :     INTEGER                 :: LowLL, UppLL, ScalLL, TmpLL
    2786             :     INTEGER                 :: ERROR
    2787             :     INTEGER                 :: TotLL, nnLL
    2788             :     CHARACTER(LEN=255)      :: MSG, LOC
    2789             :     LOGICAL                 :: NegScalExist
    2790             :     LOGICAL                 :: MaskFractions
    2791             :     LOGICAL                 :: isLevDct1
    2792             :     LOGICAL                 :: isLevDct2
    2793             :     LOGICAL                 :: isMaskDct
    2794             :     LOGICAL                 :: isPblHt
    2795             :     LOGICAL                 :: isBoxHt
    2796             :     INTEGER                 :: LevDct1_Unit
    2797             :     INTEGER                 :: LevDct2_Unit
    2798             : 
    2799             :     ! testing only
    2800             :     INTEGER                 :: IX, IY
    2801             : 
    2802             :     !=================================================================
    2803             :     ! GET_CURRENT_EMISSIONS begins here
    2804             :     !=================================================================
    2805             : 
    2806             :     ! Initialize
    2807             :     ScalDct => NULL()
    2808             :     MaskDct => NULL()
    2809             :     LOC     = 'GET_CURRENT_EMISSIONS_ADJ (hco_calc_mod.F90)'
    2810             : 
    2811             :     ! Enter
    2812             :     CALL HCO_ENTER(HcoState%Config%Err, LOC, RC )
    2813             :     IF(RC /= HCO_SUCCESS) RETURN
    2814             : 
    2815             :     ! testing only:
    2816             :     IX = 3 !-1
    2817             :     IY = 8 !-1
    2818             : 
    2819             :     ! Check if container contains data
    2820             :     IF ( .NOT. FileData_ArrIsDefined(BaseDct%Dta) ) THEN
    2821             :        MSG = 'Array not defined: ' // TRIM(BaseDct%cName)
    2822             :        CALL HCO_ERROR( MSG, RC )
    2823             :        RETURN
    2824             :     ENDIF
    2825             : 
    2826             :     ! Initialize mask. By default, assume that we use all grid boxes.
    2827             :     MASK(:,:,:)  = 1.0_hp
    2828             :     MaskFractions = HcoState%Options%MaskFractions
    2829             : 
    2830             :     ! Verbose
    2831             :     IF ( HCO_IsVerb(HcoState%Config%Err) ) THEN
    2832             :        WRITE(MSG,*) 'Evaluate field ', TRIM(BaseDct%cName)
    2833             :        CALL HCO_MSG(HcoState%Config%Err,MSG,SEP1=' ')
    2834             :     ENDIF
    2835             : 
    2836             :     ! ----------------------------------------------------------------
    2837             :     ! Set base emissions
    2838             :     ! ----------------------------------------------------------------
    2839             : 
    2840             :     ! Initialize ERROR. Will be set to 1 if error occurs below
    2841             :     ERROR = 0
    2842             : 
    2843             :     ! Initialize variables to compute average vertical level index
    2844             :     totLL = 0
    2845             :     nnLL  = 0
    2846             : 
    2847             :     ! Check for level index containers
    2848             :     IF ( BaseDct%levScalID1 > 0 ) THEN
    2849             :        CALL Pnt2DataCont( HcoState, BaseDct%levScalID1, LevDct1, RC )
    2850             :        IF ( RC /= HCO_SUCCESS ) THEN
    2851             :            CALL HCO_ERROR( 'ERROR 18', RC, THISLOC=LOC )
    2852             :            RETURN
    2853             :        ENDIF
    2854             :     ELSE
    2855             :        LevDct1 => NULL()
    2856             :     ENDIF
    2857             :     IF ( BaseDct%levScalID2 > 0 ) THEN
    2858             :        CALL Pnt2DataCont( HcoState, BaseDct%levScalID2, LevDct2, RC )
    2859             :        IF ( RC /= HCO_SUCCESS ) THEN
    2860             :            CALL HCO_ERROR( 'ERROR 19', RC, THISLOC=LOC )
    2861             :            RETURN
    2862             :        ENDIF
    2863             :     ELSE
    2864             :        LevDct2 => NULL()
    2865             :     ENDIF
    2866             : 
    2867             :     ! Test whether LevDct1 and LevDct2 are associated
    2868             :     isLevDct1 = ASSOCIATED( LevDct1 )
    2869             :     isLevDct2 = ASSOCIATED( LevDct2 )
    2870             : 
    2871             :     ! Get the units of LevDct1 (if it exists)
    2872             :     IF ( isLevDct1 ) THEN
    2873             :        LevDct1_Unit = GetEmisLUnit( HcoState, LevDct1 )
    2874             :        IF ( LevDct1_Unit < 0 ) THEN
    2875             :           MSG = 'LevDct1 units are not defined!'
    2876             :           CALL HCO_ERROR ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2877             :           RC = HCO_FAIL
    2878             :           RETURN
    2879             :        ENDIF
    2880             :     ELSE
    2881             :        LevDct1_Unit = -1
    2882             :     ENDIF
    2883             : 
    2884             :     ! Get the units of LevDct2 (if it exists)
    2885             :     IF ( isLevDct2 ) THEN
    2886             :        LevDct2_Unit = GetEmisLUnit( HcoState, LevDct2 )
    2887             :        IF ( LevDct2_Unit < 0 ) THEN
    2888             :           MSG = 'LevDct2_Units are not defined!'
    2889             :           CALL HCO_ERROR ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2890             :           RETURN
    2891             :        ENDIF
    2892             :     ELSE
    2893             :        LevDct2_Unit = -1
    2894             :     ENDIF
    2895             : 
    2896             :     ! Throw an error if boxheight is missing and the units are in meters
    2897             :     IF ( LevDct1_Unit == HCO_EMISL_M  .or.                                  &
    2898             :          LevDct2_Unit == HCO_EMISL_M ) THEN
    2899             :        IF ( .NOT. ASSOCIATED(HcoState%Grid%BXHEIGHT_M%Val) ) THEN
    2900             :           MSG = 'Boxheight (in meters) is missing in HEMCO state'
    2901             :           CALL HCO_ERROR ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2902             :           RETURN
    2903             :        ENDIF
    2904             :     ENDIF
    2905             : 
    2906             :     ! Throw an error if boxheight is missing and the units are in PBL frac
    2907             :     IF ( LevDct1_Unit == HCO_EMISL_PBL  .or.                                &
    2908             :          LevDct2_Unit == HCO_EMISL_PBL ) THEN
    2909             :        IF ( .NOT. ASSOCIATED(HcoState%Grid%PBLHEIGHT%Val) ) THEN
    2910             :           MSG = 'Boundary layer height is missing in HEMCO state'
    2911             :           CALL HCO_ERROR ( HcoState%Config%Err, MSG, RC, THISLOC=LOC )
    2912             :           RETURN
    2913             :        ENDIF
    2914             :     ENDIF
    2915             : 
    2916             :     ! Loop over all latitudes and longitudes
    2917             : !$OMP PARALLEL DO                                                            &
    2918             : !$OMP DEFAULT( SHARED                                                       )&
    2919             : !$OMP PRIVATE( I, J, L, tIdx, TMPVAL, DilFact, LowLL, UppLL                 )&
    2920             : !$OMP COLLAPSE( 2                                                           )&
    2921             : !$OMP SCHEDULE( DYNAMIC, 4                                                  )&
    2922             : !$OMP REDUCTION( +:totLL                                                    )&
    2923             : !$OMP REDUCTION( +:nnLL                                                     )
    2924             :     DO J = 1, nJ
    2925             :     DO I = 1, nI
    2926             : 
    2927             :        ! Zero for safety's sake
    2928             :        totLL = 0
    2929             :        nnLL  = 0
    2930             : 
    2931             :        ! Get current time index for this container and at this location
    2932             :        tIDx = tIDx_GetIndx( HcoState, BaseDct%Dta, I, J )
    2933             :        IF ( tIDx < 1 ) THEN
    2934             :           WRITE(MSG,*) 'Cannot get time slice index at location ',I,J,&
    2935             :                        ': ', TRIM(BaseDct%cName), tIDx
    2936             :           ERROR = 1
    2937             :           EXIT
    2938             :        ENDIF
    2939             : 
    2940             :        ! Get lower and upper vertical index
    2941             :        CALL GetVertIndx ( HcoState,     BaseDct,   isLevDct1, LevDct1,       &
    2942             :                           LevDct1_Unit, isLevDct2, LevDct2,   LevDct2_Unit,  &
    2943             :                           I,            J,         LowLL,     UppLL,         &
    2944             :                           RC                                                )
    2945             :        IF ( RC /= HCO_SUCCESS ) THEN
    2946             :           WRITE(MSG,*) 'Error getting vertical index at location ',I,J,&
    2947             :                        ': ', TRIM(BaseDct%cName)
    2948             :           ERROR = 1 ! Will cause error
    2949             :           EXIT
    2950             :        ENDIF
    2951             : 
    2952             :        ! average upper level
    2953             :        totLL = totLL + UppLL
    2954             :        nnLL  = nnLL + 1
    2955             : 
    2956             :        ! Loop over all levels
    2957             :        DO L = LowLL, UppLL
    2958             : 
    2959             :           ! Get base value. Use uniform value if scalar field.
    2960             :           IF ( BaseDct%Dta%SpaceDim == 1 ) THEN
    2961             :              TMPVAL = BaseDct%Dta%V2(tIDx)%Val(1,1)
    2962             :           ELSEIF ( BaseDct%Dta%SpaceDim == 2 ) THEN
    2963             :              TMPVAL = BaseDct%Dta%V2(tIDx)%Val(I,J)
    2964             :           ELSE
    2965             :              TMPVAL = BaseDct%Dta%V3(tIDx)%Val(I,J,L)
    2966             :           ENDIF
    2967             : 
    2968             :           ! If it's a missing value, mask box as unused and set value to zero
    2969             :           IF ( TMPVAL == HCO_MISSVAL ) THEN
    2970             :              MASK(I,J,:)      = 0.0_hp
    2971             :              OUTARR_3D(I,J,L) = 0.0_hp
    2972             : 
    2973             :           ! Pass base value to output array
    2974             :           ELSE
    2975             : 
    2976             :              ! Get dilution factor. Never dilute 3D emissions.
    2977             :              IF ( BaseDct%Dta%SpaceDim == 3 ) THEN
    2978             :                 DilFact = 1.0_hp !1.0
    2979             : 
    2980             :              ! 2D dilution factor
    2981             :              ELSE
    2982             :                 CALL GetDilFact ( HcoState,    BaseDct%Dta%EmisL1, &
    2983             :                                   BaseDct%Dta%EmisL1Unit, BaseDct%Dta%EmisL2,  &
    2984             :                                   BaseDct%Dta%EmisL2Unit, I, J, L, LowLL,  &
    2985             :                                   UppLL, DilFact, RC )
    2986             :                 IF ( RC /= HCO_SUCCESS ) THEN
    2987             :                    WRITE(MSG,*) 'Error getting dilution factor at ',I,J,&
    2988             :                                 ': ', TRIM(BaseDct%cName)
    2989             :                    ERROR = 1
    2990             :                    EXIT
    2991             :                 ENDIF
    2992             :              ENDIF
    2993             : 
    2994             :              ! Scale base emission by dilution factor
    2995             :              OUTARR_3D(I,J,L) = DilFact * TMPVAL
    2996             :           ENDIF
    2997             :        ENDDO !L
    2998             : 
    2999             :     ENDDO !I
    3000             :     ENDDO !J
    3001             : !$OMP END PARALLEL DO
    3002             : 
    3003             :     ! Check for error
    3004             :     IF ( ERROR == 1 ) THEN
    3005             :        CALL HCO_ERROR( MSG, RC )
    3006             :        RETURN
    3007             :     ENDIF
    3008             : 
    3009             :     ! ----------------------------------------------------------------
    3010             :     ! Apply scale factors
    3011             :     ! The container IDs of all scale factors associated with this base
    3012             :     ! container are stored in vector Scal_cID.
    3013             :     ! ----------------------------------------------------------------
    3014             : 
    3015             :     ! Loop over scale factors
    3016             :     IF ( BaseDct%nScalID > 0 ) THEN
    3017             : 
    3018             :     DO N = 1, BaseDct%nScalID
    3019             : 
    3020             :        ! Get the scale factor container ID for the current slot
    3021             :        IDX = BaseDct%Scal_cID(N)
    3022             : 
    3023             :        ! Point to data container with the given container ID
    3024             :        CALL Pnt2DataCont( HcoState, IDX, ScalDct, RC )
    3025             :        IF ( RC /= HCO_SUCCESS ) THEN
    3026             :            CALL HCO_ERROR( 'ERROR 20', RC, THISLOC=LOC )
    3027             :            RETURN
    3028             :        ENDIF
    3029             : 
    3030             :        ! Sanity check: scale field cannot be a base field
    3031             :        IF ( (ScalDct%DctType == HCO_DCTTYPE_BASE) ) THEN
    3032             :           MSG = 'Wrong scale field type: ' // TRIM(ScalDct%cName)
    3033             :           CALL HCO_ERROR( MSG, RC )
    3034             :           RETURN
    3035             :        ENDIF
    3036             : 
    3037             :        ! Skip this scale factor if no data defined. This is possible
    3038             :        ! if scale factors are only defined for a given time range and
    3039             :        ! the simulation datetime is outside of this range.
    3040             :        IF ( .NOT. FileData_ArrIsDefined(ScalDct%Dta) ) THEN
    3041             :           IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
    3042             :              MSG = 'Skip scale factor '//TRIM(ScalDct%cName)// &
    3043             :                    ' because it is not defined for this datetime.'
    3044             :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3045             :           ENDIF
    3046             :           CYCLE
    3047             :        ENDIF
    3048             : 
    3049             :        ! Verbose mode
    3050             :        IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
    3051             :           MSG = 'Applying scale factor ' // TRIM(ScalDct%cName)
    3052             :           CALL HCO_MSG(HcoState%Config%Err,MSG)
    3053             :        ENDIF
    3054             : 
    3055             :        ! Get vertical extension of this scale factor array.
    3056             :        IF( (ScalDct%Dta%SpaceDim<=2) ) THEN
    3057             :           ScalLL = 1
    3058             :        ELSE
    3059             :           ScalLL = SIZE(ScalDct%Dta%V3(1)%Val,3)
    3060             :        ENDIF
    3061             : 
    3062             :        ! Check if there is a mask field associated with this scale
    3063             :        ! factor. In this case, get a pointer to the corresponding
    3064             :        ! mask field and evaluate scale factors only inside the mask
    3065             :        ! region.
    3066             :        IF ( ASSOCIATED(ScalDct%Scal_cID) ) THEN
    3067             :           CALL Pnt2DataCont( HcoState, ScalDct%Scal_cID(1), MaskDct, RC )
    3068             :           IF ( RC /= HCO_SUCCESS ) THEN
    3069             :               CALL HCO_ERROR( 'ERROR 21', RC, THISLOC=LOC )
    3070             :               RETURN
    3071             :           ENDIF
    3072             : 
    3073             :           ! Must be mask field
    3074             :           IF ( MaskDct%DctType /= HCO_DCTTYPE_MASK ) THEN
    3075             :              MSG = 'Invalid mask for scale factor: '//TRIM(ScalDct%cName)
    3076             :              MSG = TRIM(MSG) // '; mask: '//TRIM(MaskDct%cName)
    3077             :              CALL HCO_ERROR( MSG, RC )
    3078             :              RETURN
    3079             :           ENDIF
    3080             :        ENDIF
    3081             : 
    3082             :        ! Reinitialize error flag. Will be set to 1 or 2 if error occurs,
    3083             :        ! and to -1 if negative scale factor is ignored.
    3084             :        ERROR = 0
    3085             : 
    3086             :        ! Loop over all latitudes and longitudes
    3087             : !$OMP PARALLEL DO                                                            &
    3088             : !$OMP DEFAULT( SHARED )                                                      &
    3089             : !$OMP PRIVATE( I, J, tIdx, TMPVAL, L, LowLL, UppLL, tmpLL, MaskScale        )&
    3090             : !$OMP COLLAPSE( 2                                                           )&
    3091             : !$OMP SCHEDULE( DYNAMIC, 4                                                  )
    3092             :        DO J = 1, nJ
    3093             :        DO I = 1, nI
    3094             : 
    3095             :           ! ------------------------------------------------------------
    3096             :           ! If there is a mask associated with this scale factors, check
    3097             :           ! if this grid box is within or outside of the mask region.
    3098             :           ! Values that partially fall into the mask region are either
    3099             :           ! treated as binary (100% inside or outside), or partially
    3100             :           ! (using the real grid area fractions), depending on the
    3101             :           ! HEMCO options.
    3102             :           ! ------------------------------------------------------------
    3103             : 
    3104             :           ! Default mask scaling is 1.0 (no mask applied)
    3105             :           MaskScale = 1.0_sp
    3106             : 
    3107             :           ! If there is a mask applied to this scale factor ...
    3108             :           IF ( ASSOCIATED(MaskDct) ) THEN
    3109             :              CALL GetMaskVal ( MaskDct, I, J, &
    3110             :                                MaskScale, MaskFractions, RC )
    3111             :              IF ( RC /= HCO_SUCCESS ) THEN
    3112             :                 ERROR = 4
    3113             :                 EXIT
    3114             :              ENDIF
    3115             :           ENDIF
    3116             : 
    3117             :           ! We can skip this grid box if mask is completely zero
    3118             :           IF ( MaskScale <= 0.0_sp ) CYCLE
    3119             : 
    3120             :           ! Get current time index for this container and at this location
    3121             :           tIDx = tIDx_GetIndx( HcoState, ScalDct%Dta, I, J )
    3122             :           IF ( tIDx < 1 ) THEN
    3123             :              WRITE(*,*) 'Cannot get time slice index at location ',I,J,&
    3124             :                           ': ', TRIM(ScalDct%cName), tIDx
    3125             :              ERROR = 3
    3126             :              EXIT
    3127             :           ENDIF
    3128             : 
    3129             :           ! Check if this is a mask. If so, add mask values to the MASK
    3130             :           ! array. For now, we assume masks to be binary, i.e. 0 or 1.
    3131             :           ! We may want to change that in future to also support values
    3132             :           ! in between. This is especially important when regridding
    3133             :           ! high resolution masks onto coarser grids!
    3134             :           ! ------------------------------------------------------------
    3135             :           IF ( ScalDct%DctType == HCO_DCTTYPE_MASK ) THEN
    3136             : 
    3137             :              ! Get mask value
    3138             :              CALL GetMaskVal ( ScalDct, I, J, &
    3139             :                                TMPVAL,    MaskFractions, RC )
    3140             :              IF ( RC /= HCO_SUCCESS ) THEN
    3141             :                 ERROR = 4
    3142             :                 EXIT
    3143             :              ENDIF
    3144             : 
    3145             :              ! Pass to output mask
    3146             :              MASK(I,J,:) = MASK(I,J,:) * TMPVAL
    3147             : 
    3148             :              ! testing only
    3149             :              IF ( HCO_IsVerb(HcoState%Config%Err) .AND. I==1 .AND. J==1 ) THEN
    3150             :                 write(MSG,*) 'Mask field ', TRIM(ScalDct%cName),   &
    3151             :                      ' found and added to temporary mask.'
    3152             :                 CALL HCO_MSG(HcoState%Config%Err,MSG)
    3153             :              ENDIF
    3154             : 
    3155             :              ! Advance to next grid box
    3156             :              CYCLE
    3157             :           ENDIF! DctType=MASK
    3158             : 
    3159             :           ! ------------------------------------------------------------
    3160             :           ! For non-mask fields, apply scale factors to all levels
    3161             :           ! of the base field individually. If the scale factor
    3162             :           ! field has more than one vertical level, use the
    3163             :           ! vertical level closest to the corresponding vertical
    3164             :           ! level of the base emission field
    3165             :           ! ------------------------------------------------------------
    3166             : 
    3167             :           ! Get lower and upper vertical index
    3168             :           CALL GetVertIndx( HcoState, BaseDct,       isLevDct1,              &
    3169             :                             LevDct1,  LevDct1_Unit,  isLevDct2,              &
    3170             :                             LevDct2,  LevDct2_Unit,  I,                      &
    3171             :                             J,        LowLL,         UppLL,      RC         )
    3172             :           IF ( RC /= HCO_SUCCESS ) THEN
    3173             :              ERROR = 1 ! Will cause error
    3174             :              EXIT
    3175             :           ENDIF
    3176             : 
    3177             :           ! Loop over all vertical levels of the base field
    3178             :           DO L = LowLL,UppLL
    3179             :              ! If the vertical level exceeds the number of available
    3180             :              ! scale factor levels, use the highest available level.
    3181             :              IF ( L > ScalLL ) THEN
    3182             :                 TmpLL = ScalLL
    3183             :              ! Otherwise use the same vertical level index.
    3184             :              ELSE
    3185             :                 TmpLL = L
    3186             :              ENDIF
    3187             : 
    3188             :              ! Get scale factor for this grid box. Use same uniform
    3189             :              ! value if it's a scalar field
    3190             :              IF ( ScalDct%Dta%SpaceDim == 1 ) THEN
    3191             :                 TMPVAL = ScalDct%Dta%V2(tidx)%Val(1,1)
    3192             :              ELSEIF ( ScalDct%Dta%SpaceDim == 2 ) THEN
    3193             :                 TMPVAL = ScalDct%Dta%V2(tidx)%Val(I,J)
    3194             :              ELSE
    3195             :                 TMPVAL = ScalDct%Dta%V3(tidx)%Val(I,J,TmpLL)
    3196             :              ENDIF
    3197             : 
    3198             :              ! Set missing value to one
    3199             :              IF ( TMPVAL == HCO_MISSVAL ) TMPVAL = 1.0_sp
    3200             : 
    3201             :              ! Eventually apply mask scaling
    3202             :              IF ( MaskScale /= 1.0_sp ) THEN
    3203             :                 TMPVAL = TMPVAL * MaskScale
    3204             :              ENDIF
    3205             : 
    3206             :              ! For negative scale factor, proceed according to the
    3207             :              ! negative value setting specified in the configuration
    3208             :              ! file (NegFlag = 2: use this value):
    3209             :              IF ( TMPVAL < 0.0_sp .AND. HcoState%Options%NegFlag /= 2 ) THEN
    3210             : 
    3211             :                 ! NegFlag = 1: ignore and show warning
    3212             :                 IF ( HcoState%Options%NegFlag == 1 ) THEN
    3213             :                    ERROR = -1 ! Will prompt warning
    3214             :                    CYCLE
    3215             : 
    3216             :                 ! Return w/ error otherwise
    3217             :                 ELSE
    3218             :                    WRITE(*,*) 'Negative scale factor at ',I,J,TmpLL,tidx,&
    3219             :                               ': ', TRIM(ScalDct%cName), TMPVAL
    3220             :                    ERROR = 1 ! Will cause error
    3221             :                    EXIT
    3222             :                 ENDIF
    3223             :              ENDIF
    3224             : 
    3225             :              ! -------------------------------------------------------
    3226             :              ! Apply scale factor in accordance to field operator
    3227             :              ! -------------------------------------------------------
    3228             : 
    3229             :              ! Oper 1: multiply
    3230             :              IF ( ScalDct%Oper == 1 ) THEN
    3231             :                 OUTARR_3D(I,J,L) = OUTARR_3D(I,J,L) * TMPVAL
    3232             : 
    3233             :              ! Oper -1: divide
    3234             :              ELSEIF ( ScalDct%Oper == -1 ) THEN
    3235             :                 ! Ignore zeros to avoid NaN
    3236             :                 IF ( TMPVAL /= 0.0_sp ) THEN
    3237             :                    OUTARR_3D(I,J,L) = OUTARR_3D(I,J,L) / TMPVAL
    3238             :                 ENDIF
    3239             : 
    3240             :              ! Oper 2: square
    3241             :              ELSEIF ( ScalDct%Oper == 2 ) THEN
    3242             :                 OUTARR_3D(I,J,L) = OUTARR_3D(I,J,L) * TMPVAL * TMPVAL
    3243             : 
    3244             :              ! Return w/ error otherwise (Oper 3 is only allowed for masks!)
    3245             :              ELSE
    3246             :                 WRITE(*,*) 'Illegal operator for ', TRIM(ScalDct%cName), ScalDct%Oper
    3247             :                 ERROR = 2 ! Will cause error
    3248             :                 EXIT
    3249             :              ENDIF
    3250             : 
    3251             :           ENDDO !LL
    3252             : 
    3253             :           ! Verbose mode
    3254             :           if ( HCO_IsVerb(HcoState%Config%Err) .and. i == ix .and. j == iy ) then
    3255             :              write(MSG,*) 'Scale field ', TRIM(ScalDct%cName)
    3256             :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3257             :              write(MSG,*) 'Time slice: ', tIdx
    3258             :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3259             :              write(MSG,*) 'IX, IY: ', IX, IY
    3260             :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3261             :              write(MSG,*) 'Scale factor (IX,IY,L1): ', TMPVAL
    3262             :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3263             :              write(MSG,*) 'Mathematical operation : ', ScalDct%Oper
    3264             :              CALL HCO_MSG(HcoState%Config%Err,MSG)
    3265             : !             write(lun,*) 'Updt (IX,IY,L1): ', OUTARR_3D(IX,IY,1)
    3266             :           endif
    3267             : 
    3268             :        ENDDO !I
    3269             :        ENDDO !J
    3270             : !$OMP END PARALLEL DO
    3271             : 
    3272             :        ! error check
    3273             :        IF ( ERROR > 0 ) THEN
    3274             :           IF ( ERROR == 1 ) THEN
    3275             :              MSG = 'Negative scale factor found (aborted): ' // TRIM(ScalDct%cName)
    3276             :           ELSEIF ( ERROR == 2 ) THEN
    3277             :              MSG = 'Illegal mathematical operator for scale factor: ' // TRIM(ScalDct%cName)
    3278             :           ELSEIF ( ERROR == 3 ) THEN
    3279             :              MSG = 'Encountered negative time index for scale factor: ' // TRIM(ScalDct%cName)
    3280             :           ELSEIF ( ERROR == 4 ) THEN
    3281             :              MSG = 'Mask error in ' // TRIM(ScalDct%cName)
    3282             :           ELSE
    3283             :              MSG = 'Error when applying scale factor: ' // TRIM(ScalDct%cName)
    3284             :           ENDIF
    3285             :           ScalDct => NULL()
    3286             :           CALL HCO_ERROR( MSG, RC )
    3287             :           RETURN
    3288             :        ENDIF
    3289             : 
    3290             :        ! eventually prompt warning for negative values
    3291             :        IF ( ERROR == -1 ) THEN
    3292             :           MSG = 'Negative scale factor found (ignored): ' // TRIM(ScalDct%cName)
    3293             :           CALL HCO_WARNING( HcoState%Config%Err, MSG, RC )
    3294             :        ENDIF
    3295             : 
    3296             :        ! Free pointer
    3297             :        MaskDct => NULL()
    3298             : 
    3299             :     ENDDO ! N
    3300             :     ENDIF ! N > 0
    3301             : 
    3302             :     ! Update optional variables
    3303             :     IF ( PRESENT(UseLL) ) THEN
    3304             :        UseLL = 1
    3305             :        IF ( nnLL > 0 ) UseLL = NINT(REAL(TotLL,kind=sp)/REAL(nnLL,kind=sp))
    3306             :     ENDIF
    3307             : 
    3308             :     ! Weight output emissions by mask
    3309             :     OUTARR_3D = OUTARR_3D * MASK
    3310             : 
    3311             :     ! Cleanup and leave w/ success
    3312             :     ScalDct => NULL()
    3313             :     CALL HCO_LEAVE ( HcoState%Config%Err, RC )
    3314             : 
    3315             :   END SUBROUTINE Get_Current_Emissions_Adj
    3316             : !EOC
    3317             : #endif
    3318             : !EOC
    3319             : END MODULE HCO_Calc_Mod

Generated by: LCOV version 1.14