2515 lines
93 KiB
Fortran
2515 lines
93 KiB
Fortran
! $Id: mercury_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $
|
|
MODULE MERCURY_MOD
|
|
!
|
|
!******************************************************************************
|
|
! Module MERCURY_MOD contains variables and routines for the GEOS-CHEM
|
|
! mercury simulation. (eck, bmy, 12/14/04, 1/19/07)
|
|
!
|
|
! Module Variables:
|
|
! ============================================================================
|
|
! (1 ) AN_Hg0 (INTEGER) : Tracer index array for tagged anth Hg(0) regions
|
|
! (2 ) AN_Hg2 (INTEGER) : Tracer index array for tagged anth Hg(II) regions
|
|
! (3 ) AN_HgP (INTEGER) : Tracer index array for tagged anth HgP regions
|
|
! (4 ) COSZM (REAL*8 ) : Max daily value of COS( S. Z. Angle ) [unitless]
|
|
! (5 ) DRYHg2 (INTEGER) : Index for Hg2 in DEPSAV array (drydep freq)
|
|
! (6 ) DRYHgP (INTEGER) : Index for HgP in DEPSAV array (drydep freq)
|
|
! (7 ) EHg0_an (REAL*8 ) : Anthropogenic Hg0 emissions [kg/s]
|
|
! (8 ) EHg2_an (REAL*8 ) : Anthropogenic Hg2 emissions [kg/s]
|
|
! (9 ) EHgP_an (REAL*8 ) : Anthropogenic HgP emissions [kg/s]
|
|
! (10) EHg0_oc (REAL*8 ) : Hg0 emissions from oceans [kg/s]
|
|
! (11) EHg0_ln (REAL*8 ) : Re-emissions of Hg0 from land [kg/s]
|
|
! (12) EHg0_nt (REAL*8 ) : Hg0 emissions from natural land sources [kg/s]
|
|
! (13) TCOSZ (REAL*8 ) : Sum of COS( Solar Zenith Angle ) [unitless]
|
|
! (14) TTDAY (REAL*8 ) : Total daylight time at location (I,J) [minutes]
|
|
! (15) T44 (REAL*4 ) : Local array for drydep diagnostic
|
|
! (15) N_HgTAGS (INTEGER) : Number of tagged sources (1 or 8)
|
|
! (16) ZERO_DVEL(REAL*8 ) : Array with zero dry deposition velocity
|
|
! (17) ANTHRO_Hg_YEAR(INT): Anthropogenic Hg emissions year (1995 or 2000)
|
|
!
|
|
! Module Routines:
|
|
! ===========================================================================
|
|
! (1 ) CHEMMERCURY : Chemistry routine for Hg
|
|
! (2 ) CHEM_Hg0_Hg2 : Chemistry for Hg0, Hg2 and drydep of Hg2
|
|
! (3 ) RXN_Hg0_Hg2 : Conversion of Hg(0) --> Hg(II) via reduction rxn
|
|
! (4 ) RXN_Hg0 : Conversion of Hg(0) --> Hg(II) via oxidation rxns
|
|
! (5 ) RXN_Hg2_DRYD : Prod of Hg(II) from Hg(0); also Hg(II) drydep loss
|
|
! (6 ) RXN_Hg2 : Prod of Hg(II) from Hg(0)
|
|
! (7 ) CHEM_HGP : Chemistry (via drydep loss) for HgP
|
|
! (8 ) RXN_HgP_DRYD : Loss of HgP via drydep
|
|
! (9 ) EMISSMERCURY : Emissions for Hg
|
|
! (10) SRCHG0 : Applies emissions of Hg0
|
|
! (11) SRCHG2 : Applies emissions of Hg2
|
|
! (12) SRCHGP : Applies emissions of HgP
|
|
! (13) MERCURY_READYR : Reads mercury emissions and converts to [kg/s]
|
|
! (14) GET_LWC : Computes liquid water content as a function of T
|
|
! (15) GET_VCLDF : Computes volume cloud fraction
|
|
! (16) GET_O3 : Returns monthly mean O3 field
|
|
! (17) GET_OH : Returns monthly mean OH field (w/ diurnal scaling)
|
|
! (18) OHNO3TIME : Computes diurnal scaling for monthly mean OH
|
|
! (19) DEFINE_TAGGED_Hg : Defines tracer number for tagged Hg tracers
|
|
! (20) INIT_MERCURY : Allocates and zeroes module arrays
|
|
! (21) CLEANUP_MERCURY : Deallocates module arrays
|
|
!
|
|
! GEOS-CHEM modules referenced by mercury_mod.f
|
|
! ============================================================================
|
|
! (1 ) bpch2_mod.f : Module w/ routines for binary pch file I/O
|
|
! (2 ) comode_mod.f : Module w/ SMVGEAR allocatable arrays
|
|
! (3 ) dao_mod.f : Module w/ arrays for DAO met fields
|
|
! (4 ) diag_mod.f : Module w/ GEOS-CHEM diagnostic arrays
|
|
! (5 ) drydep_mod.f : Module w/ GEOS-CHEM dry deposition routines
|
|
! (6 ) error_mod.f : Module w/ NaN, other error check routines
|
|
! (7 ) global_o3_mod.f : Module w/ routines to read 3-D O3 field
|
|
! (8 ) global_oh_mod.f : Module w/ routines to read 3-D OH field
|
|
! (9 ) grid_mod.f : Module w/ horizontal grid information
|
|
! (10) logical_mod.f : Module w/ GEOS-CHEM logical switches
|
|
! (11) pbl_mix_mod.f : Module w/ routines for PBL height & mixing
|
|
! (12) pressure_mod.f : Module w/ routines to compute P(I,J,L)
|
|
! (13) regrid_1x1_mod.f : Module w/ routines to regrid 1x1 data
|
|
! (13) time_mod.f : Module w/ routines to compute date & time
|
|
! (14) tracer_mod.f : Module w/ GEOS-CHEM tracer array STT etc.
|
|
! (15) tracerid_mod.f : Module w/ pointers to tracers & emissions
|
|
! (16) transfer_mod.f : Module w/ routines to cast & resize arrays
|
|
!
|
|
! Nomenclature:
|
|
! ============================================================================
|
|
! (1 ) Hg(0) a.k.a. Hg0 : Elemental mercury
|
|
! (2 ) Hg(II) a.k.a. Hg2 : Divalent mercury
|
|
! (3 ) HgP : Particulate mercury
|
|
!
|
|
! Mercury Tracers (1-3 are always defined; 4-21 are defined for tagged runs)
|
|
! ============================================================================
|
|
! (1 ) Hg(0) : Hg(0) - total tracer
|
|
! (2 ) Hg(II) : Hg(II) - total tracer
|
|
! (3 ) HgP : HgP - total tracer
|
|
! ------------------------+---------------------------------------------------
|
|
! (4 ) Hg(0)_an : Hg(0) - North American anthropogenic
|
|
! (5 ) Hg(0)_ae : Hg(0) - European Anthropogenic
|
|
! (6 ) Hg(0)_aa : Hg(0) - Asian anthropogenic
|
|
! (7 ) Hg(0)_ar : Hg(0) - Rest of World Anthropogenic
|
|
! (8 ) Hg(0)_oc : Hg(0) - Ocean emission
|
|
! (9 ) Hg(0)_ln : Hg(0) - Land reemission
|
|
! (10) Hg(0)_nt : Hg(0) - Land natural emission
|
|
! ------------------------+---------------------------------------------------
|
|
! (11) Hg(II)_an : Hg(II) - North American anthropogenic
|
|
! (12) Hg(II)_ae : Hg(II) - European Anthropogenic
|
|
! (13) Hg(II)_aa : Hg(II) - Asian anthropogenic
|
|
! (14) Hg(II)_ar : Hg(II) - Rest of World Anthropogenic
|
|
! (15) Hg(II)_oc : Hg(II) - Ocean emission
|
|
! (16) Hg(II)_ln : Hg(II) - Land reemission
|
|
! (17) Hg(II)_nt : Hg(II) - Land natural emission
|
|
! ------------------------+---------------------------------------------------
|
|
! (18) HgP_an : HgP - North American anthropogenic
|
|
! (19) HgP_ae : HgP - European anthropogenic
|
|
! (20) HgP_aa : HgP - Asian anthropogenic
|
|
! (21) HgP_ar : HgP - Rest of world anthropogenic
|
|
! ------------------------+---------------------------------------------------
|
|
! (22) HgP_oc : HgP - Ocean emission (FOR FUTURE USE)
|
|
! (23) HgP_ln : HgP - Land reemission (FOR FUTURE USE)
|
|
! (24) HgP_nt : HgP - Land natural emission (FOR FUTURE USE)
|
|
!
|
|
! References:
|
|
! ============================================================================
|
|
! (1 ) Hall, B. (1995). "The gas phase oxidation of elemental mercury by
|
|
! ozone.", Water, Air, and Soil Pollution 80: 301-315.
|
|
! (2 ) Sommar, J., et al. (2001). "A kinetic study of the gas-phase
|
|
! reaction between the hydroxyl radical and atomic mercury."
|
|
! Atmospheric Environment 35: 3049-3054.
|
|
!
|
|
! NOTES:
|
|
! (1 ) Updated for reduction rxn and online Hg0 ocean flux. Now use
|
|
! diagnostic arrays from "diag03_mod.f". (eck, sas, bmy, 1/21/05)
|
|
! (2 ) Now references "pbl_mix_mod.f". Remove FEMIS array and routine
|
|
! COMPUTE_FEMIS. (bmy, 2/15/05)
|
|
! (3 ) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05)
|
|
! (4 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05)
|
|
! (5 ) Now references XNUMOL from "tracer_mod.f" (bmy, 10/25/05)
|
|
! (6 ) Various updates added for tagged Hg sim. (eck, sas, cdh, bmy, 4/6/06)
|
|
! (7 ) Updated IF statement in GET_LWC (cdh, bmy, 12/1/06)
|
|
! (8 ) Modified GET_O3 to read trop+strat O3 at all levels (phs, 1/19/07)
|
|
!******************************************************************************
|
|
!
|
|
IMPLICIT NONE
|
|
|
|
!=================================================================
|
|
! MODULE PRIVATE DECLARATIONS -- keep certain internal variables
|
|
! and routines from being seen outside "mercury_mod.f"
|
|
!=================================================================
|
|
|
|
! Make everything PRIVATE ...
|
|
PRIVATE
|
|
|
|
! ... except these routines
|
|
PUBLIC :: CHEMMERCURY
|
|
PUBLIC :: CLEANUP_MERCURY
|
|
PUBLIC :: INIT_MERCURY
|
|
PUBLIC :: EMISSMERCURY
|
|
|
|
!=================================================================
|
|
! MODULE VARIABLES
|
|
!=================================================================
|
|
|
|
! Scalars
|
|
INTEGER :: ANTHRO_Hg_YEAR
|
|
INTEGER :: DRYHg2
|
|
INTEGER :: DRYHgP
|
|
|
|
! Parameters
|
|
REAL*8, PARAMETER :: SMALLNUM = 1d-32
|
|
|
|
! Arrays
|
|
INTEGER, ALLOCATABLE :: AN_Hg0(:,:)
|
|
INTEGER, ALLOCATABLE :: AN_Hg2(:,:)
|
|
INTEGER, ALLOCATABLE :: AN_HgP(:,:)
|
|
REAL*8, ALLOCATABLE :: COSZM(:,:)
|
|
REAL*8, ALLOCATABLE :: EHg0_an(:,:)
|
|
REAL*8, ALLOCATABLE :: EHg2_an(:,:)
|
|
REAL*8, ALLOCATABLE :: EHgP_an(:,:)
|
|
REAL*8, ALLOCATABLE :: EHg0_oc(:,:,:)
|
|
REAL*8, ALLOCATABLE :: EHg0_ln(:,:)
|
|
REAL*8, ALLOCATABLE :: EHg0_nt(:,:)
|
|
REAL*4, ALLOCATABLE :: T44(:,:,:,:)
|
|
REAL*8, ALLOCATABLE :: TCOSZ(:,:)
|
|
REAL*8, ALLOCATABLE :: TTDAY(:,:)
|
|
REAL*8, ALLOCATABLE :: ZERO_DVEL(:,:)
|
|
|
|
!=================================================================
|
|
! MODULE ROUTINES -- follow below the "CONTAINS" statement
|
|
!=================================================================
|
|
CONTAINS
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE CHEMMERCURY
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine CHEMMERCURY is the driver routine for mercury chemistry
|
|
! in the GEOS-CHEM module. (eck, bmy, 12/6/04, 4/6/06)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now references routine GET_PBL_MAX_L from "pbl_mix_mod.f". Now
|
|
! references AD44 from "diag_mod.f". Now sum the levels from T44 into
|
|
! the AD44 array. Now references N_TRACERS from "tracer_mod.f".
|
|
! (bmy, 2/24/05)
|
|
! (2 ) Bug fix: Set T44 to 0e0 for single precision. Now allow for zero
|
|
! dry deposition velocity. Now call INIT_MERCURY from "input_mod.f"
|
|
! (bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE DIAG_MOD, ONLY : AD44
|
|
USE DRYDEP_MOD, ONLY : DEPSAV
|
|
USE ERROR_MOD, ONLY : DEBUG_MSG
|
|
USE GLOBAL_O3_MOD, ONLY : GET_GLOBAL_O3
|
|
USE GLOBAL_OH_MOD, ONLY : GET_GLOBAL_OH
|
|
USE PBL_MIX_MOD, ONLY : GET_PBL_MAX_L
|
|
USE LOGICAL_MOD, ONLY : LPRT
|
|
USE TIME_MOD, ONLY : GET_MONTH, ITS_A_NEW_MONTH
|
|
USE TRACER_MOD, ONLY : N_TRACERS
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
# include "CMN_DIAG" ! ND44
|
|
|
|
! Local variables
|
|
LOGICAL, SAVE :: FIRST = .TRUE.
|
|
INTEGER :: I, J, L, MONTH, N, PBL_MAX
|
|
|
|
!=================================================================
|
|
! CHEMMERCURY begins here!
|
|
!
|
|
! Read monthly mean OH and O3 fields
|
|
!=================================================================
|
|
IF ( ITS_A_NEW_MONTH() ) THEN
|
|
|
|
! Get the current month
|
|
MONTH = GET_MONTH()
|
|
|
|
! Read monthly mean OH and O3 from disk
|
|
CALL GET_GLOBAL_OH( MONTH )
|
|
IF ( LPRT ) CALL DEBUG_MSG( '### CHEMMERC: a GET_GLOBAL_OH' )
|
|
|
|
CALL GET_GLOBAL_O3( MONTH )
|
|
IF ( LPRT ) CALL DEBUG_MSG( '### CHEMMERC: a GET_GLOBAL_O3' )
|
|
|
|
ENDIF
|
|
|
|
!=================================================================
|
|
! Perform chemistry on Hg tracers
|
|
!=================================================================
|
|
|
|
! Compute diurnal scaling for OH
|
|
CALL OHNO3TIME
|
|
IF ( LPRT ) CALL DEBUG_MSG( 'CHEMMERCURY: a OHNO3TIME' )
|
|
|
|
! Zero dry deposition tmp array
|
|
IF ( ND44 > 0 ) THEN
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, L, N )
|
|
DO N = 1, N_TRACERS
|
|
DO L = 1, LLTROP
|
|
DO J = 1, JJPAR
|
|
DO I = 1, IIPAR
|
|
T44(I,J,L,N) = 0e0
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
ENDIF
|
|
|
|
!-------------------------
|
|
! Hg0 and Hg2 chemistry
|
|
!-------------------------
|
|
IF ( DRYHg2 > 0 ) THEN
|
|
|
|
! If DRYHG2 > 0 then drydep is active;
|
|
! pass drydep frequency to CHEM_Hg0_Hg2
|
|
CALL CHEM_Hg0_Hg2( DEPSAV(:,:,DRYHg2) )
|
|
IF ( LPRT ) CALL DEBUG_MSG( 'CHEMMERCURY: a CHEM_Hg0_Hg2' )
|
|
|
|
ELSE
|
|
|
|
! Otherwise pass zero drydep frequency
|
|
CALL CHEM_Hg0_Hg2( ZERO_DVEL )
|
|
IF ( LPRT ) CALL DEBUG_MSG( 'CHEMMERCURY: a CHEM_Hg0_Hg2' )
|
|
|
|
ENDIF
|
|
|
|
!--------------------------
|
|
! HgP chemistry
|
|
!--------------------------
|
|
IF ( DRYHgP > 0 ) THEN
|
|
|
|
! If DRYHgP > 0, then drydep is active;
|
|
! Pass drydep frequency to CHEM_HgP
|
|
CALL CHEM_HgP( DEPSAV(:,:,DRYHgP) )
|
|
IF ( LPRT ) CALL DEBUG_MSG( 'CHEMMERCURY: a CHEM_HgP' )
|
|
|
|
ELSE
|
|
|
|
! Otherwise pass zero drydep frequency
|
|
CALL CHEM_HgP( ZERO_DVEL )
|
|
IF ( LPRT ) CALL DEBUG_MSG( 'CHEMMERCURY: a CHEM_HgP' )
|
|
|
|
ENDIF
|
|
|
|
! Archive drydep fluxes into ND44
|
|
IF ( ND44 > 0 ) THEN
|
|
|
|
! Model layers where the PBL top occurs
|
|
PBL_MAX = GET_PBL_MAX_L()
|
|
|
|
! Sum levels into AD44
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, L, N )
|
|
DO N = 1, N_TRACERS
|
|
DO J = 1, JJPAR
|
|
DO I = 1, IIPAR
|
|
DO L = 1, PBL_MAX
|
|
AD44(I,J,N,1) = AD44(I,J,N,1) + T44(I,J,L,N)
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
ENDIF
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE CHEMMERCURY
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE CHEM_Hg0_Hg2( V_DEP_Hg2 )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine CHEM_Hg0_Hg2 is the chemistry subroutine for the oxidation/
|
|
! reduction of Hg0/Hg(II). For tracers with dry deposition, the loss rate
|
|
! of dry dep is combined in the chemistry loss term.
|
|
! (eck, bmy, 12/6/04, 1/9/06)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1 ) V_DEP_Hg2 (REAL*8) : Dry deposition velocity for Hg(II) [cm/s]
|
|
!
|
|
! Description of the chemistry mechanism:
|
|
! ============================================================================
|
|
! (1 ) Conversion from Hg(0) to Hg(II): Oxidation by O3 and OH
|
|
!
|
|
! Hg(0)(g)+ O3(g) --> Hg(II) , k = 3.0e-20 cm3 molec-1 s-1
|
|
! Source: Hall, 1995
|
|
!
|
|
! Hg(0)(g)+ OH(g) --> Hg(II) , k = 8.7e-14 cm3 s-1
|
|
! Source: Sommar et al. 2001
|
|
!
|
|
! (2 ) Aqueous-phase photochemical reduction of Hg(II) is included based
|
|
! on estimate of rate constant and scaled to OH concentrations.
|
|
!
|
|
! (3 ) Hg(II) is dry-deposited, kd = Dvel/DELZ (sec-1)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Updated for reduction reaction. Now use diagnostic arrays from
|
|
! "diag03_mod.f" (eck, bmy, 1/21/05)
|
|
! (2 ) Now references GET_FRAC_UNDER_PBLTOP from "pbl_mix_mod.f". Now
|
|
! performs drydep for all levels in the PBL. Changed Kred to 2.1e-10
|
|
! on advice of Noelle Eckley Selin. (bmy, 2/24/05)
|
|
! (3 ) Now references XNUMOL from "tracer_mod.f" (bmy, 10/25/05)
|
|
! (4 ) Now prevent divide-by-zero error. Now use ID_Hg0 and ID_Hg2 index
|
|
! arrays from "tracerid_mod.f". Also modified for updated ocean
|
|
! mercury module. Updated some constants. Also saves out diagnostic
|
|
! of Hg2 lost to rxn w/ seasalt. (eck, cdh, sas, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE DAO_MOD, ONLY : T, AD
|
|
USE DIAG03_MOD, ONLY : AD03_Hg2_Hg0, AD03_Hg2_O3, AD03_Hg2_OH
|
|
USE DIAG03_MOD, ONLY : AD03_Hg2_SS, LD03, ND03
|
|
USE LOGICAL_MOD, ONLY : LSPLIT
|
|
USE PBL_MIX_MOD, ONLY : GET_FRAC_UNDER_PBLTOP
|
|
USE TIME_MOD, ONLY : GET_TS_CHEM
|
|
USE TRACER_MOD, ONLY : STT, XNUMOL
|
|
USE TRACERID_MOD, ONLY : ID_Hg0, ID_Hg2, ID_Hg_tot, N_Hg_CATS
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Arguments
|
|
REAL*8, INTENT(IN) :: V_DEP_Hg2(IIPAR,JJPAR)
|
|
|
|
! Local variables
|
|
INTEGER :: I, J, L, N, NN
|
|
REAL*8 :: AREA_CM2, C_O3, C_OH
|
|
REAL*8 :: DRYDEP, DTCHEM, E_RKT
|
|
REAL*8 :: E_K1, E_K2, FA
|
|
REAL*8 :: FC, K1, K2
|
|
REAL*8 :: Ko, Kr, Kt
|
|
REAL*8 :: Kr_Kt, NK1, NK2
|
|
REAL*8 :: LOST_Hg0_O3, LOST_Hg0_OH, LWC
|
|
REAL*8 :: F_UNDER_TOP, RKT, E_SALT
|
|
REAL*8 :: LOST_Hg0(N_Hg_CATS)
|
|
REAL*8 :: LOST_SS(N_Hg_CATS)
|
|
REAL*8 :: Ox_Hg0(N_Hg_CATS)
|
|
|
|
! K for reaction Hg0 + O3 in cm3 molec-1 s-1 (Source: Hall '95)
|
|
REAL*8, PARAMETER :: K = 3.0d-20
|
|
|
|
! K for reaction Hg2 + OH in cm3 s-1
|
|
REAL*8, PARAMETER :: K_HG_OH = 8.7d-14
|
|
|
|
! Henry's Law constant for Hg2
|
|
REAL*8, PARAMETER :: HL = 1.4d6
|
|
|
|
! Gas constant??
|
|
REAL*8, PARAMETER :: R = 8.2d-2
|
|
|
|
! K for reduction (scaled to budget and OH conc)
|
|
REAL*8, PARAMETER :: Kred = 8.4d-10
|
|
|
|
! K for sea salt (eck, bmy, 4/6/06)
|
|
REAL*8, PARAMETER :: KSalt = 3.8d-5
|
|
|
|
! External functions
|
|
REAL*8, EXTERNAL :: BOXVL
|
|
|
|
!=================================================================
|
|
! CHEM_Hg0_Hg2 begins here!
|
|
!=================================================================
|
|
|
|
! Chemistry timestep [s]
|
|
DTCHEM = GET_TS_CHEM() * 60d0
|
|
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, L, NN, LOST_Hg0 )
|
|
!$OMP+PRIVATE( F_UNDER_TOP, C_O3, C_OH, FC, LWC )
|
|
!$OMP+PRIVATE( FA, K1, K2, Ko, Kr )
|
|
!$OMP+PRIVATE( Kt, Kr_Kt, RKT, E_RKT, E_K1 )
|
|
!$OMP+PRIVATE( E_K2, E_SALT, LOST_Hg0_O3, LOST_Hg0_OH, LOST_SS )
|
|
!$OMP+PRIVATE( Ox_Hg0 )
|
|
DO L = 1, LLPAR
|
|
DO J = 1, JJPAR
|
|
DO I = 1, IIPAR
|
|
|
|
! Initialize LOST_Hg0, Ox_Hg0 arrays
|
|
DO NN = 1, N_Hg_CATS
|
|
LOST_Hg0(NN) = 0d0
|
|
LOST_SS(NN) = 0d0
|
|
Ox_Hg0(NN) = 0d0
|
|
ENDDO
|
|
|
|
! Also initialize for ND03 diag
|
|
LOST_Hg0_O3 = 0d0
|
|
LOST_Hg0_OH = 0d0
|
|
|
|
! Fraction of box (I,J,L) underneath the PBL top [unitless]
|
|
F_UNDER_TOP = GET_FRAC_UNDER_PBLTOP( I, J, L )
|
|
|
|
! Monthly mean O3 and OH concentrations [molec/cm3]
|
|
C_O3 = GET_O3( I, J, L )
|
|
C_OH = GET_OH( I, J, L )
|
|
|
|
! Get fraction of cloud in the gridbox [unitless]
|
|
FC = GET_VCLDF( I, J, L )
|
|
|
|
! Get liquid water content in cloudy area of gridbox (m3/m3)
|
|
LWC = GET_LWC( T(I,J,L) ) * FC
|
|
|
|
! Define fraction of Hg(II) which is in air
|
|
FA = ( HL * R * T(I,J,L) * LWC )
|
|
FA = FA / ( 1d0 + FA )
|
|
|
|
! Define K's for the oxidation reactions
|
|
K1 = K * C_O3
|
|
K2 = K_HG_OH * C_OH
|
|
Ko = K1 + K2
|
|
|
|
! Define K for the reduction reaction. Include the fraction of
|
|
! Hg(II) in air within the Kreduction & scale to OH concentration
|
|
Kr = Kred * FA * C_OH
|
|
|
|
! Total rate constant: Oxidation + Reduction
|
|
Kt = Ko + Kr
|
|
|
|
! Ratio of Kr / Kt
|
|
IF ( Kt > SMALLNUM ) THEN
|
|
Kr_Kt = Kr / Kt
|
|
ELSE
|
|
Kr_Kt = SMALLNUM
|
|
ENDIF
|
|
|
|
! Kt * timestep (i.e. the argument for EXP) [unitless]
|
|
RKT = Kt * DTCHEM
|
|
|
|
! Compute the exponential terms for use below
|
|
E_RKT = EXP( -RKT )
|
|
E_K1 = EXP( -K1 * DTCHEM )
|
|
E_K2 = EXP( -K2 * DTCHEM )
|
|
E_SALT = EXP( -Ksalt * DTCHEM )
|
|
|
|
!==============================================================
|
|
! Hg(0) Chemistry: Conversion from Hg(0) to Hg(II)
|
|
!
|
|
! CASE 1: REDUCTION REACTION
|
|
! -------------------------------------------------------------
|
|
! Aqueous chem occurs if Kr>0, it's cloudy, and T > -15 C.
|
|
! In this case we have the reaction:
|
|
!
|
|
! New Hg(0) = { ( Old Hg(0) * EXP( -Kt * DT ) ) } +
|
|
! { ( Old Hg(0) + Old Hg(II) ) * Kr/Kt *
|
|
! ( 1 - EXP( -Kt * DT ) ) }
|
|
!
|
|
! where: Kr = K of the reduction rxn
|
|
! Kt = K of the total rxn (oxidation + reduction)
|
|
! DT = Chemistry timestep [s]
|
|
! Old Hg(0) = Hg(0) at start of this timestep
|
|
! Old Hg(II) = Hg(II) as start of this timestep
|
|
!
|
|
! The amount of Hg(0) lost in this rxn becomes Hg(II):
|
|
!
|
|
! Hg(0) converted to Hg(II) = Old Hg(0) - New Hg(0)
|
|
!
|
|
! CASE 2: OXIDATION REACTIONS
|
|
! -------------------------------------------------------------
|
|
! If aqueous chemistry does not happen, then Hg(0) is converted
|
|
! to Hg(II) via the oxidation rxns with rate constants K1, K2:
|
|
!
|
|
! New Hg(0) = Old_Hg(0) * EXP( -K1 * DT ) * EXP( -K2 * DT )
|
|
!
|
|
! The amt of Hg(0) lost in these rxns rxn becomes Hg(II):
|
|
!
|
|
! Hg(0) converted to Hg(II) = Old Hg(0) - New Hg(0)
|
|
!==============================================================
|
|
IF ( Kr > 0d0 .and. FC > 0d0 .and. T(I,J,L) > 258d0 ) THEN
|
|
|
|
!--------------------------------------------
|
|
! CASE 1: Total Hg(II) tracer, aq chem
|
|
!--------------------------------------------
|
|
|
|
! Loop over all Hg0 tracers
|
|
DO NN = 1, N_Hg_CATS
|
|
|
|
! Conversion of total Hg(0) --> Hg(II)
|
|
CALL RXN_Hg0_Hg2( I, J, L,
|
|
& ID_Hg0(NN), ID_Hg2(NN), RKT,
|
|
& E_RKT, Kr_Kt, Kt,
|
|
& Ko, Kr, DTCHEM,
|
|
& LOST_Hg0(NN), Ox_Hg0(NN) )
|
|
|
|
ENDDO
|
|
|
|
ELSE
|
|
|
|
!--------------------------------------------
|
|
! CASE 2: Total Hg(II) tracer, non-aq chem
|
|
!--------------------------------------------
|
|
|
|
! Loop over all Hg0 tracers
|
|
DO NN = 1, N_Hg_CATS
|
|
|
|
! Total Hg(0) loss by oxidation rxn
|
|
CALL RXN_Hg0( I, J, L,
|
|
& ID_Hg0(NN), E_K1, E_K2, LOST_Hg0(NN) )
|
|
|
|
! Gross oxidation flux Hg(0) -> Hg(II)
|
|
Ox_Hg0(NN) = LOST_Hg0(NN)
|
|
|
|
ENDDO
|
|
|
|
ENDIF
|
|
|
|
!==============================================================
|
|
! Compute Hg(II) production from OH and O3 rxns for diagnostic
|
|
!
|
|
! This is for the diagnostics OH and O3 prod of Hg(II).
|
|
! They are messed up a little since adding the reduction
|
|
! reaction haven't fixed them yet. (eck, 12/7/04)
|
|
!==============================================================
|
|
IF ( Ox_Hg0(ID_Hg_tot) > 0d0 ) THEN
|
|
|
|
! Avoid division by zero
|
|
IF ( ( K1 + K2 ) > 0d0 ) THEN
|
|
|
|
! Production of Hg(II) from O3 rxn [kg]
|
|
LOST_Hg0_O3 = ( K1 / ( K1 + K2 ) ) * Ox_Hg0(ID_Hg_tot)
|
|
|
|
! Production of Hg(II) from OH rxn [kg]
|
|
LOST_Hg0_OH = ( K2 / ( K1 + K2 ) ) * Ox_Hg0(ID_Hg_tot)
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
!==============================================================
|
|
! Hg(II) chemistry: Conversion from Hg(0) and drydep loss
|
|
!
|
|
! CASE 1: WITHIN THE PLANETARY BOUNDARY LAYER (PBL)
|
|
! -------------------------------------------------------------
|
|
! At the surface we have both dry deposition of Hg(II) plus
|
|
! conversion of Hg(0) into Hg(II). In this case we use the
|
|
! following rxns:
|
|
!
|
|
! CASE 1a: If Conv Hg(0) > 0:
|
|
! ---------------------------
|
|
! New Hg(II) = ( Old Hg(II) * EXP( -RKT ) ) +
|
|
! ( Conv Hg(0)/RKT * ( 1 - EXP( -RKT ) )
|
|
!
|
|
!
|
|
! CASE 1b: If Conv Hg(0) <= 0:
|
|
! ----------------------------
|
|
! New Hg(II) = ( Old Hg(II) + Conv Hg(0) ) * EXP( -RKT )
|
|
!
|
|
! Where: RKT = DTCHEM * Drydep Vel of Hg(II)
|
|
! "Conv Hg(0)" = Amt of Hg(0) that became Hg(II), which
|
|
! is archived from the Hg(0) rxns above
|
|
!
|
|
! CASE 2: OUTSIDE THE PLANETARY BOUNDARY LAYER (PBL)
|
|
! -------------------------------------------------------------
|
|
! At levels higher than the surface, we do not have drydep.
|
|
! Therefore we only have conversion of Hg(0) into Hg(II), and
|
|
! we use this rxn:
|
|
!
|
|
! New Hg(II) = Old Hg(II) + Conv Hg(0)
|
|
!
|
|
!
|
|
! NOTE: ND44 diagnostics are archived in RXN_Hg2_DRYD.
|
|
!==============================================================
|
|
|
|
! If we are in the PBL and there is nonzero drydep velocity ...
|
|
IF ( F_UNDER_TOP > 0d0 .and. V_DEP_Hg2(I,J) > 0d0 ) THEN
|
|
|
|
! Hg2 drydep frequency [1/s] -- F_UNDER_TOP accounts for the
|
|
! fraction of box (I,J,L) that is located beneath the PBL top
|
|
RKT = V_DEP_Hg2(I,J) * DTCHEM * F_UNDER_TOP
|
|
|
|
! Pre-compute exponential term
|
|
E_RKT = EXP( -RKT )
|
|
|
|
!-----------------------------------------------
|
|
! CASE 1: Total Hg(II) tracer, in PBL
|
|
!-----------------------------------------------
|
|
|
|
! Loop over all Hg2 tracers
|
|
DO NN = 1, N_Hg_CATS
|
|
|
|
! Compute new Hg(II) concentration in PBL
|
|
! Also return Hg2 lost to sea salt (eck, bmy, 4/6/06)
|
|
CALL RXN_Hg2_DRYD( I, J, L,
|
|
& ID_Hg2(NN), RKT, E_RKT,
|
|
& E_SALT, LOST_Hg0(NN), DTCHEM,
|
|
& LOST_SS(NN) )
|
|
|
|
ENDDO
|
|
|
|
ELSE
|
|
|
|
!--------------------------------------------
|
|
! CASE 2: Total Hg(II) tracer, outside PBL
|
|
!--------------------------------------------
|
|
|
|
! Loop over all Hg2 tracers
|
|
DO NN = 1, N_Hg_CATS
|
|
|
|
! Compute new concentration of total Hg(II) outside PBL [kg]
|
|
CALL RXN_Hg2( I, J, L, ID_Hg2(NN), LOST_Hg0(NN) )
|
|
|
|
ENDDO
|
|
|
|
ENDIF
|
|
|
|
!==============================================================
|
|
! ND03 diagnostic: Hg(II) production [kg]
|
|
!==============================================================
|
|
IF ( ND03 > 0 .and. L <= LD03 ) THEN
|
|
NN = ID_Hg_tot
|
|
AD03_Hg2_Hg0(I,J,L) = AD03_Hg2_Hg0(I,J,L) + LOST_Hg0(NN)
|
|
AD03_Hg2_OH(I,J,L) = AD03_Hg2_OH(I,J,L) + LOST_Hg0_OH
|
|
AD03_Hg2_O3(I,J,L) = AD03_Hg2_O3(I,J,L) + LOST_Hg0_O3
|
|
|
|
! Sea salt diagnostic is 2-D
|
|
IF ( L == 1 ) THEN
|
|
AD03_Hg2_SS(I,J,NN) = AD03_Hg2_SS(I,J,NN) + LOST_SS(NN)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE CHEM_Hg0_Hg2
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE RXN_Hg0_Hg2( I, J, L, N_Hg0, N_Hg2,
|
|
& RKT, E_RKT, Kr_Kt, Kt, Ko,
|
|
& Kr, DTCHEM, LOST_Hg0, Ox_Hg0 )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine RXN_Hg0_Hg2 computes the conversion of Hg(0) to Hg(II) via
|
|
! an aqueous chemistry reduction reaction. The formula used below is a s
|
|
! solution of the 2-box model equation. (eck, bmy, 12/14/04, 4/6/06)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : GEOS-CHEM lon, lat, alt grid box indices
|
|
! (4 ) N_Hg0 (INTEGER) : Index for Hg(0) total or tagged tracers
|
|
! (5 ) N_Hg2 (INTEGER) : Index for Hg(II) total or tagged tracers
|
|
! (6 ) RKT (REAL*8 ) : Value of R * k * Temp for this rxn [unitless]
|
|
! (7 ) E_RKT (REAL*8 ) : Value of EXP( - RKT ) [unitless]
|
|
! (8 ) Kr_Kt (REAL*8 ) : Ratio of Kr / Kt (redux K / total K) [unitless]
|
|
!
|
|
! Arguments as Output:
|
|
! ============================================================================
|
|
! (9 ) LOST_Hg0 (REAL*8 ) : Loss term: Hg(0) before - Hg(0) after [kg]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Changed equation to reflect reduction rxn. Also modified to output
|
|
! the gross oxidation flux. (eck, cdh, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE TRACER_MOD, ONLY : STT
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L, N_Hg0, N_Hg2
|
|
REAL*8, INTENT(IN) :: RKT, E_RKT, Kr_Kt, Kt, Kr
|
|
REAL*8, INTENT(IN) :: Ko, DTCHEM
|
|
REAL*8, INTENT(OUT) :: LOST_Hg0, Ox_Hg0
|
|
|
|
! Local variables
|
|
REAL*8 :: OLD_Hg0, OLD_Hg2, NEW_Hg0
|
|
|
|
!=================================================================
|
|
! RXN_Hg0_Hg2 begins here!
|
|
!=================================================================
|
|
|
|
! Error check tracer number
|
|
IF ( N_Hg0 < 1 .or. N_Hg2 < 1 ) RETURN
|
|
|
|
! Initial concentrations of Hg(0) and Hg(II) [kg]
|
|
OLD_Hg0 = MAX( STT(I,J,L,N_Hg0), SMALLNUM )
|
|
OLD_Hg2 = MAX( STT(I,J,L,N_Hg2), SMALLNUM )
|
|
|
|
! New concentration of Hg(0) [kg]
|
|
NEW_Hg0 = ( OLD_Hg0 * E_RKT ) +
|
|
& ((( OLD_Hg2 + OLD_Hg0 ) * Kr_Kt ) * ( 1d0 - E_RKT ) )
|
|
|
|
! Gross oxidation flux Hg(0) -> Hg(II)
|
|
Ox_Hg0 = ( Kt - Kr ) / Kt**2 *
|
|
& ( ( OLD_Hg0 + OLD_Hg2 ) * Kr *
|
|
& ( E_RKT - 1d0 + Kt * DTCHEM )
|
|
& + OLD_Hg0 * Kt * ( 1d0 -E_RKT ) )
|
|
|
|
! Set a floor of zero
|
|
OX_Hg0 = MAX( OX_Hg0, 0d0 )
|
|
|
|
! Save back into STT array [kg]
|
|
NEW_Hg0 = MAX( NEW_Hg0, SMALLNUM )
|
|
STT(I,J,L,N_Hg0) = NEW_Hg0
|
|
|
|
! Compute amount of Hg(0) which has now become Hg(II) [kg]
|
|
LOST_Hg0 = OLD_Hg0 - NEW_Hg0
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE RXN_Hg0_Hg2
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE RXN_Hg0( I, J, L, N, E_K1, E_K2, LOST_Hg0 )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine RXN_Hg0 computes the loss of Hg(0) by oxidation reactions with
|
|
! rate constants K1 and K2. (eck, bmy, 12/14/04)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : GEOS-CHEM lon, lat, alt grid box indices
|
|
! (4 ) N (INTEGER) : Index for Hg(0) total or tagged tracers
|
|
! (5 ) E_K1 (REAL*8 ) : Value of EXP( -K1 ) [unitless]
|
|
! (6 ) E_K2 (REAL*8 ) : Value of EXP( -K2 ) [unitless]
|
|
!
|
|
! Arguments as Output:
|
|
! ============================================================================
|
|
! (7 ) LOST_Hg0 (REAL*8 ) : Loss term: Hg(0) before - Hg(0) after [kg]
|
|
!
|
|
! NOTES:
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE TRACER_MOD, ONLY : STT
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L, N
|
|
REAL*8, INTENT(IN) :: E_K1, E_K2
|
|
REAL*8, INTENT(OUT) :: LOST_Hg0
|
|
|
|
! Local variables
|
|
REAL*8 :: OLD_Hg0, NEW_Hg0
|
|
|
|
!=================================================================
|
|
! RXN_Hg0 begins here!
|
|
!=================================================================
|
|
|
|
! Error check tracer number
|
|
IF ( N < 1 ) RETURN
|
|
|
|
! Initial concentration of Hg(0) [kg]
|
|
OLD_Hg0 = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! New concentration of Hg0 after oxidation rxns [kg]
|
|
NEW_Hg0 = MAX( ( OLD_Hg0 * E_K1 * E_K2 ), SMALLNUM )
|
|
|
|
! Save back into STT array [kg]
|
|
STT(I,J,L,N) = NEW_Hg0
|
|
|
|
! Compute amount of Hg(0) which has been oxidized into Hg(II) [kg]
|
|
LOST_Hg0 = OLD_Hg0 - NEW_Hg0
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE RXN_Hg0
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE RXN_Hg2_DRYD( I, J, L,
|
|
& N, RKT, E_RKT,
|
|
& E_SALT, LOST_Hg0, DTCHEM, LOST_SS )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine RXN_Hg2_DRYD computes the new concentration of Hg(II) from the
|
|
! converted Hg(0) plus the drydep of Hg(II). (eck, bmy, 12/14/04, 4/6/06)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : GEOS-CHEM lon, lat, alt grid box indices
|
|
! (4 ) N (INTEGER) : Index for Hg(II) total or tagged tracers
|
|
! (5 ) RKT (REAL*8 ) : Value of R * k * Temp for drydep [unitless]
|
|
! (6 ) E_RKT (REAL*8 ) : Value of EXP( - RKT ) [unitless]
|
|
! (7 ) E_SALT (REAL*8 ) : Value of EXP( -KSALT * DTCHEM )
|
|
! (8 ) LOST_Hg0 (REAL*8 ) : Amount of Hg(0) that became Hg(II) [kg]
|
|
! (9 ) DTCHEM (INTEGER) : Chemistry timestep [s]
|
|
!
|
|
! Arguments as Output:
|
|
! ============================================================================
|
|
! (10 ) LOST_SS (REAL*8 ) : Hg2 lost to sea salt rxn [kg]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now use 2 different solutions, depending on whether or not LOST_Hg0
|
|
! (amt of converted Hg0 -> Hg2) is positive. Also now archive the
|
|
! amount of total Hg(II) tracer lost to drydep for the ocean flux
|
|
! routines in "ocean_mercury_mod.f". (sas, bmy, 1/19/05)
|
|
! (2 ) Remove references to "diag_mod.f" and "CMN_DIAG". Now save drydep
|
|
! fluxes into T44 array. (bmy, 2/24/05)
|
|
! (3 ) Now references XNUMOL from "tracer_mod.f" (bmy, 10/25/05)
|
|
! (4 ) Now add E_SALT to account for uptake by sea salt. Now references
|
|
! IS_WATER from "dao_mod.f". Now uses ID_Hg2 and ID_Hg_tot from
|
|
! "tracerid_mod.f". Now references LDYNOCEAN from "logical_mod.f".
|
|
! Now do not call ADD_Hg2_DD if we are not using the dynamic ocean
|
|
! module. Now also return LOST_SS. (eck, cdh, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE DAO_MOD, ONLY : IS_WATER
|
|
USE GRID_MOD, ONLY : GET_AREA_CM2
|
|
USE LOGICAL_MOD, ONLY : LDYNOCEAN
|
|
USE OCEAN_MERCURY_MOD, ONLY : ADD_Hg2_DD
|
|
USE TRACER_MOD, ONLY : STT, XNUMOL
|
|
USE TRACERID_MOD, ONLY : IS_Hg2
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
# include "CMN_DIAG" ! ND44
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L, N
|
|
REAL*8, INTENT(IN) :: RKT, E_RKT, E_SALT, LOST_Hg0, DTCHEM
|
|
REAL*8, INTENT(OUT) :: LOST_SS
|
|
|
|
! Local variables
|
|
INTEGER :: NN
|
|
REAL*8 :: AREA_CM2, DRYDEP, OLD_Hg2
|
|
REAL*8 :: NEW_Hg2, TEMP_Hg2
|
|
|
|
!=================================================================
|
|
! RXN_Hg2_DRYD begins here!
|
|
!=================================================================
|
|
|
|
! Error check tracer number
|
|
IF ( N < 1 ) RETURN
|
|
|
|
! Initial concentration of Hg(II) [kg]
|
|
OLD_Hg2 = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
IF ( LOST_Hg0 > 0d0 ) THEN
|
|
|
|
!--------------------------------------------------------------
|
|
! CASE 1a: Amt of Hg(0) converted to Hg(II) is positive
|
|
! Use Solution #1 of the differential equation
|
|
!--------------------------------------------------------------
|
|
|
|
! Concentration of Hg(II) after drydep [kg]
|
|
! Factor in drydep at this time
|
|
NEW_Hg2 = ( OLD_Hg2 * E_RKT ) +
|
|
& ( LOST_Hg0/RKT * ( 1d0 - E_RKT ) )
|
|
|
|
ELSE
|
|
|
|
!--------------------------------------------------------------
|
|
! CASE 1b: Amt of Hg(0) converted to Hg(II) is negative or zero
|
|
! Use Solution #2 of the differential equation
|
|
!--------------------------------------------------------------
|
|
|
|
! New concentration of Hg(II) [kg]
|
|
! Assume drydep takes place after chemistry
|
|
NEW_Hg2 = ( OLD_Hg2 + LOST_Hg0 ) * E_RKT
|
|
|
|
ENDIF
|
|
|
|
! Also account for uptake of Hg(II) by sea salt aerosol
|
|
IF ( IS_WATER( I, J ) ) THEN
|
|
TEMP_Hg2 = NEW_Hg2 * E_SALT
|
|
ELSE
|
|
TEMP_Hg2 = NEW_Hg2
|
|
ENDIF
|
|
|
|
! Amount of Hg2 lost to sea salt
|
|
LOST_SS = MAX( NEW_Hg2 - TEMP_Hg2, SMALLNUM )
|
|
|
|
! Reset
|
|
NEW_Hg2 = TEMP_Hg2
|
|
|
|
! Save back into STT array [kg]
|
|
NEW_Hg2 = MAX( NEW_Hg2, SMALLNUM )
|
|
STT(I,J,L,N) = NEW_Hg2
|
|
|
|
!=================================================================
|
|
! Compute amount of Hg(II) lost to drydep
|
|
!=================================================================
|
|
|
|
! Amount of Hg(II) lost to dry deposition [kg]
|
|
DRYDEP = ( OLD_Hg2 - NEW_Hg2 ) + LOST_Hg0
|
|
|
|
! Archive Hg(II) lost to drydep [kg] for the ocean mercury flux routines
|
|
! in "ocean_mercury_mod.f" if necessary. Do not call ADD_Hg2_DD if the
|
|
IF ( IS_Hg2(N) .and. LDYNOCEAN ) THEN
|
|
CALL ADD_Hg2_DD( I, J, N, DRYDEP )
|
|
ENDIF
|
|
|
|
!=================================================================
|
|
! ND44 diagnostic: drydep flux of Hg(II) [molec/cm2/s]
|
|
!=================================================================
|
|
IF ( ND44 > 0 ) THEN
|
|
|
|
! Grid box surface area [cm2]
|
|
AREA_CM2 = GET_AREA_CM2( J )
|
|
|
|
! Amt of Hg(II) lost to drydep [molec/cm2/s]
|
|
DRYDEP = DRYDEP * XNUMOL(N) / ( AREA_CM2 * DTCHEM )
|
|
|
|
! Archive Hg(II) drydep flux in T44 array [molec/cm2/s]
|
|
T44(I,J,L,N) = T44(I,J,L,N) + DRYDEP
|
|
|
|
ENDIF
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE RXN_Hg2_DRYD
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE RXN_Hg2( I, J, L, N, LOST_Hg0 )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine RXN_Hg2 computes the new concentration of Hg(II) which is the
|
|
! old concentration plus the amount of converted Hg(0) (eck, bmy, 12/14/04)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : GEOS-CHEM lon, lat, alt grid box indices
|
|
! (4 ) N (INTEGER) : Index for Hg(II) total or tagged tracers
|
|
! (5 ) LOST_Hg0 (REAL*8 ) : Amount of Hg(0) that has become Hg(II) [kg]
|
|
!
|
|
! NOTES:
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE TRACER_MOD, ONLY : STT
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L, N
|
|
REAL*8, INTENT(IN) :: LOST_Hg0
|
|
|
|
! Local variables
|
|
REAL*8 :: OLD_Hg2, NEW_Hg2
|
|
|
|
!=================================================================
|
|
! RXN_Hg2 begins here!
|
|
!=================================================================
|
|
|
|
! Error check tracer number
|
|
IF ( N < 1 ) RETURN
|
|
|
|
! Initial concentration of Hg(II) [kg]
|
|
OLD_Hg2 = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! New concentration of Hg(II) is the old concentration
|
|
! plus the amount of Hg(0) which was converted to Hg(II) [kg]
|
|
NEW_Hg2 = MAX( ( OLD_Hg2 + LOST_Hg0 ), SMALLNUM )
|
|
|
|
! Save new concentration of Hg(II) to STT array [kg]
|
|
STT(I,J,L,N) = NEW_Hg2
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE RXN_Hg2
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE CHEM_HgP( V_DEP_HgP )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine CHEM_HgP is the chemistry subroutine for HgP (particulate
|
|
! mercury. HgP is lost via dry deposition. (eck, bmy, 12/7/04, 4/6/06)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1 ) V_DEP_HgP (REAL*8) : Dry deposition velocity for Hg(II) [cm/s]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Removed references to AD44 and "CMN_DIAG". Now compute drydep for all
|
|
! levels within the PBL. Now references ND03, LD03 from "diag03_mod.f".
|
|
! (bmy, 2/24/05)
|
|
! (2 ) Now references XNUMOL & XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05)
|
|
! (3 ) Now use ID_HgP index array from "tracerid_mod.f". (cdh, bmy, 1/9/06)
|
|
!******************************************************************************
|
|
!
|
|
! Refernces to F90 modules
|
|
USE DIAG03_MOD, ONLY : ND03, LD03
|
|
USE GRID_MOD, ONLY : GET_AREA_CM2
|
|
USE LOGICAL_MOD, ONLY : LSPLIT
|
|
USE PBL_MIX_MOD, ONLY : GET_FRAC_UNDER_PBLTOP, GET_PBL_MAX_L
|
|
USE TIME_MOD, ONLY : GET_TS_CHEM
|
|
USE TRACER_MOD, ONLY : STT, XNUMOL
|
|
USE TRACERID_MOD, ONLY : ID_HgP, N_Hg_CATS
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Arguments
|
|
REAL*8, INTENT(IN) :: V_DEP_HgP(IIPAR,JJPAR)
|
|
|
|
! Local variables
|
|
INTEGER :: I, J, L, NN, PBL_MAX
|
|
REAL*8 :: DTCHEM, E_KT, F_UNDER_TOP
|
|
|
|
!=================================================================
|
|
! CHEM_HgP begins here!
|
|
!=================================================================
|
|
|
|
! Chemistry timestep [s]
|
|
DTCHEM = GET_TS_CHEM() * 60d0
|
|
|
|
! Maximum extent of the PBL
|
|
PBL_MAX = GET_PBL_MAX_L()
|
|
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, L, F_UNDER_TOP, E_KT, NN )
|
|
!$OMP+SCHEDULE( DYNAMIC )
|
|
DO L = 1, PBL_MAX
|
|
DO J = 1, JJPAR
|
|
DO I = 1, IIPAR
|
|
|
|
! Fraction of box (I,J,L) underneath the PBL top [unitless]
|
|
F_UNDER_TOP = GET_FRAC_UNDER_PBLTOP( I, J, L )
|
|
|
|
! If we are in the PBL and there is nonzero drydep vel ...
|
|
IF ( F_UNDER_TOP > 0d0 .and. V_DEP_HgP(I,J) > 0d0 ) THEN
|
|
|
|
! Pre-compute the exponential term for use below [unitless]
|
|
E_KT = EXP( -V_DEP_HgP(I,J) * DTCHEM * F_UNDER_TOP )
|
|
|
|
! Compute new conc of HgP tracers after drydep [kg]
|
|
DO NN = 1, N_Hg_CATS
|
|
|
|
! Do dry deposition (skip undefined HgP tagged tracers)
|
|
IF ( ID_HgP(NN) > 0 ) THEN
|
|
CALL RXN_HgP_DRYD( I, J, L, ID_HgP(NN), E_KT, DTCHEM )
|
|
ENDIF
|
|
|
|
ENDDO
|
|
ENDIF
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
|
|
! Return to callwing program
|
|
END SUBROUTINE CHEM_HgP
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE RXN_HgP_DRYD( I, J, L, N, E_KT, DTCHEM )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine RXN_Hg0_DRYD computes the new concentration of HgP
|
|
! after dry deposition. ND44 diagnostics are also archived.
|
|
! (eck, bmy, 12/14/04, 4/6/06)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : GEOS-CHEM lon, lat, alt grid box indices
|
|
! (4 ) N (INTEGER) : Index for HgP total or tagged tracers
|
|
! (5 ) E_KT (REAL*8 ) : Value of EXP( -KT ) for drydep rxn [unitless]
|
|
! (6 ) DTCHEM (INTEGER) : Chemistry timestep [s]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Remove references to "diag_mod.f" and "CMN_DIAG". Now save drydep
|
|
! fluxes into T44 array. (bmy, 2/24/05)
|
|
! (2 ) Now references XNUMOL from "tracer_mod.f" (bmy, 10/25/05)
|
|
! (3 ) Now uses ID_HgP and ID_Hg_tot from "tracerid_mod.f" (cdh, bmy,4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE GRID_MOD, ONLY : GET_AREA_CM2
|
|
USE TRACER_MOD, ONLY : STT, XNUMOL
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
# include "CMN_DIAG" ! ND44
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L, N
|
|
REAL*8, INTENT(IN) :: DTCHEM, E_KT
|
|
|
|
! Local variables
|
|
INTEGER :: NN
|
|
REAL*8 :: AREA_CM2, DRYDEP, OLD_HgP, NEW_HgP
|
|
|
|
!=================================================================
|
|
! RXN_HgP_DRYD begins here!
|
|
!=================================================================
|
|
|
|
! Error check tracer number
|
|
IF ( N < 1 ) RETURN
|
|
|
|
! Initial concentration of HgP [kg]
|
|
OLD_HgP = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! New concentration of HgP after drydep [kg]
|
|
NEW_HgP = MAX( ( OLD_HgP * E_KT ), SMALLNUM )
|
|
|
|
! Save new concentration of HgP in STT [kg]
|
|
STT(I,J,L,N) = NEW_HgP
|
|
|
|
!=================================================================
|
|
! ND44 diagnostic: drydep flux of Hg(II) [molec/cm2/s]
|
|
!=================================================================
|
|
IF ( ND44 > 0 ) THEN
|
|
|
|
! Grid box surface area [cm2]
|
|
AREA_CM2 = GET_AREA_CM2( J )
|
|
|
|
! Amt of Hg(II) lost to drydep [molec/cm2/s]
|
|
DRYDEP = OLD_HgP - NEW_HgP
|
|
DRYDEP = ( DRYDEP * XNUMOL(N) ) / ( AREA_CM2 * DTCHEM )
|
|
|
|
! Archive Hg(II) drydep flux in T44 array [molec/cm2/s]
|
|
T44(I,J,L,N) = T44(I,J,L,N) + DRYDEP
|
|
|
|
ENDIF
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE RXN_HgP_DRYD
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE EMISSMERCURY
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine EMISSMERCURY is the driver routine for mercury emissions.
|
|
! (eck, bmy, 12/7/04, 4/6/06)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now call OCEAN_MERCURY_FLUX from "ocean_mercury_mod.f" to compute
|
|
! the emissions of Hg0 from the ocean instead of reading it from disk.
|
|
! (sas, bmy, 1/20/05)
|
|
! (2 ) Now no longer call COMPUTE_FEMIS, since we can get the same information
|
|
! from routine GET_FRAC_OF_PBL in "pbl_mix_mod.f" (bmy, 2/22/05)
|
|
! (3 ) Now modified for new ocean mercury module. (cdh, sas, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE ERROR_MOD, ONLY : DEBUG_MSG
|
|
USE LOGICAL_MOD, ONLY : LPRT, LDYNOCEAN
|
|
USE OCEAN_MERCURY_MOD, ONLY : OCEAN_MERCURY_FLUX
|
|
USE TIME_MOD, ONLY : GET_MONTH
|
|
USE TRACER_MOD, ONLY : STT
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Local variables
|
|
LOGICAL, SAVE :: FIRST = .TRUE.
|
|
INTEGER :: THISMONTH
|
|
|
|
!=================================================================
|
|
! EMISSMERCURY begins here!
|
|
!=================================================================
|
|
|
|
! First-time initialization
|
|
IF ( FIRST ) THEN
|
|
|
|
! Read anthro, ocean, land emissions of Hg from disk
|
|
CALL MERCURY_READYR
|
|
|
|
! Reset first-time flag
|
|
FIRST = .FALSE.
|
|
ENDIF
|
|
|
|
!=================================================================
|
|
! Call emission routines for Hg(0), Hg(II), and Hg(P)
|
|
!=================================================================
|
|
|
|
! Ocean flux of Hg(0)
|
|
IF ( LDYNOCEAN ) THEN
|
|
CALL OCEAN_MERCURY_FLUX( EHg0_oc )
|
|
IF ( LPRT ) CALL DEBUG_MSG( '### EMISSMERCURY: a OCEAN_FLUX' )
|
|
ENDIF
|
|
|
|
! Add Hg(0) source into STT [kg]
|
|
CALL SRCHg0
|
|
IF ( LPRT ) CALL DEBUG_MSG( '### EMISSMERCURY: a SRCHg0' )
|
|
|
|
! Add Hg(II) source into STT [kg]
|
|
CALL SRCHg2
|
|
IF ( LPRT ) CALL DEBUG_MSG( '### EMISSMERCURY: a SRCHg2' )
|
|
|
|
! Add HgP source into STT [kg]
|
|
CALL SRCHgP
|
|
IF ( LPRT ) CALL DEBUG_MSG( '### EMISSMERCURY: a SRCHgP' )
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE EMISSMERCURY
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE SRCHg0
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine SRCHg0 is the subroutine for Hg(0) emissions.
|
|
! Emissions of Hg(0) will be distributed throughout the boundary layer.
|
|
! (eck, cdh, bmy, 1/21/05, 4/6/06)
|
|
!
|
|
! Arguments as Input/Output:
|
|
! ============================================================================
|
|
! (1 ) TC (REAL*8) : Tracer concentration of Hg(0) [kg]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now use diagnostic arrays from "diag03_mod.f" (bmy, 1/21/05)
|
|
! (2 ) Now references GET_FRAC_OF_PBL and GET_PBL_MAX_L from "pbl_mix_mod.f".
|
|
! Remove reference to FEMIS. (bmy, 2/22/05)
|
|
! (3 ) EHg0_an is now a 2-D array. Modified for new ocean mercury module.
|
|
! Now use ID_Hg0 index array from "tracerid_mod.f". Now make sure
|
|
! STT does not underflow. (cdh, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! Reference to diagnostic arrays
|
|
USE DIAG03_MOD, ONLY : AD03, ND03
|
|
USE ERROR_MOD, ONLY : ERROR_STOP
|
|
USE LOGICAL_MOD, ONLY : LSPLIT
|
|
USE PBL_MIX_MOD, ONLY : GET_FRAC_OF_PBL, GET_PBL_MAX_L
|
|
USE TIME_MOD, ONLY : GET_TS_EMIS
|
|
USE TRACER_MOD, ONLY : STT
|
|
USE TRACERID_MOD, ONLY : ID_Hg_tot, ID_Hg_na, ID_Hg_eu, ID_Hg_as
|
|
USE TRACERID_MOD, ONLY : ID_Hg_rw, ID_Hg_oc, ID_Hg_ln, ID_Hg_nt
|
|
USE TRACERID_MOD, ONLY : ID_Hg0
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Local variables
|
|
INTEGER :: I, J, L, N, PBL_MAX
|
|
REAL*8 :: DTSRCE, E_Hg, F_OF_PBL, T_Hg, T_Hg_An
|
|
|
|
!=================================================================
|
|
! SRCHg0 begins here!
|
|
!=================================================================
|
|
|
|
! Emission timestep [s]
|
|
DTSRCE = GET_TS_EMIS() * 60d0
|
|
|
|
! Maximum extent of the PBL [model levels]
|
|
PBL_MAX = GET_PBL_MAX_L()
|
|
|
|
! Loop over grid boxes
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, L, N, T_Hg_An, T_Hg, F_OF_PBL, E_Hg )
|
|
DO J = 1, JJPAR
|
|
DO I = 1, IIPAR
|
|
|
|
! Compute total anthropogenic Hg(0) emissions
|
|
T_Hg_An = EHg0_an(I,J)
|
|
|
|
! Compute total Hg(0) emissions (anthro+oceans+land+natural)
|
|
T_Hg = T_Hg_An + EHg0_oc(I,J,ID_Hg_tot) +
|
|
& EHg0_ln(I,J) + EHg0_nt(I,J)
|
|
|
|
!==============================================================
|
|
! Partition Hg0 throughout PBL; store into STT [kg]
|
|
! Now make sure STT does not underflow (cdh, bmy, 4/6/06)
|
|
!==============================================================
|
|
|
|
! Loop up to max PBL level
|
|
DO L = 1, PBL_MAX
|
|
|
|
! Fraction of box (I,J,L) w/in the PBL [unitless]
|
|
F_OF_PBL = GET_FRAC_OF_PBL( I, J, L )
|
|
|
|
!-----------------
|
|
! Total Hg tracer
|
|
!-----------------
|
|
N = ID_Hg0(ID_Hg_tot)
|
|
E_Hg = F_OF_PBL * T_Hg
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
|
|
!-----------------
|
|
! Tagged tracers
|
|
!-----------------
|
|
IF ( LSPLIT ) THEN
|
|
|
|
!--------------------
|
|
! Primary emissions
|
|
!--------------------
|
|
|
|
! Anthro Hg0 by region
|
|
N = AN_Hg0(I,J)
|
|
E_Hg = F_OF_PBL * T_Hg_an
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Land re-emissions of Hg0
|
|
N = ID_Hg0(ID_Hg_ln)
|
|
E_Hg = F_OF_PBL * EHg0_ln(I,J)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Natural land sources of Hg0
|
|
N = ID_Hg0(ID_Hg_nt)
|
|
E_Hg = F_OF_PBL * EHg0_nt(I,J)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
!--------------------
|
|
! Ocean re-emissions
|
|
!--------------------
|
|
|
|
! Anthro re-emission from ocean in N. AMERICA
|
|
N = ID_Hg0(ID_Hg_na)
|
|
E_Hg = F_OF_PBL * EHg0_oc(I,J,ID_Hg_na)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Anthro re-emission from ocean in EUROPE
|
|
N = ID_Hg0(ID_Hg_eu)
|
|
E_Hg = F_OF_PBL * EHg0_oc(I,J,ID_Hg_eu)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Anthro re-emission from ocean in ASIA
|
|
N = ID_Hg0(ID_Hg_as)
|
|
E_Hg = F_OF_PBL * EHg0_oc(I,J,ID_Hg_as)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Anthro re-emission from ocean in REST OF WORLD
|
|
N = ID_Hg0(ID_Hg_rw)
|
|
E_Hg = F_OF_PBL * EHg0_oc(I,J,ID_Hg_rw)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Re-emission from ocean in OCEAN
|
|
N = ID_Hg0(ID_Hg_oc)
|
|
E_Hg = F_OF_PBL * EHg0_oc(I,J,ID_Hg_oc)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Re-emission from ocean in LAND REEMISSION
|
|
N = ID_Hg0(ID_Hg_ln)
|
|
E_Hg = F_OF_PBL * EHg0_oc(I,J,ID_Hg_ln)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
! Re-emission from ocean in NATURAL
|
|
N = ID_Hg0(ID_Hg_nt)
|
|
E_Hg = F_OF_PBL * EHg0_oc(I,J,ID_Hg_nt)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + ( E_Hg * DTSRCE )
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
ENDIF
|
|
ENDDO
|
|
|
|
!==============================================================
|
|
! ND03 diagnostic: Total Hg(0) emissions [kg]
|
|
! 1=anthro; 3=from ocean; 4=land re-emission; 5=natural src
|
|
!==============================================================
|
|
IF ( ND03 > 0 ) THEN
|
|
N = ID_Hg_tot
|
|
AD03(I,J,1) = AD03(I,J,1) + ( T_Hg_An * DTSRCE )
|
|
AD03(I,J,3) = AD03(I,J,3) + ( EHg0_oc(I,J,N) * DTSRCE )
|
|
AD03(I,J,4) = AD03(I,J,4) + ( EHg0_ln(I,J) * DTSRCE )
|
|
AD03(I,J,5) = AD03(I,J,5) + ( EHg0_nt(I,J) * DTSRCE )
|
|
ENDIF
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE SRCHg0
|
|
|
|
!-----------------------------------------------------------------------------
|
|
|
|
SUBROUTINE SRCHg2
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine SRCHg2 is the subroutine for Hg(II) emissions.
|
|
! Emissions of Hg(II) will be distributed throughout the boundary layer.
|
|
! (eck, bmy, 12/7/04, 4/6/06)
|
|
!
|
|
! Arguments as Input/Output:
|
|
! ============================================================================
|
|
! (1 ) TC (REAL*8) : Tracer concentration of Hg(II) [kg]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now use diagnostic arrays from "diag03_mod.f" (bmy, 1/21/05)
|
|
! (2 ) Now references GET_FRAC_OF_PBL and GET_PBL_MAX_L from "pbl_mix_mod.f".
|
|
! Remove reference to FEMIS. (bmy, 2/22/05)
|
|
! (3 ) EHg2_an is now a 2-D array. Now use ID_Hg2 index array from
|
|
! "tracerid_mod.f". Now make sure STT does not underflow.
|
|
! (eck, cdh, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! Reference to F90 modules
|
|
USE DIAG03_MOD, ONLY : AD03, ND03
|
|
USE ERROR_MOD, ONLY : ERROR_STOP
|
|
USE LOGICAL_MOD, ONLY : LSPLIT
|
|
USE PBL_MIX_MOD, ONLY : GET_FRAC_OF_PBL, GET_PBL_MAX_L
|
|
USE TIME_MOD, ONLY : GET_TS_EMIS
|
|
USE TRACER_MOD, ONLY : STT
|
|
USE TRACERID_MOD, ONLY : ID_Hg_tot, ID_Hg2
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Local variables
|
|
INTEGER :: I, J, L, N, PBL_MAX
|
|
REAL*8 :: DTSRCE, F_OF_PBL, E_Hg
|
|
|
|
!=================================================================
|
|
! SRCHg2 begins here!
|
|
!=================================================================
|
|
|
|
! Emission timestep [s]
|
|
DTSRCE = GET_TS_EMIS() * 60d0
|
|
|
|
! Maximum extent of the PBL [model levels]
|
|
PBL_MAX = GET_PBL_MAX_L()
|
|
|
|
! Loop over grid boxes
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, L, F_OF_PBL, E_Hg, N )
|
|
DO J = 1, JJPAR
|
|
DO I = 1, IIPAR
|
|
|
|
! Loop up to the max PBL layer
|
|
DO L = 1, PBL_MAX
|
|
|
|
! Fraction of box (I,J,L) w/in the PBL [unitless]
|
|
F_OF_PBL = GET_FRAC_OF_PBL( I, J, L )
|
|
|
|
! Partition total Hg2 into box (I,J,L) [kg]
|
|
E_Hg = F_OF_PBL * EHg2_an(I,J) * DTSRCE
|
|
|
|
!---------------------------
|
|
! Total anthro Hg(II) [kg]
|
|
!---------------------------
|
|
N = ID_Hg2(ID_Hg_tot)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + E_Hg
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
!---------------------------
|
|
! Tagged anthro Hg(II) [kg]
|
|
!---------------------------
|
|
IF ( LSPLIT ) THEN
|
|
N = AN_Hg2(I,J)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + E_Hg
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
ENDIF
|
|
ENDDO
|
|
|
|
!-------------------------------
|
|
! ND03 diag: Anthro Hg(II) [kg]
|
|
!-------------------------------
|
|
IF ( ND03 > 0 ) THEN
|
|
AD03(I,J,6) = AD03(I,J,6) + ( EHg2_an(I,J) * DTSRCE )
|
|
ENDIF
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE SRCHg2
|
|
|
|
!-----------------------------------------------------------------------------
|
|
|
|
SUBROUTINE SRCHgP
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine SRCHgP is the subroutine for HgP emissions.
|
|
! Emissions of HgP will be distributed throughout the boundary layer.
|
|
! (eck, bmy, 12/7/04, 4/6/06)
|
|
!
|
|
! Arguments as Input/Output:
|
|
! ============================================================================
|
|
! (1 ) TC (REAL*8) : Tracer concentration of Hg(II) [kg]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now use diagnostic arrays from "diag03_mod.f" (bmy, 1/21/05)
|
|
! (2 ) Now references GET_FRAC_OF_PBL and GET_PBL_MAX_L from "pbl_mix_mod.f".
|
|
! Remove reference to FEMIS. (bmy, 2/22/05)
|
|
! (3 ) EHgP_an is now a 2-D array. Now use ID_HgP index array from
|
|
! "tracerid_mod.f". Now make sure STT does not underflow.
|
|
! (eck, cdh, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! Reference to diagnostic arrays
|
|
USE DIAG03_MOD, ONLY : AD03, ND03
|
|
USE ERROR_MOD, ONLY : ERROR_STOP
|
|
USE LOGICAL_MOD, ONLY : LSPLIT
|
|
USE PBL_MIX_MOD, ONLY : GET_FRAC_OF_PBL, GET_PBL_MAX_L
|
|
USE TIME_MOD, ONLY : GET_TS_EMIS
|
|
USE TRACER_MOD, ONLY : STT
|
|
USE TRACERID_MOD, ONLY : ID_Hg_tot, ID_HgP
|
|
|
|
# include "CMN_SIZE" ! Size paramters
|
|
|
|
! Local variables
|
|
INTEGER :: I, J, L, N, PBL_MAX
|
|
REAL*8 :: DTSRCE, F_OF_PBL, E_Hg
|
|
|
|
!=================================================================
|
|
! SRCHgP begins here!
|
|
!=================================================================
|
|
|
|
! Chemistry timestep [s]
|
|
DTSRCE = GET_TS_EMIS() * 60d0
|
|
|
|
! Maximum extent of the PBL [model levels]
|
|
PBL_MAX = GET_PBL_MAX_L()
|
|
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, L, F_OF_PBL, E_Hg, N )
|
|
DO J = 1, JJPAR
|
|
DO I = 1, IIPAR
|
|
|
|
! Loop up to PBL top layer
|
|
DO L = 1, PBL_MAX
|
|
|
|
! Fraction of box (I,J,L) w/in the PBL [unitless]
|
|
F_OF_PBL = GET_FRAC_OF_PBL( I, J, L )
|
|
|
|
! Partition HgP into box (I,J,L) [kg]
|
|
E_Hg = F_OF_PBL * EHgP_an(I,J) * DTSRCE
|
|
|
|
!------------------------
|
|
! Total anthro HgP [kg]
|
|
!------------------------
|
|
N = ID_HgP(ID_Hg_tot)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + E_Hg
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
|
|
!------------------------
|
|
! Tagged anthro HgP [kg]
|
|
!------------------------
|
|
IF ( LSPLIT ) THEN
|
|
N = AN_HgP(I,J)
|
|
STT(I,J,L,N) = STT(I,J,L,N) + E_Hg
|
|
STT(I,J,L,N) = MAX( STT(I,J,L,N), SMALLNUM )
|
|
ENDIF
|
|
ENDDO
|
|
|
|
!----------------------------
|
|
! ND03 diag: Anthro HgP [kg]
|
|
!----------------------------
|
|
IF ( ND03 > 0 ) THEN
|
|
AD03(I,J,9) = AD03(I,J,9) + ( EHgP_an(I,J) * DTSRCE )
|
|
ENDIF
|
|
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE SRCHgP
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE MERCURY_READYR
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine MERCURY_READYR reads the year-invariant emissions for Mercury
|
|
! from anthropogenic, ocean, and land sources. (eck, bmy, 12/6/04, 4/6/06)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now read data from mercury_200501 subdirectory. Now compute oceanic
|
|
! Hg(0) emissions w/ ocean flux module instead of reading them from
|
|
! disk. Now use 1985 TAU values. (sas, bmy, 1/20/05)
|
|
! (2 ) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05)
|
|
! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05)
|
|
! (4 ) Now read anthro emissions on GEOS 1x1 grid in DATA_1x1_DIR. Also
|
|
! keep 2x25 and 4x5 files together in DATA_1x1_DIR. Also now use new
|
|
! land re-emissions files from Noelle Selin. (eck, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D, GET_RES_EXT
|
|
USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2
|
|
USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1
|
|
USE LOGICAL_MOD, ONLY : LDYNOCEAN
|
|
USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1
|
|
USE TIME_MOD, ONLY : EXPAND_DATE
|
|
USE TRANSFER_MOD, ONLY : TRANSFER_2D
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Local variables
|
|
INTEGER :: NYMD
|
|
REAL*4 :: ARRAY(IGLOB,JGLOB,1)
|
|
REAL*4 :: ARRAY1(I1x1,J1x1,1)
|
|
REAL*8 :: XTAU
|
|
REAL*8, PARAMETER :: SEC_PER_YR = 365.25d0 * 86400d0
|
|
CHARACTER(LEN=255) :: FILENAME
|
|
|
|
!=================================================================
|
|
! MERCURY_READYR begins here!
|
|
!
|
|
! Read annual anthropogenic mercury emissions [kg/s]
|
|
!=================================================================
|
|
|
|
! Mercury data is either for 1995 or 2000
|
|
NYMD = ( ANTHRO_Hg_YEAR * 10000 ) + 0101
|
|
XTAU = GET_TAU0( 1, 1, ANTHRO_Hg_YEAR )
|
|
|
|
!---------------------------
|
|
! Hg(0) emissions [kg/s]
|
|
!---------------------------
|
|
|
|
! Filename for anthropogenic mercury source
|
|
FILENAME = TRIM( DATA_DIR_1x1 ) //
|
|
& 'mercury_200511/GEIA_Hg0.geos.1x1.YYYY'
|
|
|
|
! Add year to the filename
|
|
CALL EXPAND_DATE( FILENAME, NYMD, 000000 )
|
|
|
|
! Echo info
|
|
WRITE( 6, 100 ) TRIM( FILENAME )
|
|
100 FORMAT( ' - MERCURY_READYR: Reading ', a )
|
|
|
|
! Read data in [kg/yr]
|
|
CALL READ_BPCH2( FILENAME, 'HG-SRCE', 1,
|
|
& XTAU, I1x1, J1x1,
|
|
& 1, ARRAY1, QUIET=.TRUE. )
|
|
|
|
! Regrid from 1x1 to the current grid
|
|
CALL DO_REGRID_1x1( 'kg', ARRAY1, EHg0_an )
|
|
|
|
! Convert from [kg/yr] to [kg/s]
|
|
EHg0_an = EHg0_an / SEC_PER_YR
|
|
|
|
!---------------------------
|
|
! Hg(II) emissions [kg/s]
|
|
!---------------------------
|
|
|
|
! Filename for anthropogenic mercury source
|
|
FILENAME = TRIM( DATA_DIR_1x1 ) //
|
|
& 'mercury_200511/GEIA_Hg2.geos.1x1.YYYY'
|
|
|
|
! Add year to the filename
|
|
CALL EXPAND_DATE( FILENAME, NYMD, 000000 )
|
|
|
|
! Echo info
|
|
WRITE( 6, 100 ) TRIM( FILENAME )
|
|
|
|
! Read data in [kg/yr]
|
|
CALL READ_BPCH2( FILENAME, 'HG-SRCE', 6,
|
|
& XTAU, I1x1, J1x1,
|
|
& 1, ARRAY1, QUIET=.TRUE. )
|
|
|
|
! Regrid from 1x1 to the current grid
|
|
CALL DO_REGRID_1x1( 'kg', ARRAY1, EHg2_an )
|
|
|
|
! Convert from [kg/yr] to [kg/s]
|
|
EHg2_an = EHg2_an / SEC_PER_YR
|
|
|
|
!---------------------------
|
|
! HgP emissions [kg/s]
|
|
!---------------------------
|
|
|
|
! Filename for anthropogenic mercury source
|
|
FILENAME = TRIM( DATA_DIR_1x1 ) //
|
|
& 'mercury_200511/GEIA_HgP.geos.1x1.YYYY'
|
|
|
|
! Add year to the filename
|
|
CALL EXPAND_DATE( FILENAME, NYMD, 000000 )
|
|
|
|
! Echo info
|
|
WRITE( 6, 100 ) TRIM( FILENAME )
|
|
|
|
! Read data in [kg/yr]
|
|
CALL READ_BPCH2( FILENAME, 'HG-SRCE', 9,
|
|
& XTAU, I1x1, J1x1,
|
|
& 1, ARRAY1, QUIET=.TRUE. )
|
|
|
|
! Regrid from 1x1 to the current grid
|
|
CALL DO_REGRID_1x1( 'kg', ARRAY1, EHgP_an )
|
|
|
|
! Convert from [kg/yr] to [kg/s]
|
|
EHgP_an = EHgP_an / SEC_PER_YR
|
|
|
|
!=================================================================
|
|
! Read annual emissions of anthropogenic Hg(0) which is
|
|
! re-emitted from the land [kg/s]
|
|
!=================================================================
|
|
|
|
! Use "generic" year 1985 for TAU values
|
|
XTAU = GET_TAU0( 1, 1, 1985 )
|
|
|
|
! Filename for re-emitted anthropogenic mercury
|
|
FILENAME = TRIM( DATA_DIR_1x1 ) //
|
|
& 'mercury_200511/Hg_land_reemission.' //
|
|
& GET_NAME_EXT_2D() // '.' // GET_RES_EXT()
|
|
|
|
! Echo info
|
|
WRITE( 6, 100 ) TRIM( FILENAME )
|
|
|
|
! Read data in [kg/yr]
|
|
CALL READ_BPCH2( FILENAME, 'HG-SRCE', 4,
|
|
& XTAU, IGLOB, JGLOB,
|
|
& 1, ARRAY(:,:,1), QUIET=.TRUE. )
|
|
|
|
! Cast to REAL*8 and resize
|
|
CALL TRANSFER_2D( ARRAY(:,:,1), EHg0_ln )
|
|
|
|
! Convert from [Mg/yr] to [kg/s]
|
|
EHg0_ln = EHg0_ln * 1000d0 / SEC_PER_YR
|
|
|
|
!=================================================================
|
|
! Read annual emissions of Hg(0) from natural land sources [kg/s]
|
|
!=================================================================
|
|
|
|
! Use "generic" year 1985 for TAU values
|
|
XTAU = GET_TAU0( 1, 1, 1985 )
|
|
|
|
! Filename for natural land-source mercury
|
|
FILENAME = TRIM( DATA_DIR_1x1 ) //
|
|
& 'mercury_200511/Hg_natural.' // GET_NAME_EXT_2D() //
|
|
& '.' // GET_RES_EXT()
|
|
|
|
! Echo info
|
|
WRITE( 6, 100 ) TRIM( FILENAME )
|
|
|
|
! TAU value corresponding to the data
|
|
XTAU = GET_TAU0( 1, 1, 1995 )
|
|
|
|
! Read data in [kg/yr]
|
|
CALL READ_BPCH2( FILENAME, 'HG-SRCE', 5,
|
|
& XTAU, IGLOB, JGLOB,
|
|
& 1, ARRAY(:,:,1), QUIET=.TRUE. )
|
|
|
|
! Cast to REAL*8 and resize
|
|
CALL TRANSFER_2D( ARRAY(:,:,1), EHg0_nt )
|
|
|
|
! Convert from [kg/yr] to [kg/s]
|
|
EHg0_nt = EHg0_nt / SEC_PER_YR
|
|
|
|
!=================================================================
|
|
! Read offline ocean Hg0 emissions (if LDYNOCEAN = .FALSE.)
|
|
!=================================================================
|
|
IF ( .not. LDYNOCEAN ) THEN
|
|
|
|
! File name
|
|
FILENAME = TRIM( DATA_DIR_1x1 ) //
|
|
& 'mercury_200511/Hg_ocean.geos.' // GET_RES_EXT()
|
|
|
|
! Echo info
|
|
WRITE( 6, 100 ) TRIM( FILENAME )
|
|
|
|
! TAU value corresponding to the data
|
|
XTAU = GET_TAU0( 1, 1, 1985 )
|
|
|
|
! Read data in [kg/yr]
|
|
CALL READ_BPCH2( FILENAME, 'HG-SRCE', 3,
|
|
& XTAU, IGLOB, JGLOB,
|
|
& 1, ARRAY(:,:,1), QUIET=.TRUE. )
|
|
|
|
! Cast to REAL*8 and resize
|
|
CALL TRANSFER_2D( ARRAY(:,:,1), EHg0_oc(:,:,1) )
|
|
|
|
! Convert from [kg/yr] to [kg/s]
|
|
EHg0_oc = EHg0_oc / SEC_PER_YR
|
|
|
|
ENDIF
|
|
|
|
!=================================================================
|
|
! Print totals to the screen in [Gg/yr]
|
|
!=================================================================
|
|
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
|
|
WRITE( 6, 110 )
|
|
WRITE( 6, '(a)' )
|
|
WRITE( 6, 111 ) SUM( EHg0_an ) * SEC_PER_YR * 1d-6
|
|
WRITE( 6, 113 ) SUM( EHg0_ln ) * SEC_PER_YR * 1d-6
|
|
WRITE( 6, 114 ) SUM( EHg0_nt ) * SEC_PER_YR * 1d-6
|
|
|
|
! Only write ocean total if we are doing offline ocean
|
|
IF ( .not. LDYNOCEAN ) THEN
|
|
WRITE( 6, 117 ) SUM( EHg0_oc ) * SEC_PER_YR * 1d-6
|
|
ENDIF
|
|
|
|
WRITE( 6, 115 ) SUM( EHg2_an ) * SEC_PER_YR * 1d-6
|
|
WRITE( 6, 116 ) SUM( EHgP_an ) * SEC_PER_YR * 1d-6
|
|
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
|
|
|
|
! FORMAT strings
|
|
110 FORMAT( 'M E R C U R Y E M I S S I O N S' )
|
|
111 FORMAT( 'Total Anthro Hg(0) : ', f7.3, ' [Gg/yr]' )
|
|
113 FORMAT( 'Total Re-Emitted Hg(0) : ', f7.3, ' [Gg/yr]' )
|
|
114 FORMAT( 'Total Natural Hg(0) : ', f7.3, ' [Gg/yr]' )
|
|
115 FORMAT( 'Total Anthro Hg(II) : ', f7.3, ' [Gg/yr]' )
|
|
116 FORMAT( 'Total Anthro HgP : ', f7.3, ' [Gg/yr]' )
|
|
117 FORMAT( 'Total Ocean Hg(0) : ', f7.3, ' [Gg/yr]' )
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE MERCURY_READYR
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
FUNCTION GET_LWC( T ) RESULT( LWC )
|
|
!
|
|
!******************************************************************************
|
|
! Function GET_LWC returns the cloud liquid water content at a GEOS-CHEM
|
|
! grid box as a function of temperature. (rjp, bmy, 10/31/02, 12/1/06)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1 ) T (REAL*8) : Temperature value at a GEOS-CHEM grid box [K]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now also add a case for T > 293 to the IF statement (cdh, bmy, 12/1/06)
|
|
!******************************************************************************
|
|
!
|
|
! Arguments
|
|
REAL*8, INTENT(IN) :: T
|
|
|
|
! Function value
|
|
REAL*8 :: LWC
|
|
|
|
!=================================================================
|
|
! GET_LWC begins here!
|
|
!=================================================================
|
|
|
|
! Compute Liquid water content in [g/m3]
|
|
IF ( T > 293d0 ) THEN
|
|
LWC = 0.2d0
|
|
|
|
ELSE IF ( T >= 280.d0 .AND. T <= 293.d0 ) THEN
|
|
LWC = 0.32d0 - 0.0060d0 * ( T - 273.D0 )
|
|
|
|
ELSE IF ( T >= 248.d0 .AND. T < 280.d0 ) THEN
|
|
LWC = 0.23d0 + 0.0065d0 * ( T - 273.D0 )
|
|
|
|
ELSE IF ( T < 248.d0 ) THEN
|
|
LWC = 0.07d0
|
|
|
|
ENDIF
|
|
|
|
! Convert from [g/m3] to [m3/m3]
|
|
LWC = LWC * 1.D-6
|
|
|
|
! Return to calling program
|
|
END FUNCTION GET_LWC
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
FUNCTION GET_VCLDF( I, J, L ) RESULT( VCLDF )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine GET_VCLDF computes the volume cloud fraction for Hg0 and Hg2
|
|
! chemistry. (eck, bmy, 12/6/04)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : GEOS-CHEM lon, lat, alt indices
|
|
!
|
|
! References:
|
|
! ============================================================================
|
|
! (1 ) Sundqvist et al. [1989]
|
|
!
|
|
! NOTES:
|
|
! (1 ) Copied from "sulfate_mod.f" but was made into a function since we are
|
|
! already looping over (I,J,L) in CHEM_Hg0_Hg2 (eck, bmy, 12/6/04)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE DAO_MOD, ONLY : RH
|
|
USE PRESSURE_MOD, ONLY : GET_PCENTER, GET_PEDGE
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L
|
|
|
|
! Local variables
|
|
REAL*8 :: PRES, PSFC, RH2, R0, B0
|
|
REAL*8, PARAMETER :: ZRT = 0.60d0, ZRS = 0.99d0
|
|
|
|
! Function value
|
|
REAL*8 :: VCLDF
|
|
|
|
!=================================================================
|
|
! GET_VCLDF begins here!
|
|
!=================================================================
|
|
|
|
! Surface pressure
|
|
PSFC = GET_PEDGE(I,J,1)
|
|
|
|
! Pressure at center of grid box L
|
|
PRES = GET_PCENTER(I,J,L)
|
|
|
|
! RH (from "dao_mod.f") is relative humidity [%]
|
|
! Convert to fraction and store in RH2
|
|
RH2 = RH(I,J,L) * 1.0d-2
|
|
|
|
! Terms from Sundqvist ???
|
|
R0 = ZRT + ( ZRS - ZRT ) * EXP( 1d0 - ( PSFC / PRES )**2.5 )
|
|
B0 = ( RH2 - R0 ) / ( 1d0 - R0 )
|
|
|
|
! Force B0 into the range 0-1
|
|
IF ( RH2 < R0 ) B0 = 0d0
|
|
IF ( B0 > 1d0 ) B0 = 1d0
|
|
|
|
! Volume cloud fraction
|
|
VCLDF = 1d0 - SQRT( 1d0 - B0 )
|
|
|
|
! Return to calling program
|
|
END FUNCTION GET_VCLDF
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
FUNCTION GET_O3( I, J, L ) RESULT( O3_MOLEC_CM3 )
|
|
!
|
|
!******************************************************************************
|
|
! Function GET_O3 returns monthly mean O3 for offline sulfate aerosol
|
|
! simulations. (bmy, 12/16/02, 1/19/07)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : Grid box indices for lon, lat, vertical level
|
|
!
|
|
! NOTES:
|
|
! (1 ) We assume SETTRACE has been called to define IDO3. (bmy, 12/16/02)
|
|
! (2 ) Now reference inquiry functions from "tracer_mod.f" (bmy, 7/20/04)
|
|
! (3 ) Now also read stratospheric O3 (phs, 1/19/07)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE DAO_MOD, ONLY : AD
|
|
USE GLOBAL_O3_MOD, ONLY : O3
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L
|
|
|
|
! Local variables
|
|
REAL*8 :: O3_MOLEC_CM3
|
|
|
|
! External functions
|
|
REAL*8, EXTERNAL :: BOXVL
|
|
|
|
!=================================================================
|
|
! GET_O3 begins here!
|
|
!=================================================================
|
|
|
|
! Get O3 [v/v] for this gridbox & month & convert to [molec/cm3]
|
|
O3_MOLEC_CM3 = O3(I,J,L) * ( 6.022d23 / 28.97d-3 ) *
|
|
& AD(I,J,L) / BOXVL(I,J,L)
|
|
|
|
! Return to calling program
|
|
END FUNCTION GET_O3
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
FUNCTION GET_OH( I, J, L ) RESULT( OH_MOLEC_CM3 )
|
|
!
|
|
!******************************************************************************
|
|
! Function GET_OH returns monthly mean OH and imposes a diurnal variation.
|
|
! (eck, bmy, 12/7/04)
|
|
!
|
|
! Arguments as Input:
|
|
! ============================================================================
|
|
! (1-3) I, J, L (INTEGER) : Grid box indices for lon, lat, vertical level
|
|
!
|
|
! NOTES:
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE DAO_MOD, ONLY : SUNCOS
|
|
USE GLOBAL_OH_MOD, ONLY : OH
|
|
USE TIME_MOD, ONLY : GET_TS_CHEM
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: I, J, L
|
|
|
|
! Local variables
|
|
INTEGER :: JLOOP
|
|
REAL*8 :: OH_MOLEC_CM3
|
|
|
|
!=================================================================
|
|
! GET_OH begins here!
|
|
!=================================================================
|
|
|
|
! 1-D grid box index for SUNCOS
|
|
JLOOP = ( (J-1) * IIPAR ) + I
|
|
|
|
! Test for sunlight...
|
|
IF ( SUNCOS(JLOOP) > 0d0 .and. TCOSZ(I,J) > 0d0 ) THEN
|
|
|
|
! Impose a diurnal variation on OH during the day
|
|
OH_MOLEC_CM3 = OH(I,J,L) *
|
|
& ( SUNCOS(JLOOP) / TCOSZ(I,J) ) *
|
|
& ( 1440d0 / GET_TS_CHEM() )
|
|
|
|
! Make sure OH is not negative
|
|
OH_MOLEC_CM3 = MAX( OH_MOLEC_CM3, 0d0 )
|
|
|
|
ELSE
|
|
|
|
! At night, OH goes to zero
|
|
OH_MOLEC_CM3 = 0d0
|
|
|
|
ENDIF
|
|
|
|
! Return to calling program
|
|
END FUNCTION GET_OH
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE OHNO3TIME
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine OHNO3TIME computes the sum of cosine of the solar zenith
|
|
! angle over a 24 hour day, as well as the total length of daylight.
|
|
! This is needed to scale the offline OH and NO3 concentrations.
|
|
! (rjp, bmy, 12/16/02, 12/8/04)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Copy code from COSSZA directly for now, so that we don't get NaN
|
|
! values. Figure this out later (rjp, bmy, 1/10/03)
|
|
! (2 ) Now replace XMID(I) with routine GET_XMID from "grid_mod.f".
|
|
! Now replace RLAT(J) with routine GET_YMID_R from "grid_mod.f".
|
|
! Removed NTIME, NHMSb from the arg list. Now use GET_NHMSb,
|
|
! GET_ELAPSED_SEC, GET_TS_CHEM, GET_DAY_OF_YEAR, GET_GMT from
|
|
! "time_mod.f". (bmy, 3/27/03)
|
|
! (3 ) Now store the peak SUNCOS value for each surface grid box (I,J) in
|
|
! the COSZM array. (rjp, bmy, 3/30/04)
|
|
! (4 ) Also added parallel loop over grid boxes (eck, bmy, 12/8/04)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE GRID_MOD, ONLY : GET_XMID, GET_YMID_R
|
|
USE TIME_MOD, ONLY : GET_NHMSb, GET_ELAPSED_SEC
|
|
USE TIME_MOD, ONLY : GET_TS_CHEM, GET_DAY_OF_YEAR, GET_GMT
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
# include "CMN_GCTM" ! Physical constants
|
|
|
|
! Local variables
|
|
LOGICAL, SAVE :: FIRST = .TRUE.
|
|
INTEGER :: I, IJLOOP, J, L, N, NT, NDYSTEP
|
|
REAL*8 :: A0, A1, A2, A3, B1, B2, B3
|
|
REAL*8 :: LHR0, R, AHR, DEC, TIMLOC, YMID_R
|
|
REAL*8 :: SUNTMP(MAXIJ)
|
|
|
|
!=================================================================
|
|
! OHNO3TIME begins here!
|
|
!=================================================================
|
|
|
|
! Solar declination angle (low precision formula, good enough for us):
|
|
A0 = 0.006918
|
|
A1 = 0.399912
|
|
A2 = 0.006758
|
|
A3 = 0.002697
|
|
B1 = 0.070257
|
|
B2 = 0.000907
|
|
B3 = 0.000148
|
|
R = 2.* PI * float( GET_DAY_OF_YEAR() - 1 ) / 365.
|
|
|
|
DEC = A0 - A1*cos( R) + B1*sin( R)
|
|
& - A2*cos(2*R) + B2*sin(2*R)
|
|
& - A3*cos(3*R) + B3*sin(3*R)
|
|
|
|
LHR0 = int(float( GET_NHMSb() )/10000.)
|
|
|
|
! Only do the following at the start of a new day
|
|
IF ( FIRST .or. GET_GMT() < 1e-5 ) THEN
|
|
|
|
! Zero arrays
|
|
TTDAY(:,:) = 0d0
|
|
TCOSZ(:,:) = 0d0
|
|
COSZM(:,:) = 0d0
|
|
|
|
! NDYSTEP is # of chemistry time steps in this day
|
|
NDYSTEP = ( 24 - INT( GET_GMT() ) ) * 60 / GET_TS_CHEM()
|
|
|
|
! NT is the elapsed time [s] since the beginning of the run
|
|
NT = GET_ELAPSED_SEC()
|
|
|
|
! Loop forward through NDYSTEP "fake" timesteps for this day
|
|
DO N = 1, NDYSTEP
|
|
|
|
! Zero SUNTMP array
|
|
SUNTMP(:) = 0d0
|
|
|
|
! Loop over surface grid boxes
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, YMID_R, IJLOOP, TIMLOC, AHR )
|
|
DO J = 1, JJPAR
|
|
|
|
! Grid box latitude center [radians]
|
|
YMID_R = GET_YMID_R( J )
|
|
|
|
DO I = 1, IIPAR
|
|
|
|
! Increment IJLOOP
|
|
IJLOOP = ( (J-1) * IIPAR ) + I
|
|
TIMLOC = real(LHR0) + real(NT)/3600.0 + GET_XMID(I)/15.0
|
|
|
|
DO WHILE (TIMLOC .lt. 0)
|
|
TIMLOC = TIMLOC + 24.0
|
|
ENDDO
|
|
|
|
DO WHILE (TIMLOC .gt. 24.0)
|
|
TIMLOC = TIMLOC - 24.0
|
|
ENDDO
|
|
|
|
AHR = abs(TIMLOC - 12.) * 15.0 * PI_180
|
|
|
|
!===========================================================
|
|
! The cosine of the solar zenith angle (SZA) is given by:
|
|
!
|
|
! cos(SZA) = sin(LAT)*sin(DEC) + cos(LAT)*cos(DEC)*cos(AHR)
|
|
!
|
|
! where LAT = the latitude angle,
|
|
! DEC = the solar declination angle,
|
|
! AHR = the hour angle, all in radians.
|
|
!
|
|
! If SUNCOS < 0, then the sun is below the horizon, and
|
|
! therefore does not contribute to any solar heating.
|
|
!===========================================================
|
|
|
|
! Compute Cos(SZA)
|
|
SUNTMP(IJLOOP) = sin(YMID_R) * sin(DEC) +
|
|
& cos(YMID_R) * cos(DEC) * cos(AHR)
|
|
|
|
! TCOSZ is the sum of SUNTMP at location (I,J)
|
|
! Do not include negative values of SUNTMP
|
|
TCOSZ(I,J) = TCOSZ(I,J) + MAX( SUNTMP(IJLOOP), 0d0 )
|
|
|
|
! COSZM is the peak value of SUMTMP during a day at (I,J)
|
|
! (rjp, bmy, 3/30/04)
|
|
COSZM(I,J) = MAX( COSZM(I,J), SUNTMP(IJLOOP) )
|
|
|
|
! TTDAY is the total daylight time at location (I,J)
|
|
IF ( SUNTMP(IJLOOP) > 0d0 ) THEN
|
|
TTDAY(I,J) = TTDAY(I,J) + DBLE( GET_TS_CHEM() )
|
|
ENDIF
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
|
|
! Increment elapsed time [sec]
|
|
NT = NT + ( GET_TS_CHEM() * 60 )
|
|
ENDDO
|
|
|
|
! Reset first-time flag
|
|
FIRST = .FALSE.
|
|
ENDIF
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE OHNO3TIME
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE DEFINE_TAGGED_Hg
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine DEFINE_TAGGED_Hg defines the tagged tracer numbers for
|
|
! anthropogenic (by geographic region) Hg0, Hg2, and HgP. The position of
|
|
! Hg2 and HgP in the DEPSAV array is also computed for future use. This
|
|
! routine only has to be called once at the start of the simulation.
|
|
! (eck, cdh, bmy, 12/15/04, 4/6/06)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now only define AN_Hg0, AN_Hg2, AN_HgP. Now use ID_Hg0, ID_Hg2, and
|
|
! ID_HgP index arrays from "tracerid_mod.f". (eck, cdh, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE GRID_MOD, ONLY : GET_XMID, GET_YMID
|
|
USE ERROR_MOD, ONLY : ERROR_STOP
|
|
USE TRACER_MOD, ONLY : N_TRACERS
|
|
USE TRACERID_MOD, ONLY : ID_Hg0, ID_Hg2, ID_HgP
|
|
USE TRACERID_MOD, ONLY : ID_Hg_tot, ID_Hg_na, ID_Hg_eu, ID_Hg_as
|
|
USE TRACERID_MOD, ONLY : ID_Hg_rw, ID_Hg_oc, ID_Hg_ln, ID_Hg_nt
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
|
|
! Local variables
|
|
INTEGER :: I, J
|
|
REAL*8 :: X, Y
|
|
CHARACTER(LEN=255) :: LOCATION
|
|
|
|
!=================================================================
|
|
! DEFINE_TAGGED_Hg begins here!
|
|
!=================================================================
|
|
|
|
! Location string for ERROR_STOP
|
|
LOCATION = 'DEFINE_TAGGED_Hg ("mercury_mod.f")'
|
|
|
|
!---------------------------------
|
|
! Anthropogenic tracer indices
|
|
!---------------------------------
|
|
!$OMP PARALLEL DO
|
|
!$OMP+DEFAULT( SHARED )
|
|
!$OMP+PRIVATE( I, J, X, Y )
|
|
|
|
! Loop over latitudes
|
|
DO J = 1, JJPAR
|
|
|
|
! Grid-box latitude [degrees]
|
|
Y = GET_YMID( J )
|
|
|
|
! Loop over longitudes
|
|
DO I = 1, IIPAR
|
|
|
|
! Grid box longitude [degrees]
|
|
X = GET_XMID( I )
|
|
|
|
! North American Anthro Hg
|
|
IF ( ( X >= -172.5 .and. X < -17.5 ) .and.
|
|
& ( Y >= 24.0 .and. Y < 88.0 ) ) THEN
|
|
AN_Hg0(I,J) = ID_Hg0(ID_Hg_na)
|
|
AN_Hg2(I,J) = ID_Hg2(ID_Hg_na)
|
|
AN_HgP(I,J) = ID_HgP(ID_Hg_na)
|
|
|
|
! European Anthro Hg (1st sub-box)
|
|
ELSE IF ( ( X >= -17.5 .and. X < 72.5 ) .and.
|
|
& ( Y >= 36.0 .and. Y < 45.0 ) ) THEN
|
|
AN_Hg0(I,J) = ID_Hg0(ID_Hg_eu)
|
|
AN_Hg2(I,J) = ID_Hg2(ID_Hg_eu)
|
|
AN_HgP(I,J) = ID_HgP(ID_Hg_eu)
|
|
|
|
! European Anthro Hg (2nd sub-box)
|
|
ELSE IF ( ( X >= -17.5 .and. X < 172.5 ) .and.
|
|
& ( Y >= 45.0 .and. Y < 88.0 ) ) THEN
|
|
AN_Hg0(I,J) = ID_Hg0(ID_Hg_eu)
|
|
AN_Hg2(I,J) = ID_Hg2(ID_Hg_eu)
|
|
AN_HgP(I,J) = ID_HgP(ID_Hg_eu)
|
|
|
|
! Asian Anthro Hg
|
|
ELSE IF ( ( X >= 70.0 .and. X < 152.5 ) .and.
|
|
& ( Y >= 8.0 .and. Y < 45.0 ) ) THEN
|
|
AN_Hg0(I,J) = ID_Hg0(ID_Hg_as)
|
|
AN_Hg2(I,J) = ID_Hg2(ID_Hg_as)
|
|
AN_HgP(I,J) = ID_HgP(ID_Hg_as)
|
|
|
|
! Rest-of-world Anthro Hg
|
|
ELSE
|
|
AN_Hg0(I,J) = ID_Hg0(ID_Hg_rw)
|
|
AN_Hg2(I,J) = ID_Hg2(ID_Hg_rw)
|
|
AN_HgP(I,J) = ID_HgP(ID_Hg_rw)
|
|
|
|
ENDIF
|
|
ENDDO
|
|
ENDDO
|
|
!$OMP END PARALLEL DO
|
|
|
|
!=================================================================
|
|
! Error check tracers: make sure they are not zero
|
|
! since this can cause array-out-of-bounds errors
|
|
!=================================================================
|
|
|
|
! Tagged Hg0
|
|
IF ( ANY( AN_Hg0 == 0 ) ) THEN
|
|
CALL ERROR_STOP( 'AN_Hg0 tracers are undefined!', LOCATION )
|
|
ENDIF
|
|
|
|
! Tagged Hg2
|
|
IF ( ANY( AN_Hg2 == 0 ) ) THEN
|
|
CALL ERROR_STOP( 'AN_Hg2 tracers are undefined!', LOCATION )
|
|
ENDIF
|
|
|
|
! Tagged Hg2
|
|
IF ( ANY( AN_HgP == 0 ) ) THEN
|
|
CALL ERROR_STOP( 'AN_HgP tracer are undefined!', LOCATION )
|
|
ENDIF
|
|
|
|
!---------------------------------
|
|
! Error check # of tracers
|
|
!---------------------------------
|
|
IF ( N_TRACERS < 21 ) THEN
|
|
CALL ERROR_STOP( 'Too few Hg tagged tracers!',
|
|
& 'DEFINE_TAGGED_Hg ("mercury_mod.f")' )
|
|
ENDIF
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE DEFINE_TAGGED_Hg
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE INIT_MERCURY( THIS_ANTHRO_Hg_YEAR )
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine INIT_MERCURY allocates and zeroes all module arrays.
|
|
! (eck, cdh, sas, bmy, 12/2/04, 4/6/06)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Removed reference to FEMIS array. Now also allocates and zeroes
|
|
! the T44 array. Added reference to CMN_DIAG. Now references
|
|
! N_TRACERS from "tracer_mod.f". (bmy, 2/24/05)
|
|
! (2 ) EHg0_an, EHg2_an, EHgP_an are now 2-D arrays. Now modified for
|
|
! updated ocean mercury module. (eck, cdh, sas, bmy, 4/6/06)
|
|
!******************************************************************************
|
|
!
|
|
! References to F90 modules
|
|
USE DRYDEP_MOD, ONLY : DEPNAME, NUMDEP
|
|
USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP
|
|
USE LOGICAL_MOD, ONLY : LSPLIT, LDRYD
|
|
USE TRACER_MOD, ONLY : N_TRACERS
|
|
USE TRACERID_MOD, ONLY : N_Hg_CATS
|
|
|
|
# include "CMN_SIZE" ! Size parameters
|
|
# include "CMN_DIAG" ! ND44
|
|
|
|
! Arguments
|
|
INTEGER, INTENT(IN) :: THIS_ANTHRO_Hg_YEAR
|
|
|
|
! Local variables
|
|
LOGICAL, SAVE :: IS_INIT = .FALSE.
|
|
INTEGER :: AS, N
|
|
CHARACTER(LEN=255) :: LOCATION
|
|
|
|
!=================================================================
|
|
! INIT_MERCURY begins here!
|
|
!=================================================================
|
|
|
|
! Return if we have already allocated arrays
|
|
IF ( IS_INIT ) RETURN
|
|
|
|
! Anthropogenic Hg emissions year
|
|
ANTHRO_Hg_YEAR = THIS_ANTHRO_Hg_YEAR
|
|
|
|
! Location string for ERROR_STOP
|
|
LOCATION = 'DEFINE_TAGGED_Hg ("mercury_mod.f")'
|
|
|
|
!=================================================================
|
|
! Allocate arrays
|
|
!=================================================================
|
|
ALLOCATE( COSZM( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'COSZM' )
|
|
COSZM = 0d0
|
|
|
|
ALLOCATE( EHg0_an( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'EHg0_an' )
|
|
EHg0_an = 0d0
|
|
|
|
ALLOCATE( EHg2_an( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'EHg2_an' )
|
|
EHg2_an = 0d0
|
|
|
|
ALLOCATE( EHgP_an( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'EHgP_an' )
|
|
EHgP_an = 0d0
|
|
|
|
ALLOCATE( EHg0_oc( IIPAR, JJPAR, N_Hg_CATS ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'EHg0_oc' )
|
|
EHg0_oc = 0d0
|
|
|
|
ALLOCATE( EHg0_ln( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'EHg0_ln' )
|
|
EHg0_ln = 0d0
|
|
|
|
ALLOCATE( EHg0_nt( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'EHg0_nt' )
|
|
EHg0_nt = 0d0
|
|
|
|
ALLOCATE( TCOSZ( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'TCOSZ' )
|
|
TCOSZ = 0d0
|
|
|
|
ALLOCATE( TTDAY( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'TTDAY' )
|
|
TTDAY = 0d0
|
|
|
|
! Allocate ZERO_DVEL if drydep is turned off
|
|
IF ( .not. LDRYD ) THEN
|
|
ALLOCATE( ZERO_DVEL( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'ZERO_DVEL' )
|
|
ZERO_DVEL = 0d0
|
|
ENDIF
|
|
|
|
!=================================================================
|
|
! Allocate & initialize arrays for tagged tracer indices
|
|
!=================================================================
|
|
IF ( LSPLIT ) THEN
|
|
|
|
! Tracer indices for tagged anthro regions
|
|
ALLOCATE( AN_Hg0( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'AN_Hg0' )
|
|
AN_Hg0 = 0d0
|
|
|
|
ALLOCATE( AN_Hg2( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'AN_Hg2' )
|
|
AN_Hg2 = 0d0
|
|
|
|
ALLOCATE( AN_HgP( IIPAR, JJPAR ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'AN_HgP' )
|
|
AN_HgP = 0d0
|
|
|
|
! Define the tagged tracer indices
|
|
CALL DEFINE_TAGGED_Hg
|
|
|
|
ENDIF
|
|
|
|
!=================================================================
|
|
! Locate the drydep species w/in the DEPSAV array (for ND44)
|
|
!=================================================================
|
|
|
|
! Initialize flags
|
|
DRYHg2 = 0d0
|
|
DRYHgP = 0d0
|
|
|
|
! If drydep is turned on ...
|
|
IF ( LDRYD ) THEN
|
|
|
|
! Loop over drydep species
|
|
DO N = 1, NUMDEP
|
|
|
|
! Locate by DEPNAME
|
|
SELECT CASE ( TRIM( DEPNAME(N) ) )
|
|
CASE( 'Hg2' )
|
|
DRYHg2 = N
|
|
CASE( 'HgP' )
|
|
DRYHgP = N
|
|
CASE DEFAULT
|
|
! nothing
|
|
END SELECT
|
|
ENDDO
|
|
|
|
! Temporary array for ND44 diagnostic
|
|
!----------------------------------------------------------------
|
|
! Prior to 4/6/06:
|
|
! For now, comment this out so that MERCURY MENU can be placed
|
|
! above the DIAGNOSTIC MENU in "input.geos" (bmy, 2/27/06)
|
|
!IF ( ND44 > 0 ) THEN
|
|
!----------------------------------------------------------------
|
|
ALLOCATE( T44( IIPAR, JJPAR, LLTROP, N_TRACERS ), STAT=AS )
|
|
IF ( AS /= 0 ) CALL ALLOC_ERR( 'T44' )
|
|
T44 = 0e0
|
|
!----------------------------------------------------------------
|
|
! Prior to 4/6/06:
|
|
! For now, comment this out so that MERCURY MENU can be placed
|
|
! above the DIAGNOSTIC MENU in "input.geos" (bmy, 2/27/06)
|
|
!ENDIF
|
|
!----------------------------------------------------------------
|
|
ENDIF
|
|
|
|
! Reset IS_INIT, since we have already allocated arrays
|
|
IS_INIT = .TRUE.
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE INIT_MERCURY
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
SUBROUTINE CLEANUP_MERCURY
|
|
!
|
|
!******************************************************************************
|
|
! Subroutine CLEANUP_MERCURY deallocates all module arrays.
|
|
! (eck, bmy, 12/6/04, 2/24/05)
|
|
!
|
|
! NOTES:
|
|
! (1 ) Now deallocate MLD, NPP, RAD (sas, bmy, 1/18/05)
|
|
! (2 ) Now deallocate T44 (bmy, 2/24/05)
|
|
!******************************************************************************
|
|
!
|
|
!=================================================================
|
|
! CLEANUP_MERCURY begins here!
|
|
!=================================================================
|
|
IF ( ALLOCATED( AN_Hg0 ) ) DEALLOCATE( AN_Hg0 )
|
|
IF ( ALLOCATED( AN_Hg2 ) ) DEALLOCATE( AN_Hg2 )
|
|
IF ( ALLOCATED( AN_HgP ) ) DEALLOCATE( AN_HgP )
|
|
IF ( ALLOCATED( COSZM ) ) DEALLOCATE( COSZM )
|
|
IF ( ALLOCATED( EHg0_an ) ) DEALLOCATE( EHg0_an )
|
|
IF ( ALLOCATED( EHg2_an ) ) DEALLOCATE( EHg2_an )
|
|
IF ( ALLOCATED( EHgP_an ) ) DEALLOCATE( EHgP_an )
|
|
IF ( ALLOCATED( EHg0_oc ) ) DEALLOCATE( EHg0_oc )
|
|
IF ( ALLOCATED( EHg0_ln ) ) DEALLOCATE( EHg0_ln )
|
|
IF ( ALLOCATED( EHg0_nt ) ) DEALLOCATE( EHg0_nt )
|
|
IF ( ALLOCATED( TCOSZ ) ) DEALLOCATE( TCOSZ )
|
|
IF ( ALLOCATED( T44 ) ) DEALLOCATE( T44 )
|
|
IF ( ALLOCATED( TTDAY ) ) DEALLOCATE( TTDAY )
|
|
|
|
! Return to calling program
|
|
END SUBROUTINE CLEANUP_MERCURY
|
|
|
|
!------------------------------------------------------------------------------
|
|
|
|
! End of module
|
|
END MODULE MERCURY_MOD
|