diff --git a/code/BLKSLV.f b/code/BLKSLV.f new file mode 100644 index 0000000..78e2c3f --- /dev/null +++ b/code/BLKSLV.f @@ -0,0 +1,87 @@ +C $Id: BLKSLV.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + SUBROUTINE BLKSLV +C----------------------------------------------------------------------- +C Solves the block tri-diagonal system: +C A(I)*X(I-1) + B(I)*X(I) + C(I)*X(I+1) = H(I) +C----------------------------------------------------------------------- + IMPLICIT NONE +# include "jv_mie.h" + integer i, j, k, id + real*8 sum +C-----------UPPER BOUNDARY ID=1 + CALL GEN(1) + CALL MATIN4 (B) + DO I=1,N + RR(I,1) = 0.0d0 + DO J=1,N + SUM = 0.0d0 + DO K=1,N + SUM = SUM - B(I,K)*CC(K,J) + ENDDO + DD(I,J,1) = SUM + RR(I,1) = RR(I,1) + B(I,J)*H(J) + ENDDO + ENDDO +C----------CONTINUE THROUGH ALL DEPTH POINTS ID=2 TO ID=ND-1 + DO ID=2,ND-1 + CALL GEN(ID) + DO I=1,N + DO J=1,N + B(I,J) = B(I,J) + A(I)*DD(I,J,ID-1) + ENDDO + H(I) = H(I) - A(I)*RR(I,ID-1) + ENDDO + CALL MATIN4 (B) + DO I=1,N + RR(I,ID) = 0.0d0 + DO J=1,N + RR(I,ID) = RR(I,ID) + B(I,J)*H(J) + DD(I,J,ID) = - B(I,J)*C1(J) + ENDDO + ENDDO + ENDDO +C---------FINAL DEPTH POINT: ND + CALL GEN(ND) + DO I=1,N + DO J=1,N + SUM = 0.0d0 + DO K=1,N + SUM = SUM + AA(I,K)*DD(K,J,ND-1) + ENDDO + B(I,J) = B(I,J) + SUM + H(I) = H(I) - AA(I,J)*RR(J,ND-1) + ENDDO + ENDDO + CALL MATIN4 (B) + DO I=1,N + RR(I,ND) = 0.0d0 + DO J=1,N + RR(I,ND) = RR(I,ND) + B(I,J)*H(J) + ENDDO + ENDDO +C-----------BACK SOLUTION + DO ID=ND-1,1,-1 + DO I=1,N + DO J=1,N + RR(I,ID) = RR(I,ID) + DD(I,J,ID)*RR(J,ID+1) + ENDDO + ENDDO + ENDDO +C----------MEAN J & H + DO ID=1,ND,2 + FJ(ID) = 0.0d0 + DO I=1,N + FJ(ID) = FJ(ID) + RR(I,ID)*WT(I) + ENDDO + ENDDO + DO ID=2,ND,2 + FJ(ID) = 0.0d0 + DO I=1,N + FJ(ID) = FJ(ID) + RR(I,ID)*WT(I)*EMU(I) + ENDDO + ENDDO +C Output fluxes for testing purposes +c CALL CH_FLUX +c + RETURN + END diff --git a/code/CLDSRF.f b/code/CLDSRF.f new file mode 100644 index 0000000..a7cf487 --- /dev/null +++ b/code/CLDSRF.f @@ -0,0 +1,93 @@ +C $Id: CLDSRF.f,v 1.1 2009/06/09 21:51:51 daven Exp $ + SUBROUTINE CLDSRF( ODCOL, SA ) +C----------------------------------------------------------------------- +c Routine to set cloud and surface properties +C----------------------------------------------------------------------- +C Add the following input variables for CTM interface (bmy, 9/13/99) +C +C Variable Type Dimensn Units Description +C -------- ---- ------- ----- ----------- +C ODCOL dble [LPAR] - Vertical optical depth profile +C SA dble - - Surface Albedo +C----------------------------------------------------------------------- +c rflect Surface albedo (Lambertian) +c odmax Maximum allowed optical depth, above which they are scaled +c odcol Optical depth at each model level +c odsum Column optical depth +c nlbatm Level of lower photolysis boundary - usually surface +C----------------------------------------------------------------------- + IMPLICIT NONE + +# include "cmn_fj.h" +# include "jv_cmn.h" + +C=============== INPUT PARAMETERS ====================================== + REAL*8, INTENT(INOUT) :: ODCOL(LPAR) + REAL*8, INTENT(IN) :: SA + +C=============== LOCAL VARIABLES ======================================= + integer i, j, k + real*8 odsum, odmax, odtot +c +c Default lower photolysis boundary as bottom of level 1 + nlbatm = 1 +c +c Set surface albedo + RFLECT = dble(SA) + RFLECT = max(0.d0,min(1.d0,RFLECT)) +c +c Zero aerosol column + do k=1,MX + do i=1,NB + AER(k,i) = 0.d0 + enddo + enddo +c +c Scale optical depths as appropriate - limit column to 'odmax' + odmax = 200.d0 + odsum = 0.d0 + do i=1,lpar + odcol(i) = dble(odcol(i)) + odsum = odsum + odcol(i) + enddo + if(odsum.gt.odmax) then + odsum = odmax/odsum + do i=1,lpar + odcol(i) = odcol(i)*odsum + enddo + odsum = odmax + endif +c +c Use clear-sky conditions +c do i=1,jpnl +c odcol(i)=0.d0 +c enddo +c +c Set sub-division switch if appropriate + odtot=0.d0 + jadsub(nb)=0 + jadsub(nb-1)=0 + do i=nb-1,1,-1 + k=2*i + jadsub(k)=0 + jadsub(k-1)=0 + odtot=odtot+odcol(i) + if(odtot.gt.0.d0.and.odcol(i).ne.0.d0.and. + $ dtausub.gt.0.d0) then + if(odtot.le.dtausub) then + jadsub(k)=1 + jadsub(k-1)=1 + elseif(odtot.gt.dtausub) then + jadsub(k)=1 + jadsub(k-1)=0 + do j=1,2*(i-1) + jadsub(j)=0 + enddo + go to 20 + endif + endif + enddo + 20 continue +c + return + end diff --git a/code/CMN b/code/CMN new file mode 100644 index 0000000..2a216d3 --- /dev/null +++ b/code/CMN @@ -0,0 +1,40 @@ +! $Id: CMN,v 1.1 2009/06/09 21:51:52 daven Exp $ + !================================================================= + ! NOTES: + ! (1 ) Changed RCS ID tag comment character from "C" to "!" to + ! allow freeform compilation. Also added the & continuation + ! characters in column 73 to allow header files to be + ! included in F90 freeform files. (bmy, 6/25/02) + ! (2 ) Commented out P, we now use routines from "pressure_mod.f" + ! to compute pressure for hybrid grid. Removed TCRIJ, + ! TCSCAL, TOTALC, TCWETL, SIG, SIGE, AREAW, AREAG, AREAH, + ! DXP, DYP, DXYP, DXYV, GRAV, LSRC1, LSRC2, LSRC3, LSRC4, + ! NSTRTC, LDIFF1, LDIFFM, KDIFFU, NINST, NINIT, ICASE, LTM + ! TLAT, TLNG -- these are now obsolete. + ! (dsa, bdf, bmy, 8/26/02) + ! (3 ) Moved AD and T to "dao_mod.f". The fact that these + ! were in "CMN" is historical baggage. (bmy, 9/18/02) + ! (4 ) Removed RH2, STH, RLAT, RLATV, TAUI, TAUE, JMONTH, + ! JMONTH0, XMID, YLMID, YEDGE, DXYP, TAU, TAU0, TOFDAY, + ! NTAU, IDAY, JDATE, JYEAR, JDAY, MONTH, IYEAR, I00, + ! J00, JMSIZE, NREAD, NWRITE, NDYN, NCONV, NDIAG, NCHEM, + ! NSRCE. Most of these are now superseded by either + ! "grid_mod.f" or "time_mod.f". (bmy, 3/11/03) + ! (5 ) Fix for LINUX - remove & in column 73 (bmy, 6/27/03) + ! (6 ) Remove obsolete variables and XTRA2 (bmy, 8/2/05) + !================================================================= + + !================================================================= + ! IEBD1, JEBD1, IEBD2, JEBD2 define the embedded chemistry region + !================================================================= + INTEGER :: IEBD1, IEBD2, JEBD1, JEBD2 + COMMON /EMBCHM/ IEBD1, IEBD2, JEBD1, JEBD2 + + !================================================================= + ! LPAUSE stores the annual mean tropopause (bmy, 12/6/99) + ! IFLX stores the flags for ND27 diagnostic (bmy, 12/6/99) + !================================================================= + INTEGER :: LPAUSE(IIPAR,JJPAR), IFLX(IIPAR,JJPAR) + COMMON /TROPTOP/ LPAUSE, IFLX + + diff --git a/code/CMN_DEP b/code/CMN_DEP new file mode 100644 index 0000000..2347024 --- /dev/null +++ b/code/CMN_DEP @@ -0,0 +1,30 @@ +! $Id: CMN_DEP,v 1.1 2009/06/09 21:51:52 daven Exp $ +! +!-----COMMON BLOCKS FOR DRYDEP +! +! NOTES: +! (1 ) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation. Changed continuation character from numbers +! to &. Changed comment character from C to !. Added & continuation +! characters in column 73 to allow header files to be included in +! F90 freeform files. (bmy, 6/25/02)* + + + ! IREG - Number of landtypes in grid square (I,J) + ! ILAND - Land type ID in grid square (I,J) for IREG landtypes + ! IUSE - Fraction ((per mil) of gridbox area occupied by + ! land type + INTEGER IREG,ILAND,IUSE + REAL*8 FRCLND + COMMON /DEPSV6/ IREG(IGLOB,JGLOB), & + & ILAND(IGLOB,JGLOB,NTYPE), & + & IUSE(IGLOB,JGLOB,NTYPE), & + & FRCLND(IIPAR,JJPAR) + + ! XLAI - Leaf Area Index of land type for current MONTH + REAL*8 XLAI + COMMON /DEPSV7/ XLAI(IGLOB,JGLOB,NTYPE) + + ! XLAI2 - Leaf Area Index of land type for following MONTH + REAL*8 XLAI2 + COMMON /DEPSV5/ XLAI2(IGLOB,JGLOB,NTYPE) diff --git a/code/CMN_DIAG b/code/CMN_DIAG new file mode 100644 index 0000000..37550d1 --- /dev/null +++ b/code/CMN_DIAG @@ -0,0 +1,206 @@ +! $Id: CMN_DIAG,v 1.3 2012/03/01 22:00:25 daven Exp $ +! +! NOTES: +! (1 ) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation. Also added & continuation characters in column 73 +! to allow header files to be included in F90 freeform files. +! Also converted PARAMETER statements to F90 syntax. (bmy, 6/25/02) +! (2 ) Add LD05 for sulfate prod/loss (rjp, bdf, bmy, 9/20/02) +! (3 ) Removed obsolete variables NTAU0, IDAY0, JDATE0, JYEAR0, KDACC, +! KDADYN, KDACONV, KDASRCE, KDACHEM, KDA3FLDS, KDA6FLDS, KDI6FLDS, +! KDKZZFLDS (bmy, 2/11/03) +! (4 ) Fix for LINUX - remove & from column 73 (bmy, 6/27/03) +! (5 ) Added LD03 for Kr85 Prod/loss diagnostic (bmy, 8/20/03) +! (6 ) Removed obsolete arrays (bmy, 1/21/05) +! (7 ) Rename MAXDIAG to MAX_DIAG and MAXTRACER to MAX_TRACER in order to +! avoid name conflicts with "gamap_mod.f" (bmy, 5/3/05) +! (8 ) Remove reference to TRCOFFSET (bmy, 5/16/06) +! (9 ) Added multi level LD54 to common CDIAG1 (phs, 9/22/06) +! (10) Added multi level LD10 to common CDIAG1. Set PD10 to 20. Set +! PD66 to 6. (phs, 9/18/07) +! (11) Added LD52 to common CDIAG1 (jaegle, 02/26/09) +! (12) Add GLYX, MGLY, SOAG, SOAM, and a few other tracers to AD17, AD18 +! for archiving rainout and washout fraction. (tmf, 1/7/09) +! (13) Add GLYX, MGLY J value archive. (tmf, 1/7/09) +! (14) Add GLYX, MGLY, SOAG, SOAM, and a few other tracers to AD37, AD38, AD39 +! for archiving rainout and washout flux. (tmf, 1/7/09) +! (15) Add GLYX, MGLY, GLYC, 6 PANs, SOAG, SOAM dry dep, +! PD44 = 41.(tmf, 1/7/09) +! (16) Add biogenic C2H4 emission, PD46 = 6. (tmf, 1/20/09) +! (17) Add support for ND19, ND58 and ND60 (kjw, dkh, 02/12/12, adj32_023) +!---------------------------------------------------------------------------- +! Parameters for the diagnostic arrays (for ease of use) +! + ! Changed PD66 to 6 (bmy, 9/8/00) + ! Changed PD21 to 10 (bmy, 9/30/00) + ! Changed PD67 to 18 (bmy, 10/11/00) + ! Changed PD46 to 4 (bmy, 1/2/01) + ! Changed PD29 to 5 (bmy, 1/2/01) + ! Changed PD11 to 7 (bmy, 9/4/01) + ! Changed PD32 to 0 (bmy, 2/14/02) + ! Changed PD21 to 20 (bmy, 2/27/02) + ! Changed PD43 to 4 (bmy, 3/4/02) + ! Changed PD05 to 10 (bmy, 10/18/02) + ! Changed PD44 to 30 (bmy, 11/19/02) + ! Changed PD43 to 5 + ! Changed PD67 to 22 (bmy, 6/23/03) + ! Changed PD66 to 5 (bmy, 6/23/03) + ! Changed PD03 to 5 (bmy, 8/20/03) + ! Changed PD37 to 10 (bmy, 1/21/04) + ! Changed PD06 to NDSTBIN (bmy, 4/5/04) + ! Changed PD07 to 7 (bmy, 4/5/04) + ! Changed PD08 to 2 (bmy, 4/20/04) + ! Changed PD07 to 12 (bmy, 7/15/04) + ! Changed PD21 to 26 (bmy, 1/5/05) + ! Removed PD03 -- now in "diag03_mod.f" (bmy, 1/21/05) + ! Removed PD41 -- now in "diag41_mod.f" (bmy, 1/21/05) + ! Now set PD09 to 6 (bmy, 6/27/05) + ! Removed PD04 -- now in "diag04_mod.f" (bmy, 7/26/05) + ! Now set PD30 to 1 (bmy, 8/18/05) + ! Now set PD46 to 6 (tmf, 1/20/09) + ! Now set PD10 to 20 (phs, 9/18/07) + ! Changed PD17 to 8 (tmf, 1/7/09) + ! Changed PD18 to 8 (tmf, 1/7/09) + ! Changed PD22 to 8 (tmf, 1/7/09) + ! Changed PD37 to 35 (tmf, 1/7/09) + ! Changed PD38 to 35 (tmf, 1/7/09) + ! Changed PD39 to 35 (tmf, 1/7/09) + ! Changed PD44 to 41 (tmf, 1/7/09) + ! Now set PD52 to 1 (jaegle 2/26/09) + ! Changed PD29 to 8 (zhe 11/28/10) + INTEGER, PARAMETER :: PD01=3 + INTEGER, PARAMETER :: PD02=3 + INTEGER, PARAMETER :: PD05=10 + INTEGER, PARAMETER :: PD06=NDSTBIN + INTEGER, PARAMETER :: PD07=12 + INTEGER, PARAMETER :: PD08=2 + INTEGER, PARAMETER :: PD09=6 + INTEGER, PARAMETER :: PD10=20 + INTEGER, PARAMETER :: PD11=7 + INTEGER, PARAMETER :: PD12=0 + INTEGER, PARAMETER :: PD13=1 + INTEGER, PARAMETER :: PD14=NNPAR + INTEGER, PARAMETER :: PD15=NNPAR + INTEGER, PARAMETER :: PD16=2 + INTEGER, PARAMETER :: PD17=8 + INTEGER, PARAMETER :: PD18=8 + INTEGER, PARAMETER :: PD19=1 + INTEGER, PARAMETER :: PD20=0 + INTEGER, PARAMETER :: PD21=27 + INTEGER, PARAMETER :: PD22=8 + INTEGER, PARAMETER :: PD23=0 + INTEGER, PARAMETER :: PD24=NNPAR + INTEGER, PARAMETER :: PD25=NNPAR + INTEGER, PARAMETER :: PD26=NNPAR + INTEGER, PARAMETER :: PD27=1 + INTEGER, PARAMETER :: PD28=0 + INTEGER, PARAMETER :: PD29=8 + INTEGER, PARAMETER :: PD30=1 + INTEGER, PARAMETER :: PD31=1 + INTEGER, PARAMETER :: PD32=1 + INTEGER, PARAMETER :: PD33=NNPAR + INTEGER, PARAMETER :: PD34=2 + INTEGER, PARAMETER :: PD35=NNPAR + INTEGER, PARAMETER :: PD36=NNPAR + INTEGER, PARAMETER :: PD37=35 + INTEGER, PARAMETER :: PD38=35 + INTEGER, PARAMETER :: PD39=35 + INTEGER, PARAMETER :: PD40=4 + INTEGER, PARAMETER :: PD43=5 + INTEGER, PARAMETER :: PD44=41 + INTEGER, PARAMETER :: PD45=NNPAR+1 + INTEGER, PARAMETER :: PD46=6 + INTEGER, PARAMETER :: PD47=NNPAR+1 + INTEGER, PARAMETER :: PD48=2 + INTEGER, PARAMETER :: PD49=0 + INTEGER, PARAMETER :: PD50=0 + INTEGER, PARAMETER :: PD51=0 + INTEGER, PARAMETER :: PD52=1 + INTEGER, PARAMETER :: PD53=0 + INTEGER, PARAMETER :: PD54=0 + INTEGER, PARAMETER :: PD55=3 + INTEGER, PARAMETER :: PD57=0 + INTEGER, PARAMETER :: PD58=12 + ! diag59 added, lz, 10/11/10, and delete ND59 at two places in this file + !INTEGER, PARAMETER :: PD59=0 + INTEGER, PARAMETER :: PD60=1 + INTEGER, PARAMETER :: PD61=0 + INTEGER, PARAMETER :: PD62=NNPAR + INTEGER, PARAMETER :: PD63=0 + INTEGER, PARAMETER :: PD64=0 + INTEGER, PARAMETER :: PD65=LLPAR*MAXFAM + INTEGER, PARAMETER :: PD66=6 + INTEGER, PARAMETER :: PD67=22 + INTEGER, PARAMETER :: PD68=4 + INTEGER, PARAMETER :: PD69=1 + INTEGER, PARAMETER :: PD70=0 + +!---------------------------------------------------------------------------- +! Diagnostic counters & time variables +! NJDAY is now 366 for leap years (bmy, 3/17/99) + INTEGER :: KDA48, NJDAY(366) + COMMON /CDIAG0/ KDA48, NJDAY +!---------------------------------------------------------------------------- +! Variables for the number of levels in multi-level diagnostics +! Removed LD03 -- this is now in diag03_mod.f (bmy, 1/21/05) +! Added LD09 (bmy, 6/27/05) +! Added LD54 (phs, 9/22/06) +! Added LD10 (phs, 9/18/07) +! Added LD31 (bmy, 5/8/07) +! Added LD52 (jaegle, 02/26/09) + INTEGER + & LD12, LD13, LD14, LD15, LD16, LD17, LD18, LD21, LD22, LD24, + & LD25, LD26, LD37, LD38, LD39, LD43, LD45, LD47, LD54, LD64, + & LD65, LD66, LD68, LD01, LD02, LD05, LD07, LD09, LD10, LD31, + & LD52, LD19, LD58, LD60 + + COMMON /CDIAG1/ + & LD12, LD13, LD14, LD15, LD16, LD17, LD18, LD21, LD22, LD24, + & LD25, LD26, LD37, LD38, LD39, LD43, LD45, LD47, LD54, LD64, + & LD65, LD66, LD68, LD01, LD02, LD05, LD07, LD09, LD10, LD31, + & LD52, LD19, LD58, LD60 +!---------------------------------------------------------------------------- +! NDxx diagnostic flags + INTEGER + & ND01, ND02, ND05, ND06, ND07, ND08, ND09, ND10, + & ND11, ND12, ND13, ND14, ND15, ND16, ND17, ND18, ND19, ND20, + & ND21, ND22, ND23, ND24, ND25, ND26, ND27, ND28, ND29, ND30, + & ND31, ND32, ND33, ND34, ND35, ND36, ND37, ND38, ND39, ND40, + & ND43, ND44, ND45, ND46, ND47, ND48, ND49, ND50, +! lz +! & ND51, ND52, ND53, ND54, ND55, ND57, ND58, ND59, ND60, + & ND51, ND52, ND53, ND54, ND55, ND57, ND58, ND60, + & ND61, ND62, ND63, ND64, ND65, ND66, ND67, ND68, ND69, ND70, + & ND71, ND72, ND73, ND74, ND75 + + COMMON /CDIAG2/ + & ND01, ND02, ND05, ND06, ND07, ND08, ND09, ND10, + & ND11, ND12, ND13, ND14, ND15, ND16, ND17, ND18, ND19, ND20, + & ND21, ND22, ND23, ND24, ND25, ND26, ND27, ND28, ND29, ND30, + & ND31, ND32, ND33, ND34, ND35, ND36, ND37, ND38, ND39, ND40, + & ND43, ND44, ND45, ND46, ND47, ND48, ND49, ND50, +! lz +! & ND51, ND52, ND53, ND54, ND55, ND57, ND58, ND59, ND60, + & ND51, ND52, ND53, ND54, ND55, ND57, ND58, ND60, + & ND61, ND62, ND63, ND64, ND65, ND66, ND67, ND68, ND69, ND70, + & ND71, ND72, ND73, ND74, ND75 +!---------------------------------------------------------------------------- +! Variables for printing out selected tracers in diagnostic output + INTEGER, PARAMETER :: MAX_DIAG = 70 + !INTEGER, PARAMETER :: MAX_TRACER = 120 + INTEGER, PARAMETER :: MAX_TRACER = 150 !(hml, 04/04/13) + INTEGER :: TINDEX, TCOUNT, TMAX + + COMMON /TR_INDEX/ TINDEX(MAX_DIAG,MAX_TRACER), + & TCOUNT(MAX_DIAG), + & TMAX(MAX_DIAG) + + !================================================================= + ! NO, J-Value, and 2-PM diagnostic arrays (bmy, 9/25/98) + ! Move this here for now (bmy, 7/20/04) + !================================================================= + REAL*8 HR1_NO, HR2_NO, HR1_JV, HR2_JV, + & HR1_OH, HR2_OH, HR1_OTH, HR2_OTH + + COMMON /JVNO2OH/ HR1_NO, HR2_NO, HR1_JV, HR2_JV, + & HR1_OH, HR2_OH, HR1_OTH, HR2_OTH diff --git a/code/CMN_GCTM b/code/CMN_GCTM new file mode 100644 index 0000000..67801d8 --- /dev/null +++ b/code/CMN_GCTM @@ -0,0 +1,39 @@ +! $Id: CMN_GCTM,v 1.1 2009/06/09 21:51:50 daven Exp $ + + !================================================================= + ! CMN_GCTM contains GEOS-CHEM specific PHYSICAL CONSTANTS + ! and DERIVED QUANTITIES (bmy, 6/25/02, 6/23/03) + ! + ! NOTES: + ! (1 ) Changed RCS ID tag comment character from "C" to "!$" to + ! allow freeform compilation. Also convert PARAMETERS to F90 + ! syntax. Updated comments, cosmetic changes. (bmy, 6/25/02) + ! (2 ) Added atmospheric scale height (7.6 km) (bmy, 6/23/03) + !================================================================= + + ! AIRMW : Molecular weight of air [28.97 g/mole] + REAL*8, PARAMETER :: AIRMW = 28.97d0 + + ! g0 : Gravity at Surface of Earth [9.8 m/s^2] + REAL*8, PARAMETER :: g0 = 9.8d0 + + ! PI : Double-Precision value of PI + REAL*8, PARAMETER :: PI = 3.14159265358979323d0 + + ! Re : Radius of Earth [m] + REAL*8, PARAMETER :: Re = 6.375d6 + + ! Rd : Gas Constant (R) in Dry Air [287 J/K/kg] + REAL*8, PARAMETER :: Rd = 287.0d0 + + ! g0_100 = 100.0 / g0 + REAL*8, PARAMETER :: g0_100 = 100d0 / g0 + + ! PI_180 = PI / 180.0 + REAL*8, PARAMETER :: PI_180 = PI / 180d0 + + ! Rdg0 = Rd / g0 + REAL*8, PARAMETER :: Rdg0 = Rd / g0 + + ! Scale height of atmosphere (7.6 km = 7600m) + REAL*8, PARAMETER :: SCALE_HEIGHT = 7600d0 diff --git a/code/CMN_ISOP b/code/CMN_ISOP new file mode 100644 index 0000000..a7c3596 --- /dev/null +++ b/code/CMN_ISOP @@ -0,0 +1,16 @@ +! $Id: CMN_ISOP,v 1.1 2009/06/09 21:51:53 daven Exp $ +! +!-----COMMON BLOCKS FOR ISOPRENE +! +! NOTES: +! (1 ) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation. Also added & continuation characters in column 73 +! to allow header files to be included in F90 freeform files. +! (bmy, 6/25/02) +! + REAL*8 SOPCOEFF,BASEISOP,BASEGRASS,BASEMB + COMMON /DEPSV9/ & + ! polynomial fitting's coeffcients + & SOPCOEFF(NPOLY),BASEISOP(MAXIJ,NTYPE), & + ! Added for EMISOP_GRASS and EMISOP_MB (bdf, bmy, 8/1/01) + & BASEGRASS(MAXIJ),BASEMB(MAXIJ) diff --git a/code/CMN_MONOT b/code/CMN_MONOT new file mode 100644 index 0000000..fa9b294 --- /dev/null +++ b/code/CMN_MONOT @@ -0,0 +1,10 @@ +! $Id: CMN_MONOT,v 1.1 2009/06/09 21:51:50 daven Exp $ +! +!-----COMMON BLOCKS FOR MONOTERPENE +! +! (1 ) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation. Updated comments, cosmetic changes. (bmy, 6/25/02) + + ! Baseline emission + REAL*8 BASEMONOT + COMMON /BDFMONOT/ BASEMONOT(MAXIJ,NTYPE) diff --git a/code/CMN_NOX b/code/CMN_NOX new file mode 100644 index 0000000..1eed38b --- /dev/null +++ b/code/CMN_NOX @@ -0,0 +1,20 @@ +! $Id: CMN_NOX,v 1.1 2009/06/09 21:51:53 daven Exp $ + !================================================================= + ! CMN_NOX is the header file for containing NOx from aircraft, + ! lightning, and soils. CMN_NOX also contains variables for the + ! lightning subroutines. (mgs, bey, bdf, bmy, 3/5/98, 10/2/07) + ! + ! NOTES: + ! (1 ) Changed RCS ID tags from "C" to "!" to allow + ! freeform compilation. (bmy, 6/25/02) + ! (2 ) Moved BXHEIGHT to "dao_mod.f". The fact that BXHEIGHT + ! was in "CMN_NOX" is historical baggage. (bmy, 9/18/02) + ! (3 ) Now everything except GEMISNOX, GEMISNOX2 is in + ! "lightning_mod.f" (bmy, 4/14/04) + ! (4 ) Remove GEMISNOX from common block (ltm, bmy, 10/2/07) + !================================================================= + + ! NOTE: Keep this for backwards compatibility for now (bmy, 10/2/07) + ! GEMISNOX2 = Soil Nox [molec NOx/cm3/s] + REAL*8 :: GEMISNOX2(IIPAR,JJPAR) + COMMON /BOXH/ GEMISNOX2 diff --git a/code/CMN_O3 b/code/CMN_O3 new file mode 100644 index 0000000..9c1e31e --- /dev/null +++ b/code/CMN_O3 @@ -0,0 +1,81 @@ +! $Id: CMN_O3,v 1.1 2009/06/09 21:51:51 daven Exp $ + +!-----COMMON BLOCKS FOR ANTHRO EMISSIONS (via SMVGEAR!)----- +! +! NOTES: +! (1 ) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation. Also added & continuation characters in column 73 +! to allow header files to be included in F90 freeform files. +! (bmy, 6/25/02) +! (2 ) Removed obsolete variables (bmy, 10/25/05) +! (3 ) Add anthropgenic emission species: BENZ, TOLU, XYLE, C2H2, C2H4. +! (tmf, 1/7/09) +! +! +! NOTE: Now NEMPARA = max no. of anthropogenic emissions +! NEMPARB = max no. of biogenic emissions +! +! Rural Emissions: EMISRN = NOx (1:NOXLEVELS), EMISR = all other tracers +! Total Emissions: EMISTN = NOx (1:NOXLEVELS), EMIST = all other tracers + REAL*8 EMISR, EMISRN, EMIST, EMISTN + COMMON /EMIS/ + & EMISR(IGLOB,JGLOB,NEMPARA), EMISRN(IGLOB,JGLOB,NOXLEVELS), + & EMIST(IIPAR,JJPAR,NEMPARA), EMISTN(IIPAR,JJPAR,NOXLEVELS) + +! Rural Emissions: +! EMISRRN = NOx emissions into sigma levels L=1,NOXEXTENT +! EMISRR = All other tracer emissions into sigma level L=1 + REAL*8 EMISRR, EMISRRN + COMMON /EMIS2/ + & EMISRR (IIPAR,JJPAR,NEMPARA+NEMPARB), + & EMISRRN(IIPAR,JJPAR,NOXEXTENT ) + +! Arrays to read emissions from updated merge file : +! NOx, CO, PRPE, C3H8, ALK4, C2H6, ACET, MEK +! NOTE: ALD2 is not emitted in GEIA so we don't need an array for +! it below...but it is emitted in EMEP. It will be saved +! into the EMISRR array for SMVGEAR. (bdf, bmy, 11/1/05) + REAL*4 EMISTNOX,EMISTCO,EMISTETHE,EMISTPRPE,EMISTC2H6, & + & EMISTC3H8,EMISTALK4,EMISTACET,EMISTMEK,EMISTSOX, & + & EMISTBENZ,EMISTTOLU,EMISTXYLE,EMISTC2H4,EMISTC2H2 + COMMON/EMIS4/ & + & EMISTNOX (IGLOB,JGLOB,4,2), EMISTETHE(IGLOB,JGLOB ), & + & EMISTCO (IGLOB,JGLOB ), EMISTPRPE(IGLOB,JGLOB ), & + & EMISTC3H8(IGLOB,JGLOB ), EMISTALK4(IGLOB,JGLOB ), & + & EMISTC2H6(IGLOB,JGLOB ), EMISTSOX (IGLOB,JGLOB,4,2), & + & EMISTACET(IGLOB,JGLOB ), EMISTMEK (IGLOB,JGLOB ), & + & EMISTBENZ(IGLOB,JGLOB ), EMISTTOLU(IGLOB,JGLOB ), & + & EMISTXYLE(IGLOB,JGLOB ), EMISTC2H4(IGLOB,JGLOB ), & + & EMISTC2H2(IGLOB,JGLOB ) +! Time of day and weekday/weekend scale factors +! NOTE: Now SCNR89 is (3,3) because of the weekday scale factor!!! + REAL*8 TODH, TODN, TODB, SCNR89 + COMMON /PLUAD/ TODH(6), TODN(6), TODB(6), SCNR89(3,3) + +! IFSCLYR = Year to use for scaling fossil fuel emissions (1985 = no scaling!) + INTEGER FSCALYR + COMMON /FSCAL1/ FSCALYR + +! FTOTCO2 = yearly scale factors based on Total Fuel CO2 emissions +! FLIQCO2 = yearly scale factors based on Liquid Fuel CO2 emissions + REAL*4 FTOTCO2, FLIQCO2 + COMMON /FSCAL2/ FTOTCO2(IGLOB,JGLOB), FLIQCO2(IGLOB,JGLOB) + +! FRACO3, FRACNO = fractions of O3, NO +! SAVEOH, SAVENO, SAVENO3 = array to save OH, NO, & NO3 fields +! SAVENO2 = array to save NO2 fields (rvm, 5/9/00) +! FRACNO2 = fraction of NO2 (rvm, bmy, 2/27/02) +! SAVEHO2 = array to save HO2 fields (rvm, bmy, 2/27/02) + REAL*8 FRACO3, SAVEOH, FRACNO, SAVENO, SAVENO2, SAVENO3 + REAL*8 FRACNO2, SAVEHO2 + COMMON /FRO3/ + & FRACO3(IIPAR,JJPAR,LLPAR), + & SAVEOH(IIPAR,JJPAR,LLPAR), + & FRACNO(IIPAR,JJPAR,LLPAR), + & SAVENO(IIPAR,JJPAR,LLPAR), + & SAVENO2(IIPAR,JJPAR,LLPAR), + & SAVENO3(IIPAR,JJPAR,LLPAR), + & FRACNO2(IIPAR,JJPAR,LLPAR), + & SAVEHO2(IIPAR,JJPAR,LLPAR) + + diff --git a/code/CMN_SIZE b/code/CMN_SIZE new file mode 100644 index 0000000..1596854 --- /dev/null +++ b/code/CMN_SIZE @@ -0,0 +1,687 @@ +! $Id: CMN_SIZE,v 1.2 2012/03/01 22:00:25 daven Exp $ + !======================================================================= + ! CMN_SIZE: size parameters for GEOS-CHEM arrays (bmy, 3/16/01, 4/3/07) + ! + ! NOTES: + ! (1 ) Now set LLTROP = 20 for GEOS-3 (bmy, 4/12/01) + ! (2 ) Eliminated obsolete commented-out code (bmy, 4/20/01) + ! (3 ) Now set MAXFAM = 12 for more P-L families (bmy, 6/28/01) + ! (4 ) Comment out {IJL}GCMPAR -- these are obosolete (bmy, 9/24/01) + ! (5 ) Also set LLPAR = 30 for GEOS-3, will regrid online (bmy, 9/24/01) + ! (6 ) Removed obsolete code from 9/01 (bmy, 10/23/01) + ! (7 ) Removed NAIR, LAIREMS, these are now defined + ! in "aircraft_nox_mod.f" (bmy, 2/14/02) + ! (8 ) Eliminated commented-out code from 2/14/02. Also added NAER + ! and NRH parameters for aerosols. (rvm, bmy, 2/27/02) + ! (9 ) Removed IM, JM, IMX, JMX to avoid namespace pollution. This + ! is needed to get the new TPCORE to work. Also changed RCS + ! ID tag comment character from "C" to "!" to allow freeform + ! compilation. (bmy, 6/25/02) + ! (10) Removed obsolete code from 6/02 (bmy, 8/26/02) + ! (11) Added NUMDEP_SULF in a common block for sulfate dry deposition. + ! Also set MAXDEP=31 and NNPAR=31 for coupled fullchem/sulfate + ! simulations. (rjp, bdf, bmy, 11/15/02) + ! (12) Removed I0, J0; these are now superseded by "grid_mod.f" + ! (bmy, 2/11/03) + ! (13) Added parameters for GEOS-4 (bmy, 6/18/03) + ! (14) Now defines both 55 level and 30 level GEOS-4 grids. Also + ! define LLTROP=19 for GEOS-4 grids. Also remove obsolete + ! GEOS-2 grid declarations. (bmy, 10/31/03) + ! (15) LLTROP should be 17 for GEOS-4...based on the ND55 diagnostic + ! when computed for 2003 met fields (bmy, 2/18/04) + ! (16) Increase NNPAR from 31 to 39 for carbon & dust tracers. Also + ! declare NDSTBIN as # of dust bins. (rvm, tdf, bmy, 4/1/04) + ! (17) Increase NNPAR to 41 for seasalt tracers (rjp, bec, bmy, 4/20/04) + ! (18) Increase NNPAR to 50 for SOA tracers (rjp, bmy, 7/15/04) + ! (19) Now use NESTED_CH and NESTED_NA cpp switches to define + ! parameters for 1x1 nested grids. Also add parameters for + ! the 1 x 1.25 global grid. (bmy, 12/1/04) + ! (20) Now add parameters for GCAP and GEOS-5 grids. Remove references + ! to obsolete LGEOSCO and FULLCHEM Cpp switches (bmy, 6/24/05) + ! (21) Now add I1x1 and J1x1 parameters for data on the 1x1 GEOS + ! grid. (bmy, 10/24/05) + ! (22) Increase NNPAR to 52 (bmy, 12/6/05) + ! (23) Increase NNPAR to 54 (dkh, bmy, 5/22/06) + ! (24) Remove support for GEOS-1 and GEOS-STRAT met fields (bmy, 8/4/06) + ! (25) Added variable tropopause case (bmy, phs, bdf, 8/21/06) + ! (26) Set LLTROP to level of first box entirely above 20km for GEOS-3 + ! and GEOS-4 (phS, 9/14/06) + ! (27) Bug fix: set LLTROP_FIX = LLPAR for GCAP (bmy, 11/29/06) + ! (28) Reset vertical coordinates for GEOS-5. Also renamed GRID30LEV + ! to GRIDREDUCED (bmy, 4/3/07) + ! (29) New parameters for GEOS-5 nested grid (yxw, dan, bmy, 11/6/08) + ! (30) NEMPARA set to 12 to emit O3 and HNO3 (phs, 4/3/08) + ! (31) Add tracers to NNPAR = 73. (tmf, 1/7/09) + ! (32) NEMPARA set to 21 to emit new tracers for GLYX chemistry + ! (tmf, ccc, 3/2/09) + ! (33) NEMPARB set to 3 to emit MBO, MONX (tmf, ccc, 3/2/09) + !======================================================================= + + ! C Preprocessor #define statements for conditional compilation +# include "define.h" + + !================================================================= + ! DISIZE = size (in degrees) of a longitude grid box + ! DJSIZE = size (in degrees) of a latitude grid box + !================================================================= +#if defined( GRID4x5 ) + REAL*8, PARAMETER :: DISIZE = 5.0d0 + REAL*8, PARAMETER :: DJSIZE = 4.0d0 + +#elif defined( GRID2x25 ) + REAL*8, PARAMETER :: DISIZE = 2.5d0 + REAL*8, PARAMETER :: DJSIZE = 2.0d0 + +#elif defined( GRID1x125 ) + REAL*8, PARAMETER :: DISIZE = 1.25d0 + REAL*8, PARAMETER :: DJSIZE = 1.0d0 + +#elif defined( GRID1x1 ) + REAL*8, PARAMETER :: DISIZE = 1.0d0 + REAL*8, PARAMETER :: DJSIZE = 1.0d0 + +#elif defined( GRID05x0666 ) + REAL*8, PARAMETER :: DISIZE = 2d0/3d0 + REAL*8, PARAMETER :: DJSIZE = 0.5d0 + +#elif defined( GRID025x03125 ) + ! (lzh,02/01/2015) add 0.25 nested + REAL*8, PARAMETER :: DISIZE = 0.3125d0 + REAL*8, PARAMETER :: DJSIZE = 0.25d0 + +#endif + + !================================================================= + ! GRID PARAMETERS + ! + ! IGLOB = global longitude dimension + ! JGLOB = global latitude dimension + ! LGLOB = max number of sigma levels + ! IIPAR = window longitude dimension + ! JJPAR = window latitude dimension + ! LLPAR = window vertical dimension + ! LLTROP = maximum number of tropospheric levels for variable + ! tropopause + ! LLTROP_FIX = number of tropospheric levels for offline simulations + ! PTOP = model top pressure (mb) + ! + ! Most of the time, GEOS-CHEM is used for global simulations. + ! In this case, then IIPAR=IGLOB, JJPAR=JGLOB, LLPAR=LGLOB. + ! + ! For nested grids, then IIPAR= LPAUSE(I,J) ). + ! + ! Compute the net CO from the P(CO) and L(CO) rates that are + ! stored in the COPROD and COLOSS arrays. + ! + ! Unit conversion to/from [kg/box] and [molec/cm3] is required. + ! The conversion factor is STTTOGCO, which is given below. + ! + ! kg CO box | mole CO | 6.022e23 molec CO + ! ------- * -----------+-------------+------------------- + ! box BOXVL cm3 | 28e-3 kg CO | mole CO + ! + ! = molec CO + ! -------- + ! cm3 + !================================================================= + + ! Get the minimum extent of the tropopause + LMIN = GET_MIN_TPAUSE_LEVEL() + + DO L = LMIN, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Skip tropospheric grid boxes + IF ( ITS_IN_THE_TROP(I,J,L) ) CYCLE + + ! conversion factor from [kg/box] to [molec/cm3] + STTTOGCO = 6.022d23 / ( 28d-3 * BOXVL(I,J,L) ) + + ! Convert STT from [kg/box] to [molec/cm3] + GCO = STT(I,J,L,IDTCO) * STTTOGCO + + ! Air density in molec/cm3 + BAIRDENS = AD(I,J,L) * XNUMOLAIR / BOXVL(I,J,L) + + ! Apply P(CO) and L(CO) rates to GCO + GCO = GCO * ( 1d0 - COLOSS(J,L) * DT ) + + & ( COPROD(J,L) * DT * BAIRDENS ) + + ! Compute production of CH2O (qli, 12/9/99) + STT(I,J,L,IDTCH2O) = STT(I,J,L,IDTCH2O) + + & XNUMOL(IDTCO) / XNUMOL(IDTCH2O) * + & COPROD(J,L) * BAIRDENS / + & STTTOGCO + + ! Convert STT from [molec/cm3] to [kg/box] + STT(I,J,L,IDTCO) = GCO / STTTOGCO + ENDDO + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE CO_STRAT_PL diff --git a/code/Dependencies.mk b/code/Dependencies.mk new file mode 100644 index 0000000..a876c43 --- /dev/null +++ b/code/Dependencies.mk @@ -0,0 +1,508 @@ +#============================================================================== +# Dependencies Listing +#============================================================================== +BLKSLV.o : BLKSLV.f jv_mie.h +CLDSRF.o : CLDSRF.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +CO_strat_pl.o : CO_strat_pl.f CMN_SIZE define.h +critical_load_mod.o : critical_load_mod.f CMN_SIZE +EFOLD.o : EFOLD.f +FLINT.o : FLINT.f +GAUSSP.o : GAUSSP.f +GEN.o : GEN.f jv_mie.h +fjx_acet_mod.o : fjx_acet_mod.f cmn_fj.h jv_cmn.h +JRATET.o : JRATET.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +JVALUE.o : JVALUE.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +Kr85_mod.o : Kr85_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h define.h +LEGND0.o : LEGND0.f +MATIN4.o : MATIN4.f +MIESCT.o : MIESCT.f jv_mie.h +NOABS.o : NOABS.f +OPMIE.o : OPMIE.f cmn_fj.h CMN_SIZE define.h jv_cmn.h jv_mie.h +RD_TJPL.o : RD_TJPL.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +RnPbBe_mod.o : RnPbBe_mod.f CMN_DEP CMN_DIAG CMN_SIZE define.h define.h +SPHERE.o : SPHERE.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +XSEC1D.o : XSEC1D.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +XSECO2.o : XSECO2.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +XSECO3.o : XSECO3.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +aerosol_mod.o : aerosol_mod.f CMN_DIAG CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h comode.h jv_cmn.h +aircraft_nox_mod.o : aircraft_nox_mod.f CMN CMN_DIAG CMN_SIZE define.h +airmas.o : airmas.f +anthroems.o : anthroems.f CMN_O3 CMN_SIZE define.h comode.h +arctas_ship_emiss_mod.o : arctas_ship_emiss_mod.f CMN_SIZE define.h +arsl1k.o : arsl1k.f +backsub.o : backsub.f CMN_SIZE define.h comode.h +benchmark_mod.o : benchmark_mod.f CMN_SIZE define.h +biofit.o : biofit.f CMN_DEP CMN_SIZE define.h +biofuel_mod.o : biofuel_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h +biomass_mod.o : biomass_mod.f CMN_DIAG CMN_SIZE define.h +boxvl.o : boxvl.f +bravo_mod.o : bravo_mod.f CMN_O3 CMN_SIZE define.h +c2h6_mod.o : c2h6_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h +cac_anthro_mod.o : cac_anthro_mod.f CMN_O3 CMN_SIZE define.h +ch3i_mod.o : ch3i_mod.f CMN_DEP CMN_DIAG CMN_SIZE define.h comode.h +charpak_mod.o : charpak_mod.f +cleanup.o : cleanup.f +comode_mod.o : comode_mod.f CMN_SIZE define.h comode.h +decomp.o : decomp.f CMN_SIZE define.h comode.h +diag03_mod.o : diag03_mod.f CMN_DIAG CMN_SIZE define.h +diag04_mod.o : diag04_mod.f CMN_DIAG CMN_SIZE define.h +diag1.o : diag1.f CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h +diag3.o : diag3.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h comode.h +diag41_mod.o : diag41_mod.f CMN_DIAG CMN_SIZE define.h +diag42_mod.o : diag42_mod.f CMN_DIAG CMN_SIZE define.h +diag48_mod.o : diag48_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag49_mod.o : diag49_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag50_mod.o : diag50_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag51_mod.o : diag51_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag56_mod.o : diag56_mod.f CMN_DIAG CMN_SIZE define.h +diag59_mod.o : diag59_mod.f CMN_DIAG CMN_SIZE define.h +diag_2pm.o : diag_2pm.f CMN_DIAG CMN_SIZE define.h +diag_mod.o : diag_mod.f +diag_oh_mod.o : diag_oh_mod.f CMN_SIZE define.h comode.h +diag_pl_mod.o : diag_pl_mod.f CMN_DIAG CMN_SIZE define.h comode.h +diagoh.o : diagoh.f CMN_DIAG CMN_O3 CMN_SIZE define.h +directory_mod.o : directory_mod.f +drydep_mod.o : drydep_mod.f CMN_DEP CMN_DIAG CMN_GCTM CMN_SIZE define.h CMN_VEL commsoil.h comode.h +dust_dead_mod.o : dust_dead_mod.f CMN_GCTM CMN_SIZE define.h +edgar_mod.o : edgar_mod.f CMN_SIZE define.h +emep_mod.o : emep_mod.f CMN_O3 CMN_SIZE define.h +nei2005_anthro_mod.o : nei2005_anthro_mod.f CMN_O3 CMN_SIZE define.h +nei2008_anthro_mod.o : nei2008_anthro_mod.F90 CMN_O3 CMN_SIZE define.h +htap_mod.o : htap_mod.f90 CMN_O3 CMN_SIZE define.h +emf_scale.o : emf_scale.f CMN_O3 CMN_SIZE define.h comode.h +emfossil.o : emfossil.f CMN_DIAG CMN_O3 CMN_SIZE define.h comode.h rcp_mod.o +emisop.o : emisop.f CMN_ISOP CMN_SIZE define.h CMN_VEL +emisop_grass.o : emisop_grass.f CMN_ISOP CMN_SIZE define.h CMN_VEL +emisop_mb.o : emisop_mb.f CMN_ISOP CMN_SIZE define.h CMN_VEL +emissdr.o : emissdr.f CMN CMN_DIAG CMN_MONOT CMN_NOX CMN_O3 CMN_SIZE define.h comode.h +emissions_mod.o : emissions_mod.f CMN_O3 CMN_SIZE define.h rcp_mod.o +emmonot.o : emmonot.f CMN_MONOT CMN_SIZE define.h CMN_VEL +epa_nei_mod.o : epa_nei_mod.f CMN_O3 CMN_SIZE define.h +error_mod.o : error_mod.f define.h +fast_j.o : fast_j.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +fertadd.o : fertadd.f CMN_SIZE define.h commsoil.h +file_mod.o : file_mod.f define.h +findmon.o : findmon.f +fjfunc.o : fjfunc.f cmn_fj.h CMN_SIZE define.h +future_emissions_mod.o : future_emissions_mod.f CMN_SIZE define.h +fvdas_convect_mod.o : fvdas_convect_mod.f CMN_DIAG CMN_SIZE define.h +fcro2ho2.o : fcro2ho2.f +fyrno3.o : fyrno3.f +fyhoro.o : fyhoro.f +gc_biomass_mod.o : gc_biomass_mod.f CMN_SIZE define.h +gcap_convect_mod.o : gcap_convect_mod.f CMN_DIAG CMN_SIZE define.h +gcap_read_mod.o : gcap_read_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +geia_mod.o : geia_mod.f CMN_SIZE define.h +get_global_ch4.o : get_global_ch4.f +getifsun.o : getifsun.f CMN_SIZE define.h comode.h +gfed2_biomass_mod.o : gfed2_biomass_mod.f CMN_SIZE define.h +gfed3_biomass_mod.o : gfed3_biomass_mod.f CMN_SIZE define.h +global_hno3_mod.o : global_hno3_mod.f CMN_SIZE define.h +global_no3_mod.o : global_no3_mod.f CMN_SIZE define.h +global_nox_mod.o : global_nox_mod.f CMN_SIZE define.h +global_o1d_mod.o : global_o1d_mod.f CMN_SIZE define.h +global_o3_mod.o : global_o3_mod.f CMN_SIZE define.h +h2_hd_mod.o : h2_hd_mod.f CMN_DEP CMN_DIAG CMN_O3 CMN_SIZE define.h +hcn_ch3cn_mod.o : hcn_ch3cn_mod.f CMN_DEP CMN_DIAG CMN_SIZE define.h +icoads_ship_mod.o : icoads_ship_mod.f CMN_O3 CMN_SIZE define.h +ifort_errmsg.o : ifort_errmsg.f +initialize.o : initialize.f CMN_DIAG CMN_SIZE define.h +inphot.o : inphot.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +rd_aod.o : rd_aod.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +isoropiaII_adj_mod.o : isoropiaII_adj_mod.f new/isrpia_adj.inc + $(F90) -c -r8 new/isoropiaII_adj_mod.f +isoropiaIIcode_adj.o : isoropiaIIcode_adj.f new/isrpia_adj.inc + $(F90) -c -r8 new/isoropiaIIcode_adj.f +adBuffer.o : adBuffer.c + $(CC) -c new/adBuffer.c +adStack.o : adStack.c + $(CC) -c new/adStack.c +inquire_Mod.o : inquireMod.F90 +jsparse.o : jsparse.f CMN_SIZE define.h comode.h +jv_index.o : jv_index.f cmn_fj.h CMN_SIZE define.h comode.h +ksparse.o : ksparse.f CMN_SIZE define.h comode.h +lai_mod.o : lai_mod.f CMN_SIZE define.h +logical_mod.o : logical_mod.f +lump.o : lump.f CMN_SIZE define.h comode.h +main.o : main.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +mercury_mod.o : mercury_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +mmran_16.o : mmran_16.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +ndxx_setup.o : ndxx_setup.f CMN_DIAG CMN_SIZE define.h +ocean_mercury_mod.o : ocean_mercury_mod.f CMN_DEP CMN_SIZE define.h +ohsave.o : ohsave.f CMN_SIZE define.h comode.h +optdepth_mod.o : optdepth_mod.f CMN_DIAG CMN_SIZE define.h +pderiv.o : pderiv.f CMN_SIZE define.h comode.h +pjc_pfix_mod.o : pjc_pfix_mod.f CMN CMN_GCTM CMN_SIZE define.h +planeflight_mod.o : planeflight_mod.f CMN_DIAG CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h comode.h jv_cmn.h +precipfrac.o : precipfrac.f CMN_SIZE define.h +pulsing.o : pulsing.f CMN_SIZE define.h commsoil.h +rcp_mod.o : rcp_mod.f diag_mod.o aircraft_nox_mod.o dao_mod.o +rd_js.o : rd_js.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +rd_prof.o : rd_prof.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +rdisopt.o : rdisopt.f CMN_SIZE define.h +rdlai.o : rdlai.f CMN_DEP CMN_SIZE define.h CMN_VEL +rdland.o : rdland.f CMN_DEP CMN_SIZE define.h CMN_VEL +rdlight.o : rdlight.f CMN_ISOP CMN_SIZE define.h +rdmonot.o : rdmonot.f CMN_SIZE define.h +rdsoil.o : rdsoil.f CMN_SIZE define.h commsoil.h +readchem.o : readchem.f CMN_SIZE define.h comode.h +reader.o : reader.f CMN_GCTM CMN_SIZE define.h comode.h +readlai.o : readlai.f CMN_DEP CMN_SIZE define.h CMN_VEL +regrid_1x1_mod.o : regrid_1x1_mod.f CMN_GCTM CMN_SIZE define.h +retro_mod.o : retro_mod.f CMN CMN_SIZE CMN_O3 +regrid_a2a_mod.o : regrid_a2a_mod.F90 CMN_GCTM CMN_SIZE +ruralbox.o : ruralbox.f CMN_SIZE define.h comode.h +scale_anthro_mod.o : scale_anthro_mod.f CMN_SIZE define.h +schem.o : schem.f CMN_SIZE define.h +seasalt_mod.o : seasalt_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +set_aer.o : set_aer.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +setbase.o : setbase.f CMN CMN_ISOP CMN_MONOT CMN_SIZE define.h CMN_VEL +setemdep.o : setemdep.f CMN_SIZE define.h comode.h +setmodel.o : setmodel.f CMN_SIZE define.h comode.h +sfcwindsqr.o : sfcwindsqr.f CMN_SIZE define.h +smvgear.o : smvgear.f CMN_SIZE define.h comode.h +soilbase.o : soilbase.f CMN_SIZE define.h commsoil.h +soilcrf.o : soilcrf.f CMN_DEP CMN_SIZE define.h commsoil.h +soiltemp.o : soiltemp.f CMN_SIZE define.h commsoil.h +soiltype.o : soiltype.f CMN_SIZE define.h commsoil.h +streets_anthro_mod.o : streets_anthro_mod.f CMN_O3 CMN_SIZE define.h +subfun.o : subfun.f CMN_SIZE define.h comode.h +sunparam.o : sunparam.f +tcorr.o : tcorr.f +toms_mod.o : toms_mod.f CMN_SIZE define.h +tpcore_bc_mod.o : tpcore_bc_mod.f CMN CMN_SIZE define.h +tpcore_fvdas_mod.o : tpcore_fvdas_mod.f90 CMN_GCTM + $(F90) -c -r8 $*.f90 +tpcore_mod.o : tpcore_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define.h + $(F90) -c -r8 $*.f +tpcore_window_mod.o : tpcore_window_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define.h + $(F90) -c -r8 $*.f +tracerid_mod.o : tracerid_mod.f CMN_SIZE define.h comode.h +transfer_mod.o : transfer_mod.f CMN_SIZE define.h +tropopause.o : tropopause.f CMN CMN_DIAG CMN_SIZE define.h +tropopause_mod.o : tropopause_mod.f CMN CMN_SIZE define.h comode.h +unix_cmds_mod.o : unix_cmds_mod.f +update.o : update.f CMN_SIZE define.h comode.h +uvalbedo_mod.o : uvalbedo_mod.f CMN_SIZE define.h +vistas_anthro_mod.o : vistas_anthro_mod.f CMN_O3 CMN_SIZE define.h +xltmmp.o : xltmmp.f CMN_SIZE define.h +xtra_read_mod.o : xtra_read_mod.f CMN_DIAG CMN_SIZE define.h + +#------------------------------------------------------------------------------ +# MODIFIED FOR ORGANIZED DIRECTORY STRUCTURE +#------------------------------------------------------------------------------ + +#======================== +# ADJOINT DIRECTORY FILES +#======================== + +adj_arrays_mod.o : adj_arrays_mod.f define_adj.h define.h CMN_SIZE comode.h gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/adj_arrays_mod.f +calcrate_adj.o : calcrate_adj.f CMN CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/calcrate_adj.f +carbon_adj_mod.o : carbon_adj_mod.f CMN CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/carbon_adj_mod.f +checkpoint_mod.o : checkpoint_mod.f define.h + $(F90) -c -r8 adjoint/checkpoint_mod.f +checkpt_mod.o : checkpt_mod.f CMN_SIZE comode.h CMN_VEL define.h CMN_DEP + $(F90) -c -r8 adjoint/checkpt_mod.f +chemdr_adj.o : chemdr_adj.f CMN CMN_DEP CMN_DIAG CMN_NOX CMN_O3 CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/chemdr_adj.f +chemistry_adj_mod.o : chemistry_adj_mod.f gckpp_adj_Global.f90 gckpp_adj_Rates.f90 gckpp_adj_Integrator.f90 CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/chemistry_adj_mod.f +cleanup_adj.o : cleanup_adj.f + $(F90) -c -r8 adjoint/cleanup_adj.f +co2_adj_mod.o : co2_adj_mod.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/co2_adj_mod.f +CO_strat_pl_adj.o : CO_strat_pl_adj.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/CO_strat_pl_adj.f +convection_adj_mod.o : convection_adj_mod.f CMN_DIAG CMN_SIZE define.h define.h + $(F90) -c -r8 adjoint/convection_adj_mod.f +directory_adj_mod.o : directory_adj_mod.f + $(F90) -c -r8 adjoint/directory_adj_mod.f +dust_adj_mod.o : dust_adj_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define_adj.h + $(F90) -c -r8 adjoint/dust_adj_mod.f +emissions_adj_mod.o : emissions_adj_mod.f CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 adjoint/emissions_adj_mod.f +fvdas_convect_adj_mod.o : fvdas_convect_adj_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 adjoint/fvdas_convect_adj_mod.f +gc_type_mod.o : gc_type_mod.F CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/gc_type_mod.F +global_ch4_adj_mod.o : global_ch4_adj_mod.f CMN CMN_GCTM CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 $< +geos_chem_adj_mod.o : geos_chem_adj_mod.f CMN_O3 CMN_GCTM CMN_DIAG CMN_SIZE define.h comode.h define_adj.h + $(F90) -c -r8 adjoint/geos_chem_adj_mod.f +covariance_mod.o : covariance_mod.f CMN_SIZE CMN_DIAG CMN_GCTM define_adj.h + $(F90) -c -r8 adjoint/covariance_mod.f +input_adj_mod.o : input_adj_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h define_adj.h gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/input_adj_mod.f +inv_hessian_mod.o : inv_hessian_mod.f CMN_SIZE define_adj.h + $(F90) -c -r8 adjoint/inv_hessian_mod.f +inv_hessian_lbfgs_mod.o : inv_hessian_lbfgs_mod.f CMN_SIZE define_adj.h + $(F90) $(LAPACK_BLAS_FFLAGS) -c -r8 adjoint/inv_hessian_lbfgs_mod.f +inverse_driver.o : inverse_driver.f define_adj.h + $(F90) -c -r8 adjoint/inverse_driver.f +inverse_mod.o : inverse_mod.f define_adj.h define.h + $(F90) -c -r8 adjoint/inverse_mod.f +linoz_adj_mod.o : linoz_adj_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h linoz.com + $(F90) -c -r8 adjoint/linoz_adj_mod.f +logical_adj_mod.o : logical_adj_mod.f + $(F90) -c -r8 adjoint/logical_adj_mod.f +lump_adj.o : lump_adj.f CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/lump_adj.f +gckpp_adj_Precision.o : gckpp_adj_Precision.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Precision.f90 +gckpp_adj_Parameters.o : gckpp_adj_Parameters.f90 gckpp_adj_Precision.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Parameters.f90 +gckpp_adj_Global.o : gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Global.f90 +gckpp_adj_LinearAlgebra.o : gckpp_adj_LinearAlgebra.f90 gckpp_adj_Parameters.f90 gckpp_adj_JacobianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_LinearAlgebra.f90 +gckpp_adj_Monitor.o : gckpp_adj_Monitor.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Monitor.f90 +gckpp_adj_Initialize.o : gckpp_adj_Initialize.f90 gckpp_adj_Parameters.f90 gckpp_adj_Global.f90 gckpp_adj_Util.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Initialize.f90 +gckpp_adj_JacobianSP.o : gckpp_adj_JacobianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_JacobianSP.f90 +gckpp_adj_Function.o : gckpp_adj_Function.f90 gckpp_adj_Parameters.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Function.f90 +gckpp_adj_Jacobian.o : gckpp_adj_Jacobian.f90 gckpp_adj_Parameters.f90 gckpp_adj_JacobianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Jacobian.f90 +gckpp_adj_HessianSP.o : gckpp_adj_HessianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_HessianSP.f90 +gckpp_adj_Hessian.o : gckpp_adj_Hessian.f90 gckpp_adj_Parameters.f90 gckpp_adj_HessianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Hessian.f90 +gckpp_adj_Util.o : gckpp_adj_Util.f90 gckpp_adj_Parameters.f90 gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Util.f90 +gckpp_adj_StoichiomSP.o : gckpp_adj_StoichiomSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_StoichiomSP.f90 +gckpp_adj_Stoichiom.o : gckpp_adj_Stoichiom.f90 gckpp_adj_Parameters.f90 gckpp_adj_StoichiomSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Stoichiom.f90 +gckpp_adj_Rates.o : gckpp_adj_Rates.f90 gckpp_adj_Parameters.f90 gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Rates.f90 +gckpp_adj_Model.o : gckpp_adj_Model.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Model.f90 +gckpp_adj_Integrator.o : gckpp_adj_Integrator.f90 gckpp_adj_Parameters.f90 gckpp_adj_Precision.f90 gckpp_adj_Global.f90 gckpp_adj_LinearAlgebra.f90 gckpp_adj_Rates.f90 gckpp_adj_Function.f90 gckpp_adj_Jacobian.f90 gckpp_adj_Hessian.f90 gckpp_adj_Util.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Integrator.f90 +partition_adj.o : partition_adj.f CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/partition_adj.f +pbl_mix_adj_mod.o : pbl_mix_adj_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 adjoint/pbl_mix_adj_mod.f +rpmares_adj_mod.o : rpmares_adj_mod.f CMN_SIZE define.h + $(F90) -c -extend_source -r8 adjoint/rpmares_adj_mod.f +schem_adj.o : schem_adj.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/schem_adj.f +setemis_adj.o : setemis_adj.f CMN_O3 CMN_NOX CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/setemis_adj.f +sulfate_adj_mod.o : sulfate_adj_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h + $(F90) -c -r8 adjoint/sulfate_adj_mod.f +strat_chem_adj_mod.o : strat_chem_adj_mod.f CMN_SIZE + $(F90) -c -r8 adjoint/strat_chem_adj_mod.f +tagged_co_adj_mod.o : tagged_co_adj_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 adjoint/tagged_co_adj_mod.f +tagged_ox_adj_mod.o : tagged_ox_adj_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 adjoint/tagged_ox_adj_mod.f +upbdflx_adj_mod.o : upbdflx_adj_mod.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/upbdflx_adj_mod.f +wetscav_adj_mod.o : wetscav_adj_mod.f CMN_DIAG CMN_SIZE define.h define_adj.h + $(F90) -c -r8 adjoint/wetscav_adj_mod.f +weak_constraint_mod.o : weak_constraint_mod.f90 CMN_SIZE + $(F90) -c -r8 adjoint/weak_constraint_mod.f90 + +#========================= +# MODIFIED DIRECTORY FILES +#========================= +a3_read_mod.o : a3_read_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/a3_read_mod.f +a6_read_mod.o : a6_read_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/a6_read_mod.f +acetone_mod.o : acetone_mod.f CMN_DEP CMN_DIAG CMN_MONOT CMN_SIZE define.h + $(F90) -c -r8 modified/acetone_mod.f +bpch2_mod.o : bpch2_mod.f CMN_SIZE define.h define.h + $(F90) -c -r8 modified/bpch2_mod.f +calcrate.o : calcrate.f CMN CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/calcrate.f +carbon_mod.o : carbon_mod.f CMN CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/carbon_mod.f +chemdr.o : chemdr.f CMN CMN_DEP CMN_DIAG CMN_NOX CMN_O3 CMN_SIZE define.h comode.h define_adj.h + $(F90) -c -r8 modified/chemdr.f +chemistry_mod.o : chemistry_mod.f gckpp_adj_Global.f90 gckpp_adj_Rates.f90 gckpp_adj_Integrator.f90 CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/chemistry_mod.f +co2_mod.o : co2_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/co2_mod.f +comode_mod.o : comode_mod.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/comode_mod.f +convection_mod.o : convection_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/convection_mod.f +dao_mod.o : dao_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/dao_mod.f +dust_mod.o : dust_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h cmn_fj.h comode.h jv_cmn.h + $(F90) -c -r8 modified/dust_mod.f +geosfp_read_mod.o : geosfp_read_mod.f CMN_DIAG CMN_SIZE CMN_GCTM define.h + $(F90) -c -r8 modified/geosfp_read_mod.f +geos_chem_mod.o : geos_chem_mod.f CMN_SIZE CMN_DIAG CMN_GCTM comode.h define.h define_adj.h + $(F90) -c -r8 modified/geos_chem_mod.f +gamap_mod.o : gamap_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c modified/gamap_mod.f +gasconc.o : gasconc.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/gasconc.f +global_oh_mod.o : global_oh_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/global_oh_mod.f +global_ch4_mod.o : global_ch4_mod.f CMN CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/global_ch4_mod.f +grid_mod.o : grid_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/grid_mod.f +gwet_read_mod.o : gwet_read_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/gwet_read_mod.f +i6_read_mod.o : i6_read_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/i6_read_mod.f +julday_mod.o : julday_mod.f + $(F90) -c -r8 modified/julday_mod.f +input_mod.o : input_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h diag59_mod.f + $(F90) -c -r8 modified/input_mod.f +lightning_nox_mod.o : lightning_nox_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define.h + $(F90) -c -r8 modified/lightning_nox_mod.f +megan_mod.o : megan_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/megan_mod.f +paranox_mod.o : paranox_mod.f CMN_SIZE define.h comode.h + $(F90) -c -r8 paranox_mod.f +paranox_adj_mod.o : paranox_adj_mod.f CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/paranox_adj_mod.f +partition.o : partition.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/partition.f +pbl_mix_mod.o : pbl_mix_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/pbl_mix_mod.f +photoj.o : photoj.f define_adj.h cmn_fj.h CMN_SIZE define.h jv_cmn.h + $(F90) -c -r8 modified/photoj.f +physproc.o : physproc.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/physproc.f +pjc_pfix_geos5_window_mod.o : pjc_pfix_geos5_window_mod.f CMN CMN_GCTM CMN_SIZE define.h + $(F90) -c modified/pjc_pfix_geos5_window_mod.f +pjc_pfix_geosfp_window_mod.o : pjc_pfix_geosfp_window_mod.f CMN CMN_GCTM CMN_SIZE define.h + $(F90) -c modified/pjc_pfix_geosfp_window_mod.f +pressure_mod.o : pressure_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/pressure_mod.f +rpmares_mod.o : rpmares_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/rpmares_mod.f +hippo_mod.o : hippo_mod.f CMN_SIZE + $(F90) -c -extend_source -r8 modified/hippo_mod.f +atom_obs_mod.o : atom_obs_mod.f90 CMN_SIZE + $(F90) -c -extend_source -r8 modified/atom_obs_mod.f90 +restart_mod.o : restart_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/restart_mod.f +set_prof.o : set_prof.f define_adj.h cmn_fj.h CMN_SIZE define.h jv_cmn.h + $(F90) -c -r8 modified/set_prof.f +setemis.o : setemis.f CMN_DIAG CMN_NOX CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/setemis.f +soilnoxems.o : soilnoxems.f CMN_DEP CMN_DIAG CMN_NOX CMN_SIZE define.h commsoil.h + $(F90) -c -r8 modified/soilnoxems.f +sulfate_mod.o : sulfate_mod.f CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h rcp_mod.o + $(F90) -c -r8 modified/sulfate_mod.f +tagged_co_mod.o : tagged_co_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 modified/tagged_co_mod.f +tagged_ox_mod.o : tagged_ox_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/tagged_ox_mod.f +tpcore_geos5_window_mod.o : tpcore_geos5_window_mod.f90 + $(F90) -c -r8 modified/tpcore_geos5_window_mod.f90 +tpcore_geosfp_window_mod.o : tpcore_geosfp_window_mod.f90 + $(F90) -c -r8 modified/tpcore_geosfp_window_mod.f90 +time_mod.o : time_mod.f define.h + $(F90) -c -r8 modified/time_mod.f +tracer_mod.o : tracer_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/tracer_mod.f +transport_mod.o : transport_mod.f CMN CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/transport_mod.f +upbdflx_mod.o : upbdflx_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/upbdflx_mod.f +wetscav_mod.o : wetscav_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/wetscav_mod.f + +#==================== +# NEW DIRECTORY FILES +#==================== + +cgfam.o : cgfam.f + $(F90) -c -r8 new/cgfam.f +cgsearch.o : cgsearch.f + $(F90) -c -r8 new/cgsearch.f +linoz_mod.o : linoz_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h linoz.com + $(F90) -c -r8 new/linoz_mod.f +routines.o : routines.f + $(F90) -c -r8 new/routines.f +blas.o : new/blas.f + $(F90) -c -r8 new/blas.f +linpack.o : new/linpack.f + $(F90) -c -r8 new/linpack.f +timer.o : new/timer.f + $(F90) -c -r8 new/timer.f +netcdf_util_mod.o : netcdf_util_mod.f + $(F90) -c -r8 new/netcdf_util_mod.f +strat_chem_mod.o : strat_chem_mod.f CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 new/strat_chem_mod.f + +#==================== +# NETCDF directory +#==================== + +m_do_err_out.o : m_do_err_out.F90 + $(F90) -c -r8 NcdfUtil/m_do_err_out.F90 +m_netcdf_io_checks.o : m_netcdf_io_checks.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_checks.F90 +m_netcdf_io_close.o : m_netcdf_io_close.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_close.F90 +m_netcdf_io_create.o : m_netcdf_io_create.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_create.F90 +m_netcdf_io_define.o : m_netcdf_io_define.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_define.F90 +m_netcdf_io_get_dimlen.o : m_netcdf_io_get_dimlen.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_get_dimlen.F90 +m_netcdf_io_handle_err.o : m_netcdf_io_handle_err.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_handle_err.F90 +m_netcdf_io_open.o : m_netcdf_io_open.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_open.F90 +m_netcdf_io_read.o : m_netcdf_io_read.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_read.F90 +m_netcdf_io_readattr.o : m_netcdf_io_readattr.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_readattr.F90 +m_netcdf_io_write.o : m_netcdf_io_write.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_write.F90 + + +#==================== +# SCIA CODE +#==================== +ErrorModule.o : ErrorModule.f90 + $(F90) -c -r8 obs_operators/ErrorModule.f90 +sciabr_co_obs_mod.o : sciabr_co_obs_mod.f CMN_SIZE + $(F90) -c -r8 obs_operators/sciabr_co_obs_mod.f + +#==================== +# TES CODE +#==================== +tes_ch4_mod.o : tes_ch4_mod.f + $(F90) -c -r8 $< + +#==================== +# Other CH4 obs operators +#==================== +mem_ch4_mod.o : mem_ch4_mod.f CMN_SIZE + $(F90) -c -r8 $< +geocape_ch4_mod.o : geocape_ch4_mod.f CMN_SIZE + $(F90) -c -r8 $< +leo_ch4_mod.o : leo_ch4_mod.f CMN_SIZE + $(F90) -c -r8 $< + +#==================== +# OSIRIS CODE +#==================== +osiris_obs_mod.o : osiris_obs_mod.f90 + $(F90) -c -r8 obs_operators/osiris_obs_mod.f90 +#==================== + +#==================== +# Other +#==================== +improve_bc_mod.o : improve_bc_mod.f CMN_SIZE + $(F90) -c -r8 obs_operators/improve_bc_mod.f +population_mod.o : population_mod.f CMN_SIZE + $(F90) -c -r8 obs_operators/population_mod.f diff --git a/code/Dependencies.mk~ b/code/Dependencies.mk~ new file mode 100644 index 0000000..8f58072 --- /dev/null +++ b/code/Dependencies.mk~ @@ -0,0 +1,507 @@ +#============================================================================== +# Dependencies Listing +#============================================================================== +BLKSLV.o : BLKSLV.f jv_mie.h +CLDSRF.o : CLDSRF.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +CO_strat_pl.o : CO_strat_pl.f CMN_SIZE define.h +critical_load_mod.o : critical_load_mod.f CMN_SIZE +EFOLD.o : EFOLD.f +FLINT.o : FLINT.f +GAUSSP.o : GAUSSP.f +GEN.o : GEN.f jv_mie.h +fjx_acet_mod.o : fjx_acet_mod.f cmn_fj.h jv_cmn.h +JRATET.o : JRATET.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +JVALUE.o : JVALUE.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +Kr85_mod.o : Kr85_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h define.h +LEGND0.o : LEGND0.f +MATIN4.o : MATIN4.f +MIESCT.o : MIESCT.f jv_mie.h +NOABS.o : NOABS.f +OPMIE.o : OPMIE.f cmn_fj.h CMN_SIZE define.h jv_cmn.h jv_mie.h +RD_TJPL.o : RD_TJPL.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +RnPbBe_mod.o : RnPbBe_mod.f CMN_DEP CMN_DIAG CMN_SIZE define.h define.h +SPHERE.o : SPHERE.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +XSEC1D.o : XSEC1D.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +XSECO2.o : XSECO2.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +XSECO3.o : XSECO3.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +aerosol_mod.o : aerosol_mod.f CMN_DIAG CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h comode.h jv_cmn.h +aircraft_nox_mod.o : aircraft_nox_mod.f CMN CMN_DIAG CMN_SIZE define.h +airmas.o : airmas.f +anthroems.o : anthroems.f CMN_O3 CMN_SIZE define.h comode.h +arctas_ship_emiss_mod.o : arctas_ship_emiss_mod.f CMN_SIZE define.h +arsl1k.o : arsl1k.f +backsub.o : backsub.f CMN_SIZE define.h comode.h +benchmark_mod.o : benchmark_mod.f CMN_SIZE define.h +biofit.o : biofit.f CMN_DEP CMN_SIZE define.h +biofuel_mod.o : biofuel_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h +biomass_mod.o : biomass_mod.f CMN_DIAG CMN_SIZE define.h +boxvl.o : boxvl.f +bravo_mod.o : bravo_mod.f CMN_O3 CMN_SIZE define.h +c2h6_mod.o : c2h6_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h +cac_anthro_mod.o : cac_anthro_mod.f CMN_O3 CMN_SIZE define.h +ch3i_mod.o : ch3i_mod.f CMN_DEP CMN_DIAG CMN_SIZE define.h comode.h +charpak_mod.o : charpak_mod.f +cleanup.o : cleanup.f +comode_mod.o : comode_mod.f CMN_SIZE define.h comode.h +decomp.o : decomp.f CMN_SIZE define.h comode.h +diag03_mod.o : diag03_mod.f CMN_DIAG CMN_SIZE define.h +diag04_mod.o : diag04_mod.f CMN_DIAG CMN_SIZE define.h +diag1.o : diag1.f CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h +diag3.o : diag3.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h comode.h +diag41_mod.o : diag41_mod.f CMN_DIAG CMN_SIZE define.h +diag42_mod.o : diag42_mod.f CMN_DIAG CMN_SIZE define.h +diag48_mod.o : diag48_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag49_mod.o : diag49_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag50_mod.o : diag50_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag51_mod.o : diag51_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h jv_cmn.h +diag56_mod.o : diag56_mod.f CMN_DIAG CMN_SIZE define.h +diag59_mod.o : diag59_mod.f CMN_DIAG CMN_SIZE define.h +diag_2pm.o : diag_2pm.f CMN_DIAG CMN_SIZE define.h +diag_mod.o : diag_mod.f +diag_oh_mod.o : diag_oh_mod.f CMN_SIZE define.h comode.h +diag_pl_mod.o : diag_pl_mod.f CMN_DIAG CMN_SIZE define.h comode.h +diagoh.o : diagoh.f CMN_DIAG CMN_O3 CMN_SIZE define.h +directory_mod.o : directory_mod.f +drydep_mod.o : drydep_mod.f CMN_DEP CMN_DIAG CMN_GCTM CMN_SIZE define.h CMN_VEL commsoil.h comode.h +dust_dead_mod.o : dust_dead_mod.f CMN_GCTM CMN_SIZE define.h +edgar_mod.o : edgar_mod.f CMN_SIZE define.h +emep_mod.o : emep_mod.f CMN_O3 CMN_SIZE define.h +nei2005_anthro_mod.o : nei2005_anthro_mod.f CMN_O3 CMN_SIZE define.h +nei2008_anthro_mod.o : nei2008_anthro_mod.F90 CMN_O3 CMN_SIZE define.h +htap_mod.o : htap_mod.f90 CMN_O3 CMN_SIZE define.h +emf_scale.o : emf_scale.f CMN_O3 CMN_SIZE define.h comode.h +emfossil.o : emfossil.f CMN_DIAG CMN_O3 CMN_SIZE define.h comode.h rcp_mod.o +emisop.o : emisop.f CMN_ISOP CMN_SIZE define.h CMN_VEL +emisop_grass.o : emisop_grass.f CMN_ISOP CMN_SIZE define.h CMN_VEL +emisop_mb.o : emisop_mb.f CMN_ISOP CMN_SIZE define.h CMN_VEL +emissdr.o : emissdr.f CMN CMN_DIAG CMN_MONOT CMN_NOX CMN_O3 CMN_SIZE define.h comode.h +emissions_mod.o : emissions_mod.f CMN_O3 CMN_SIZE define.h rcp_mod.o +emmonot.o : emmonot.f CMN_MONOT CMN_SIZE define.h CMN_VEL +epa_nei_mod.o : epa_nei_mod.f CMN_O3 CMN_SIZE define.h +error_mod.o : error_mod.f define.h +fast_j.o : fast_j.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +fertadd.o : fertadd.f CMN_SIZE define.h commsoil.h +file_mod.o : file_mod.f define.h +findmon.o : findmon.f +fjfunc.o : fjfunc.f cmn_fj.h CMN_SIZE define.h +future_emissions_mod.o : future_emissions_mod.f CMN_SIZE define.h +fvdas_convect_mod.o : fvdas_convect_mod.f CMN_DIAG CMN_SIZE define.h +fcro2ho2.o : fcro2ho2.f +fyrno3.o : fyrno3.f +fyhoro.o : fyhoro.f +gc_biomass_mod.o : gc_biomass_mod.f CMN_SIZE define.h +gcap_convect_mod.o : gcap_convect_mod.f CMN_DIAG CMN_SIZE define.h +gcap_read_mod.o : gcap_read_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +geia_mod.o : geia_mod.f CMN_SIZE define.h +get_global_ch4.o : get_global_ch4.f +getifsun.o : getifsun.f CMN_SIZE define.h comode.h +gfed2_biomass_mod.o : gfed2_biomass_mod.f CMN_SIZE define.h +gfed3_biomass_mod.o : gfed3_biomass_mod.f CMN_SIZE define.h +global_hno3_mod.o : global_hno3_mod.f CMN_SIZE define.h +global_no3_mod.o : global_no3_mod.f CMN_SIZE define.h +global_nox_mod.o : global_nox_mod.f CMN_SIZE define.h +global_o1d_mod.o : global_o1d_mod.f CMN_SIZE define.h +global_o3_mod.o : global_o3_mod.f CMN_SIZE define.h +h2_hd_mod.o : h2_hd_mod.f CMN_DEP CMN_DIAG CMN_O3 CMN_SIZE define.h +hcn_ch3cn_mod.o : hcn_ch3cn_mod.f CMN_DEP CMN_DIAG CMN_SIZE define.h +icoads_ship_mod.o : icoads_ship_mod.f CMN_O3 CMN_SIZE define.h +ifort_errmsg.o : ifort_errmsg.f +initialize.o : initialize.f CMN_DIAG CMN_SIZE define.h +inphot.o : inphot.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +rd_aod.o : rd_aod.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +isoropiaII_adj_mod.o : isoropiaII_adj_mod.f new/isrpia_adj.inc + $(F90) -c -r8 new/isoropiaII_adj_mod.f +isoropiaIIcode_adj.o : isoropiaIIcode_adj.f new/isrpia_adj.inc + $(F90) -c -r8 new/isoropiaIIcode_adj.f +adBuffer.o : adBuffer.c + $(CC) -c new/adBuffer.c +adStack.o : adStack.c + $(CC) -c new/adStack.c +inquire_Mod.o : inquireMod.F90 +jsparse.o : jsparse.f CMN_SIZE define.h comode.h +jv_index.o : jv_index.f cmn_fj.h CMN_SIZE define.h comode.h +ksparse.o : ksparse.f CMN_SIZE define.h comode.h +lai_mod.o : lai_mod.f CMN_SIZE define.h +logical_mod.o : logical_mod.f +lump.o : lump.f CMN_SIZE define.h comode.h +main.o : main.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +mercury_mod.o : mercury_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +mmran_16.o : mmran_16.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +ndxx_setup.o : ndxx_setup.f CMN_DIAG CMN_SIZE define.h +ocean_mercury_mod.o : ocean_mercury_mod.f CMN_DEP CMN_SIZE define.h +ohsave.o : ohsave.f CMN_SIZE define.h comode.h +optdepth_mod.o : optdepth_mod.f CMN_DIAG CMN_SIZE define.h +pderiv.o : pderiv.f CMN_SIZE define.h comode.h +pjc_pfix_mod.o : pjc_pfix_mod.f CMN CMN_GCTM CMN_SIZE define.h +planeflight_mod.o : planeflight_mod.f CMN_DIAG CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h comode.h jv_cmn.h +precipfrac.o : precipfrac.f CMN_SIZE define.h +pulsing.o : pulsing.f CMN_SIZE define.h commsoil.h +rcp_mod.o : rcp_mod.f diag_mod.o aircraft_nox_mod.o dao_mod.o +rd_js.o : rd_js.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +rd_prof.o : rd_prof.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +rdisopt.o : rdisopt.f CMN_SIZE define.h +rdlai.o : rdlai.f CMN_DEP CMN_SIZE define.h CMN_VEL +rdland.o : rdland.f CMN_DEP CMN_SIZE define.h CMN_VEL +rdlight.o : rdlight.f CMN_ISOP CMN_SIZE define.h +rdmonot.o : rdmonot.f CMN_SIZE define.h +rdsoil.o : rdsoil.f CMN_SIZE define.h commsoil.h +readchem.o : readchem.f CMN_SIZE define.h comode.h +reader.o : reader.f CMN_GCTM CMN_SIZE define.h comode.h +readlai.o : readlai.f CMN_DEP CMN_SIZE define.h CMN_VEL +regrid_1x1_mod.o : regrid_1x1_mod.f CMN_GCTM CMN_SIZE define.h +retro_mod.o : retro_mod.f CMN CMN_SIZE CMN_O3 +regrid_a2a_mod.o : regrid_a2a_mod.F90 CMN_GCTM CMN_SIZE +ruralbox.o : ruralbox.f CMN_SIZE define.h comode.h +scale_anthro_mod.o : scale_anthro_mod.f CMN_SIZE define.h +schem.o : schem.f CMN_SIZE define.h +seasalt_mod.o : seasalt_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h +set_aer.o : set_aer.f cmn_fj.h CMN_SIZE define.h jv_cmn.h +setbase.o : setbase.f CMN CMN_ISOP CMN_MONOT CMN_SIZE define.h CMN_VEL +setemdep.o : setemdep.f CMN_SIZE define.h comode.h +setmodel.o : setmodel.f CMN_SIZE define.h comode.h +sfcwindsqr.o : sfcwindsqr.f CMN_SIZE define.h +smvgear.o : smvgear.f CMN_SIZE define.h comode.h +soilbase.o : soilbase.f CMN_SIZE define.h commsoil.h +soilcrf.o : soilcrf.f CMN_DEP CMN_SIZE define.h commsoil.h +soiltemp.o : soiltemp.f CMN_SIZE define.h commsoil.h +soiltype.o : soiltype.f CMN_SIZE define.h commsoil.h +streets_anthro_mod.o : streets_anthro_mod.f CMN_O3 CMN_SIZE define.h +subfun.o : subfun.f CMN_SIZE define.h comode.h +sunparam.o : sunparam.f +tcorr.o : tcorr.f +toms_mod.o : toms_mod.f CMN_SIZE define.h +tpcore_bc_mod.o : tpcore_bc_mod.f CMN CMN_SIZE define.h +tpcore_fvdas_mod.o : tpcore_fvdas_mod.f90 CMN_GCTM + $(F90) -c -r8 $*.f90 +tpcore_mod.o : tpcore_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define.h + $(F90) -c -r8 $*.f +tpcore_window_mod.o : tpcore_window_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define.h + $(F90) -c -r8 $*.f +tracerid_mod.o : tracerid_mod.f CMN_SIZE define.h comode.h +transfer_mod.o : transfer_mod.f CMN_SIZE define.h +tropopause.o : tropopause.f CMN CMN_DIAG CMN_SIZE define.h +tropopause_mod.o : tropopause_mod.f CMN CMN_SIZE define.h comode.h +unix_cmds_mod.o : unix_cmds_mod.f +update.o : update.f CMN_SIZE define.h comode.h +uvalbedo_mod.o : uvalbedo_mod.f CMN_SIZE define.h +vistas_anthro_mod.o : vistas_anthro_mod.f CMN_O3 CMN_SIZE define.h +xltmmp.o : xltmmp.f CMN_SIZE define.h +xtra_read_mod.o : xtra_read_mod.f CMN_DIAG CMN_SIZE define.h + +#------------------------------------------------------------------------------ +# MODIFIED FOR ORGANIZED DIRECTORY STRUCTURE +#------------------------------------------------------------------------------ + +#======================== +# ADJOINT DIRECTORY FILES +#======================== + +adj_arrays_mod.o : adj_arrays_mod.f define_adj.h define.h CMN_SIZE comode.h gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/adj_arrays_mod.f +calcrate_adj.o : calcrate_adj.f CMN CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/calcrate_adj.f +carbon_adj_mod.o : carbon_adj_mod.f CMN CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/carbon_adj_mod.f +checkpoint_mod.o : checkpoint_mod.f define.h + $(F90) -c -r8 adjoint/checkpoint_mod.f +checkpt_mod.o : checkpt_mod.f CMN_SIZE comode.h CMN_VEL define.h CMN_DEP + $(F90) -c -r8 adjoint/checkpt_mod.f +chemdr_adj.o : chemdr_adj.f CMN CMN_DEP CMN_DIAG CMN_NOX CMN_O3 CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/chemdr_adj.f +chemistry_adj_mod.o : chemistry_adj_mod.f gckpp_adj_Global.f90 gckpp_adj_Rates.f90 gckpp_adj_Integrator.f90 CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/chemistry_adj_mod.f +cleanup_adj.o : cleanup_adj.f + $(F90) -c -r8 adjoint/cleanup_adj.f +co2_adj_mod.o : co2_adj_mod.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/co2_adj_mod.f +CO_strat_pl_adj.o : CO_strat_pl_adj.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/CO_strat_pl_adj.f +convection_adj_mod.o : convection_adj_mod.f CMN_DIAG CMN_SIZE define.h define.h + $(F90) -c -r8 adjoint/convection_adj_mod.f +directory_adj_mod.o : directory_adj_mod.f + $(F90) -c -r8 adjoint/directory_adj_mod.f +dust_adj_mod.o : dust_adj_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define_adj.h + $(F90) -c -r8 adjoint/dust_adj_mod.f +emissions_adj_mod.o : emissions_adj_mod.f CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 adjoint/emissions_adj_mod.f +fvdas_convect_adj_mod.o : fvdas_convect_adj_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 adjoint/fvdas_convect_adj_mod.f +gc_type_mod.o : gc_type_mod.F CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/gc_type_mod.F +global_ch4_adj_mod.o : global_ch4_adj_mod.f CMN CMN_GCTM CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 $< +geos_chem_adj_mod.o : geos_chem_adj_mod.f CMN_O3 CMN_GCTM CMN_DIAG CMN_SIZE define.h comode.h define_adj.h + $(F90) -c -r8 adjoint/geos_chem_adj_mod.f +covariance_mod.o : covariance_mod.f CMN_SIZE CMN_DIAG CMN_GCTM define_adj.h + $(F90) -c -r8 adjoint/covariance_mod.f +input_adj_mod.o : input_adj_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h define_adj.h gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/input_adj_mod.f +inv_hessian_mod.o : inv_hessian_mod.f CMN_SIZE define_adj.h + $(F90) -c -r8 adjoint/inv_hessian_mod.f +inv_hessian_lbfgs_mod.o : inv_hessian_lbfgs_mod.f CMN_SIZE define_adj.h + $(F90) $(LAPACK_BLAS_FFLAGS) -c -r8 adjoint/inv_hessian_lbfgs_mod.f +inverse_driver.o : inverse_driver.f define_adj.h + $(F90) -c -r8 adjoint/inverse_driver.f +inverse_mod.o : inverse_mod.f define_adj.h define.h + $(F90) -c -r8 adjoint/inverse_mod.f +linoz_adj_mod.o : linoz_adj_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h linoz.com + $(F90) -c -r8 adjoint/linoz_adj_mod.f +logical_adj_mod.o : logical_adj_mod.f + $(F90) -c -r8 adjoint/logical_adj_mod.f +lump_adj.o : lump_adj.f CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/lump_adj.f +gckpp_adj_Precision.o : gckpp_adj_Precision.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Precision.f90 +gckpp_adj_Parameters.o : gckpp_adj_Parameters.f90 gckpp_adj_Precision.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Parameters.f90 +gckpp_adj_Global.o : gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Global.f90 +gckpp_adj_LinearAlgebra.o : gckpp_adj_LinearAlgebra.f90 gckpp_adj_Parameters.f90 gckpp_adj_JacobianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_LinearAlgebra.f90 +gckpp_adj_Monitor.o : gckpp_adj_Monitor.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Monitor.f90 +gckpp_adj_Initialize.o : gckpp_adj_Initialize.f90 gckpp_adj_Parameters.f90 gckpp_adj_Global.f90 gckpp_adj_Util.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Initialize.f90 +gckpp_adj_JacobianSP.o : gckpp_adj_JacobianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_JacobianSP.f90 +gckpp_adj_Function.o : gckpp_adj_Function.f90 gckpp_adj_Parameters.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Function.f90 +gckpp_adj_Jacobian.o : gckpp_adj_Jacobian.f90 gckpp_adj_Parameters.f90 gckpp_adj_JacobianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Jacobian.f90 +gckpp_adj_HessianSP.o : gckpp_adj_HessianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_HessianSP.f90 +gckpp_adj_Hessian.o : gckpp_adj_Hessian.f90 gckpp_adj_Parameters.f90 gckpp_adj_HessianSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Hessian.f90 +gckpp_adj_Util.o : gckpp_adj_Util.f90 gckpp_adj_Parameters.f90 gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Util.f90 +gckpp_adj_StoichiomSP.o : gckpp_adj_StoichiomSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_StoichiomSP.f90 +gckpp_adj_Stoichiom.o : gckpp_adj_Stoichiom.f90 gckpp_adj_Parameters.f90 gckpp_adj_StoichiomSP.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Stoichiom.f90 +gckpp_adj_Rates.o : gckpp_adj_Rates.f90 gckpp_adj_Parameters.f90 gckpp_adj_Global.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Rates.f90 +gckpp_adj_Model.o : gckpp_adj_Model.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Model.f90 +gckpp_adj_Integrator.o : gckpp_adj_Integrator.f90 gckpp_adj_Parameters.f90 gckpp_adj_Precision.f90 gckpp_adj_Global.f90 gckpp_adj_LinearAlgebra.f90 gckpp_adj_Rates.f90 gckpp_adj_Function.f90 gckpp_adj_Jacobian.f90 gckpp_adj_Hessian.f90 gckpp_adj_Util.f90 + $(F90) -c -r8 adjoint/gckpp_adj_Integrator.f90 +partition_adj.o : partition_adj.f CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/partition_adj.f +pbl_mix_adj_mod.o : pbl_mix_adj_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 adjoint/pbl_mix_adj_mod.f +rpmares_adj_mod.o : rpmares_adj_mod.f CMN_SIZE define.h + $(F90) -c -extend_source -r8 adjoint/rpmares_adj_mod.f +schem_adj.o : schem_adj.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/schem_adj.f +setemis_adj.o : setemis_adj.f CMN_O3 CMN_NOX CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/setemis_adj.f +sulfate_adj_mod.o : sulfate_adj_mod.f CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h + $(F90) -c -r8 adjoint/sulfate_adj_mod.f +strat_chem_adj_mod.o : strat_chem_adj_mod.f CMN_SIZE + $(F90) -c -r8 adjoint/strat_chem_adj_mod.f +tagged_co_adj_mod.o : tagged_co_adj_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 adjoint/tagged_co_adj_mod.f +tagged_ox_adj_mod.o : tagged_ox_adj_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 adjoint/tagged_ox_adj_mod.f +upbdflx_adj_mod.o : upbdflx_adj_mod.f CMN_SIZE define.h + $(F90) -c -r8 adjoint/upbdflx_adj_mod.f +wetscav_adj_mod.o : wetscav_adj_mod.f CMN_DIAG CMN_SIZE define.h define_adj.h + $(F90) -c -r8 adjoint/wetscav_adj_mod.f +weak_constraint_mod.o : weak_constraint_mod.f90 CMN_SIZE + $(F90) -c -r8 adjoint/weak_constraint_mod.f90 + +#========================= +# MODIFIED DIRECTORY FILES +#========================= +a3_read_mod.o : a3_read_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/a3_read_mod.f +a6_read_mod.o : a6_read_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/a6_read_mod.f +acetone_mod.o : acetone_mod.f CMN_DEP CMN_DIAG CMN_MONOT CMN_SIZE define.h + $(F90) -c -r8 modified/acetone_mod.f +bpch2_mod.o : bpch2_mod.f CMN_SIZE define.h define.h + $(F90) -c -r8 modified/bpch2_mod.f +calcrate.o : calcrate.f CMN CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/calcrate.f +carbon_mod.o : carbon_mod.f CMN CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/carbon_mod.f +chemdr.o : chemdr.f CMN CMN_DEP CMN_DIAG CMN_NOX CMN_O3 CMN_SIZE define.h comode.h define_adj.h + $(F90) -c -r8 modified/chemdr.f +chemistry_mod.o : chemistry_mod.f gckpp_adj_Global.f90 gckpp_adj_Rates.f90 gckpp_adj_Integrator.f90 CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/chemistry_mod.f +co2_mod.o : co2_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/co2_mod.f +comode_mod.o : comode_mod.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/comode_mod.f +convection_mod.o : convection_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/convection_mod.f +dao_mod.o : dao_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/dao_mod.f +dust_mod.o : dust_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h cmn_fj.h comode.h jv_cmn.h + $(F90) -c -r8 modified/dust_mod.f +geosfp_read_mod.o : geosfp_read_mod.f CMN_DIAG CMN_SIZE CMN_GCTM define.h + $(F90) -c -r8 modified/geosfp_read_mod.f +geos_chem_mod.o : geos_chem_mod.f CMN_SIZE CMN_DIAG CMN_GCTM comode.h define.h define_adj.h + $(F90) -c -r8 modified/geos_chem_mod.f +gamap_mod.o : gamap_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c modified/gamap_mod.f +gasconc.o : gasconc.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/gasconc.f +global_oh_mod.o : global_oh_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/global_oh_mod.f +global_ch4_mod.o : global_ch4_mod.f CMN CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/global_ch4_mod.f +grid_mod.o : grid_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/grid_mod.f +gwet_read_mod.o : gwet_read_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/gwet_read_mod.f +i6_read_mod.o : i6_read_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/i6_read_mod.f +julday_mod.o : julday_mod.f + $(F90) -c -r8 modified/julday_mod.f +input_mod.o : input_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h diag59_mod.f + $(F90) -c -r8 modified/input_mod.f +lightning_nox_mod.o : lightning_nox_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h define.h + $(F90) -c -r8 modified/lightning_nox_mod.f +megan_mod.o : megan_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/megan_mod.f +paranox_mod.o : paranox_mod.f CMN_SIZE define.h comode.h + $(F90) -c -r8 paranox_mod.f +paranox_adj_mod.o : paranox_adj_mod.f CMN_SIZE define.h comode.h + $(F90) -c -r8 adjoint/paranox_adj_mod.f +partition.o : partition.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/partition.f +pbl_mix_mod.o : pbl_mix_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/pbl_mix_mod.f +photoj.o : photoj.f define_adj.h cmn_fj.h CMN_SIZE define.h jv_cmn.h + $(F90) -c -r8 modified/photoj.f +physproc.o : physproc.f CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/physproc.f +pjc_pfix_geos5_window_mod.o : pjc_pfix_geos5_window_mod.f CMN CMN_GCTM CMN_SIZE define.h + $(F90) -c modified/pjc_pfix_geos5_window_mod.f +pjc_pfix_geosfp_window_mod.o : pjc_pfix_geosfp_window_mod.f CMN CMN_GCTM CMN_SIZE define.h + $(F90) -c modified/pjc_pfix_geosfp_window_mod.f +pressure_mod.o : pressure_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/pressure_mod.f +rpmares_mod.o : rpmares_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/rpmares_mod.f +hippo_mod.o : hippo_mod.f CMN_SIZE + $(F90) -c -extend_source -r8 modified/hippo_mod.f + +restart_mod.o : restart_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/restart_mod.f +set_prof.o : set_prof.f define_adj.h cmn_fj.h CMN_SIZE define.h jv_cmn.h + $(F90) -c -r8 modified/set_prof.f +setemis.o : setemis.f CMN_DIAG CMN_NOX CMN_SIZE define.h comode.h + $(F90) -c -r8 modified/setemis.f +soilnoxems.o : soilnoxems.f CMN_DEP CMN_DIAG CMN_NOX CMN_SIZE define.h commsoil.h + $(F90) -c -r8 modified/soilnoxems.f +sulfate_mod.o : sulfate_mod.f CMN_DIAG CMN_GCTM CMN_O3 CMN_SIZE define.h cmn_fj.h CMN_SIZE define.h rcp_mod.o + $(F90) -c -r8 modified/sulfate_mod.f +tagged_co_mod.o : tagged_co_mod.f CMN_DIAG CMN_O3 CMN_SIZE define.h + $(F90) -c -r8 modified/tagged_co_mod.f +tagged_ox_mod.o : tagged_ox_mod.f CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/tagged_ox_mod.f +tpcore_geos5_window_mod.o : tpcore_geos5_window_mod.f90 + $(F90) -c -r8 modified/tpcore_geos5_window_mod.f90 +tpcore_geosfp_window_mod.o : tpcore_geosfp_window_mod.f90 + $(F90) -c -r8 modified/tpcore_geosfp_window_mod.f90 +time_mod.o : time_mod.f define.h + $(F90) -c -r8 modified/time_mod.f +tracer_mod.o : tracer_mod.f CMN_SIZE define.h + $(F90) -c -r8 modified/tracer_mod.f +transport_mod.o : transport_mod.f CMN CMN_DIAG CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/transport_mod.f +upbdflx_mod.o : upbdflx_mod.f CMN_GCTM CMN_SIZE define.h + $(F90) -c -r8 modified/upbdflx_mod.f +wetscav_mod.o : wetscav_mod.f CMN_DIAG CMN_SIZE define.h + $(F90) -c -r8 modified/wetscav_mod.f + +#==================== +# NEW DIRECTORY FILES +#==================== + +cgfam.o : cgfam.f + $(F90) -c -r8 new/cgfam.f +cgsearch.o : cgsearch.f + $(F90) -c -r8 new/cgsearch.f +linoz_mod.o : linoz_mod.f CMN CMN_DIAG CMN_O3 CMN_SIZE define.h linoz.com + $(F90) -c -r8 new/linoz_mod.f +routines.o : routines.f + $(F90) -c -r8 new/routines.f +blas.o : new/blas.f + $(F90) -c -r8 new/blas.f +linpack.o : new/linpack.f + $(F90) -c -r8 new/linpack.f +timer.o : new/timer.f + $(F90) -c -r8 new/timer.f +netcdf_util_mod.o : netcdf_util_mod.f + $(F90) -c -r8 new/netcdf_util_mod.f +strat_chem_mod.o : strat_chem_mod.f CMN_DIAG CMN_SIZE define.h comode.h + $(F90) -c -r8 new/strat_chem_mod.f + +#==================== +# NETCDF directory +#==================== + +m_do_err_out.o : m_do_err_out.F90 + $(F90) -c -r8 NcdfUtil/m_do_err_out.F90 +m_netcdf_io_checks.o : m_netcdf_io_checks.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_checks.F90 +m_netcdf_io_close.o : m_netcdf_io_close.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_close.F90 +m_netcdf_io_create.o : m_netcdf_io_create.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_create.F90 +m_netcdf_io_define.o : m_netcdf_io_define.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_define.F90 +m_netcdf_io_get_dimlen.o : m_netcdf_io_get_dimlen.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_get_dimlen.F90 +m_netcdf_io_handle_err.o : m_netcdf_io_handle_err.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_handle_err.F90 +m_netcdf_io_open.o : m_netcdf_io_open.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_open.F90 +m_netcdf_io_read.o : m_netcdf_io_read.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_read.F90 +m_netcdf_io_readattr.o : m_netcdf_io_readattr.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_readattr.F90 +m_netcdf_io_write.o : m_netcdf_io_write.F90 + $(F90) -c -r8 NcdfUtil/m_netcdf_io_write.F90 + + +#==================== +# SCIA CODE +#==================== +ErrorModule.o : ErrorModule.f90 + $(F90) -c -r8 obs_operators/ErrorModule.f90 +sciabr_co_obs_mod.o : sciabr_co_obs_mod.f CMN_SIZE + $(F90) -c -r8 obs_operators/sciabr_co_obs_mod.f + +#==================== +# TES CODE +#==================== +tes_ch4_mod.o : tes_ch4_mod.f + $(F90) -c -r8 $< + +#==================== +# Other CH4 obs operators +#==================== +mem_ch4_mod.o : mem_ch4_mod.f CMN_SIZE + $(F90) -c -r8 $< +geocape_ch4_mod.o : geocape_ch4_mod.f CMN_SIZE + $(F90) -c -r8 $< +leo_ch4_mod.o : leo_ch4_mod.f CMN_SIZE + $(F90) -c -r8 $< + +#==================== +# OSIRIS CODE +#==================== +osiris_obs_mod.o : osiris_obs_mod.f90 + $(F90) -c -r8 obs_operators/osiris_obs_mod.f90 +#==================== + +#==================== +# Other +#==================== +improve_bc_mod.o : improve_bc_mod.f CMN_SIZE + $(F90) -c -r8 obs_operators/improve_bc_mod.f +population_mod.o : population_mod.f CMN_SIZE + $(F90) -c -r8 obs_operators/population_mod.f diff --git a/code/EFOLD.f b/code/EFOLD.f new file mode 100644 index 0000000..99a1a7c --- /dev/null +++ b/code/EFOLD.f @@ -0,0 +1,69 @@ +C $Id: EFOLD.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + subroutine EFOLD (F0, F1, N, F) +C----------------------------------------------------------------------- +C--- calculate the e-fold between two boundaries, given the value +C--- at both boundaries F0(x=0) = top, F1(x=1) = bottom. +C--- presume that F(x) proportional to exp[-A*x] for x=0 to x=1 +C--- d2F/dx2 = A*A*F and thus expect F1 = F0 * exp[-A] +C--- alternatively, could define A = ln[F0/F1] +C--- let X = A*x, d2F/dX2 = F +C--- assume equal spacing (not necessary, but makes this easier) +C--- with N-1 intermediate points (and N layers of thickness dX = A/N) +C--- +C--- 2nd-order finite difference: (F(i-1) - 2F(i) + F(i+1)) / dX*dX = F(i) +C--- let D = 1 / dX*dX: +C +C 1 | 1 0 0 0 0 0 | | F0 | +C | | | 0 | +C 2 | -D 2D+1 -D 0 0 0 | | 0 | +C | | | 0 | +C 3 | 0 -D 2D+1 -D 0 0 | | 0 | +C | | | 0 | +C | 0 0 -D 2D+1 -D 0 | | 0 | +C | | | 0 | +C N | 0 0 0 -D 2D+1 -D | | 0 | +C | | | 0 | +C N+1 | 0 0 0 0 0 1 | | F1 | +C +C----------------------------------------------------------------------- +C Advantage of scheme over simple attenuation factor: conserves total +C number of photons - very useful when using scheme for heating rates. +C Disadvantage: although reproduces e-folds very well for small flux +C differences, starts to drift off when many orders of magnitude are +C involved. +C----------------------------------------------------------------------- + implicit none + real*8 F0,F1,F(250) !F(N+1) + integer N + integer I + real*8 A,DX,D,DSQ,DDP1, B(101),R(101) +C + if(F0.eq.0.d0) then + do I=1,N + F(I)=0.d0 + enddo + return + elseif(F1.eq.0.d0) then + A = DLOG(F0/1.d-250) + else + A = DLOG(F0/F1) + endif +C + DX = float(N)/A + D = DX*DX + DSQ = D*D + DDP1 = D+D+1.d0 +C + B(2) = DDP1 + R(2) = +D*F0 + do I=3,N + B(I) = DDP1 - DSQ/B(I-1) + R(I) = +D*R(I-1)/B(I-1) + enddo + F(N+1) = F1 + do I=N,2,-1 + F(I) = (R(I) + D*F(I+1))/B(I) + enddo + F(1) = F0 + return + end diff --git a/code/FLINT.f b/code/FLINT.f new file mode 100644 index 0000000..ad8f85f --- /dev/null +++ b/code/FLINT.f @@ -0,0 +1,21 @@ +C $Id: FLINT.f,v 1.1 2009/06/09 21:51:54 daven Exp $ + REAL*8 FUNCTION FLINT (TINT,T1,T2,T3,F1,F2,F3) +C----------------------------------------------------------------------- +c Three-point linear interpolation function +C----------------------------------------------------------------------- + real*8 TINT,T1,T2,T3,F1,F2,F3 + IF (TINT .LE. T2) THEN + IF (TINT .LE. T1) THEN + FLINT = F1 + ELSE + FLINT = F1 + (F2 - F1)*(TINT -T1)/(T2 -T1) + ENDIF + ELSE + IF (TINT .GE. T3) THEN + FLINT = F3 + ELSE + FLINT = F2 + (F3 - F2)*(TINT -T2)/(T3 -T2) + ENDIF + ENDIF + return + end diff --git a/code/GAUSSP.f b/code/GAUSSP.f new file mode 100644 index 0000000..bb0a5f7 --- /dev/null +++ b/code/GAUSSP.f @@ -0,0 +1,20 @@ +C $Id: GAUSSP.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + SUBROUTINE GAUSSP (N,XPT,XWT) +C----------------------------------------------------------------------- +C Loads in pre-set Gauss points for 4 angles from 0 to +1 in cos(theta)=mu +C----------------------------------------------------------------------- + IMPLICIT NONE + INTEGER N,I + REAL*8 XPT(N),XWT(N) + REAL*8 GPT4(4),GWT4(4) + DATA GPT4/.06943184420297D0,.33000947820757D0,.66999052179243D0, + G .93056815579703D0/ + DATA GWT4/.17392742256873D0,.32607257743127D0,.32607257743127D0, + W .17392742256873D0/ + N = 4 + DO I=1,N + XPT(I) = GPT4(I) + XWT(I) = GWT4(I) + ENDDO + RETURN + END diff --git a/code/aerosol_mod.f b/code/aerosol_mod.f new file mode 100644 index 0000000..b55f21c --- /dev/null +++ b/code/aerosol_mod.f @@ -0,0 +1,1407 @@ +! $Id: aerosol_mod.f,v 1.2 2012/09/05 22:35:07 yanko Exp $ + MODULE AEROSOL_MOD +! +!****************************************************************************** +! Module AEROSOL_MOD contains variables and routines for computing optical +! properties for aerosols which are needed for both the FAST-J photolysis +! and ND21 optical depth diagnostics. (bmy, 7/20/04, 2/10/09) +! +! Module Variables: +! ============================================================================ +! (1 ) BCPI (REAL*8) : Hydrophilic black carbon aerosol [kg/m3] +! (2 ) BCPO (REAL*8) : Hydrophobic black carbon aerosol [kg/m3] +! (3 ) OCPI (REAL*8) : Hydrophilic organic carbon aerosol [kg/m3] +! (4 ) OCPO (REAL*8) : Hydrophilic organic carbon aerosol [kg/m3] +! (5 ) SALA (REAL*8) : Accumulation mode seasalt aerosol [kg/m3] +! (6 ) SALC (REAL*8) : Coarse mode seasalt aerosol [kg/m3] +! (7 ) SO4_NH4_NIT (REAL*8) : Lumped SO4-NH4-NIT aerosol [kg/m3] +! (8 ) SOILDUST (REAL*8) : Mineral dust aerosol from soils [kg/m3] +! +! Module Routines: +! ============================================================================ +! (1 ) AEROSOL_RURALBOX : Computes loop indices & other properties for RDAER +! (2 ) AEROSOL_CONC : Computes aerosol conc in [kg/m3] for FAST-J & diags +! (3 ) RDAER : Computes optical properties for aerosls for FAST-J +! (4 ) INIT_AEROSOL : Allocates and zeroes all module arrays +! (5 ) CLEANUP_AEROSOL : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by "aerosol_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch 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 ) directory_mod.f : Module w/ GEOS-CHEM data & met field dirs +! (6 ) error_mod.f : Module w/ I/O error and NaN check routines +! (7 ) logical_mod.f : Module w/ GEOS-CHEM logical switches +! (8 ) time_mod.f : Module w/ routines for computing time & date +! (9 ) tracer_mod.f : Module w/ GEOS-CHEM tracer array STT etc. +! (10) tracerid_mod.f : Module w/ pointers to tracers & emissions +! (11) transfer_mod.f : Module w/ routines to cast & resize arrays +! (12) tropopause_mod.f : Module w/ routines to read in ann mean tropopause +! +! NOTES: +! (1 ) Added AEROSOL_RURALBOX routine (bmy, 9/28/04) +! (2 ) Now convert ABSHUM from absolute humidity to relative humidity in +! AEROSOL_RURALBOX, using the same algorithm as in "gasconc.f". +! (bmy, 1/27/05) +! (3 ) Now references "tropopause_mod.f" (bmy, 8/22/05) +! (4 ) Now add contribution of SOA4 into Hydrophilic OC (dkh, bmy, 5/18/06) +! (5 ) Remove support for GEOS-1 and GEOS-STRAT met fields (bmy, 8/4/06) +! (6 ) Add support for variable tropopause (bdf, phs, 9/14/06) +! (7 ) Now set OCF=2.1 in AEROSOL_CONC for consistency w/ carbon_mod.f +! (tmf, 2/10/09) +! (8 ) Add WTAREA and WERADIUS for dicarbonyl SOA production. +! WTAREA is the same as TAREA, but excludes dry dust, BCPO and OCPO; +! use same units as TAREA. +! WERADIUS is same as ERADIUS, but excludes dry dust, BCPO and OCPO; +! use same units as ERADIUS. (tmf, 3/2/09) +! (9 ) Add SOAG and SOAM species. (tmf, ccc, 3/2/09) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "aerosol_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: SOILDUST + + ! ... and these routines + PUBLIC :: AEROSOL_CONC + PUBLIC :: AEROSOL_RURALBOX + PUBLIC :: RDAER + PUBLIC :: CLEANUP_AEROSOL + + !================================================================= + ! MODULE VARIABLES + !================================================================= + REAL*8, ALLOCATABLE :: BCPI(:,:,:) + REAL*8, ALLOCATABLE :: BCPO(:,:,:) + REAL*8, ALLOCATABLE :: OCPI(:,:,:) + REAL*8, ALLOCATABLE :: OCPO(:,:,:) + REAL*8, ALLOCATABLE :: SALA(:,:,:) + REAL*8, ALLOCATABLE :: SALC(:,:,:) + REAL*8, ALLOCATABLE :: SO4_NH4_NIT(:,:,:) + REAL*8, ALLOCATABLE :: SOILDUST(:,:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE AEROSOL_RURALBOX( N_TROP ) +! +!****************************************************************************** +! Subroutine AEROSOL_RURALBOX computes quantities that are needed by RDAER. +! This mimics the call to RURALBOX, which is only done for fullchem runs. +! (bmy, 9/28/04, 9/14/06) +! +! Arguments as Output: +! ============================================================================ +! (1 ) N_TROP (INTEGER) : Number of tropospheric boxes +! +! NOTES: +! (1 ) Now convert ABSHUM from absolute humidity to relative humidity in +! AEROSOL_RURALBOX, using the same algorithm as in "gasconc.f". +! (bmy, 1/27/05) +! (2 ) Now references ITS_IN_THE_TROP from "tropopause_mod.f" to diagnose +! boxes w/in the troposphere. (bmy, 8/22/05) +! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (4 ) Modified for variable tropopause (phs, bdf, 9/14/06) +!****************************************************************************** +! + ! References to F90 modules + USE COMODE_MOD, ONLY : ABSHUM, AIRDENS, IXSAVE + USE COMODE_MOD, ONLY : IYSAVE, IZSAVE, JLOP + USE DAO_MOD, ONLY : AD, AVGW, MAKE_AVGW, T + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + USE LOGICAL_MOD, ONLY : LVARTROP + +# include "CMN_SIZE" ! Size parameters +# include "comode.h" ! AD, AVG, WTAIR, other SMVGEAR variables + + ! Argumetns + INTEGER, INTENT(OUT) :: N_TROP + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER, SAVE :: N_TROP_BOXES + INTEGER :: I, J, L, JLOOP + REAL*8 :: CONSEXP, TK, VPRESH2O + REAL*8, EXTERNAL :: BOXVL + + !================================================================= + ! AEROSOL_RURALBOX begins here! + !================================================================= + + ! Initialize + NLONG = IIPAR + NLAT = JJPAR + NVERT = IVERT + NPVERT = NVERT + + ! Create AVGW field -- mixing ratio of water [v/v] + CALL MAKE_AVGW + + !================================================================= + ! Pre-save SMVGEAR loop indices on the first call + !================================================================= + + ! bdf-phs: must do it everytime with a variable tropopause + IF ( FIRST .or. LVARTROP ) THEN + + ! Initialize 1-D index + JLOOP = 0 + + ! Loop over grid boxes + DO L = 1, NVERT + DO J = 1, NLAT + DO I = 1, NLONG + + ! JLOP is the 1-D grid box loop index + JLOP(I,J,L) = 0 + + !---------------------------------- + ! Boxes w/in ann mean tropopause + !---------------------------------- + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + + ! Increment JLOOP for trop boxes + JLOOP = JLOOP + 1 + + ! Save JLOOP in SMVGEAR array JLOP + JLOP(I,J,L) = JLOOP + + ! These translate JLOOP back to an (I,J,L) triplet + IXSAVE(JLOOP) = I + IYSAVE(JLOOP) = J + IZSAVE(JLOOP) = L + + ENDIF + ENDDO + ENDDO + ENDDO + + ! JLOOP is now the number of boxes w/in GEOS-CHEM's annual mean + ! tropopause. Copy to SAVEd variable N_TROP_BOXES. + write(6,*) ' in aerosol ruralbox, val of trop boxes: ', jloop + N_TROP_BOXES = JLOOP + + ! Set NTLOOP, NTTLOOP here. Howeve, we will have to reset these + ! after the call to READER, since READER redefines these. + NTLOOP = JLOOP + NTTLOOP = JLOOP + + ! Reset first-time flag + FIRST = .FALSE. + ENDIF + + ! Copy N_TROP_BOXES to NTROP for passing back to calling program + N_TROP = N_TROP_BOXES + + !================================================================= + ! Compute AIRDENS and ABSHUM at every timestep + ! + ! NOTE: In the full-chemistry simulation, SMVGEAR uses the ABSHUM + ! array for both absolute humidity [molec H2O/cm3] and relative + ! humidity [fraction]. This conversion is done within subroutine + ! "gasconc.f", which is called from "chemdr.f". + ! + ! The computation of aerosol optical depths is done in routine + ! RDAER of "aerosol_mod.f". In the full-chemistry simulation, + ! RDAER is called after "gasconc.f". At the time when routine + ! RDAER is called, ABSHUM has already been converted to relative + ! humidity. + ! + ! For the offline aerosol simulation, we must also convert ABSHUM + ! from absolute humidity to relative humidity using the same + ! algorithm from "gasconc.f" (see code below). This will ensure + ! that aerosol optical depths in the offline aerosol simulation + ! will be computed in the same way as in the full chemistry + ! simulation. (bmy, 1/27/05) + !================================================================= + + ! Initialize 1-D index + JLOOP = 0 + + ! Loop over grid boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, JLOOP, TK, CONSEXP, VPRESH2O ) +!$OMP+SCHEDULE( DYNAMIC ) + DO L = 1, NVERT + DO J = 1, NLAT + DO I = 1, NLONG + + ! Get 1-D loop index + JLOOP = JLOP(I,J,L) + + !---------------------------------- + ! Only process tropospheric boxes + !---------------------------------- + IF ( JLOOP > 0 ) THEN + + ! Air density in [molec/cm3] + AIRDENS(JLOOP) = AD(I,J,L)*1000.d0/BOXVL(I,J,L)*AVG/WTAIR + + ! ABSHUM = absolute humidity [molec H2O/cm3 air] + ABSHUM(JLOOP) = AVGW(I,J,L) * AIRDENS(JLOOP) + + ! Convert ABSHUM to relative humidity [fraction] + ! using the same algorithm as in "gasconc.f" + TK = T(I,J,L) + CONSEXP = 17.2693882d0 * + & ( TK - 273.16d0 ) / ( TK - 35.86d0 ) + VPRESH2O = CONSVAP * EXP( CONSEXP ) / TK + ABSHUM(JLOOP) = ABSHUM(JLOOP) / VPRESH2O + + ENDIF + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE AEROSOL_RURALBOX + +!------------------------------------------------------------------------------ + + SUBROUTINE AEROSOL_CONC +! +!****************************************************************************** +! Subroutine AEROSOL_CONC computes aerosol concentrations in kg/m3 from +! the tracer mass in kg in the STT array. These are needed to compute +! optical properties for photolysis and for the optical depth diagnostics. +! (bmy, 7/20/04, 2/10/09) +! +! This code was originally included in "chemdr.f", but the same computation +! also needs to be done for offline aerosol simulations. Therefore, we have +! split this code off into a separate subroutine which can be called by both +! fullchem and offline aerosol simulations. +! +! NOTES: +! (1 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (2 ) Now add contribution from SOA4 into Hydrophilic OC (dkh, bmy, 5/18/06) +! (3 ) Now set OCF=2.1 to be consistent w/ "carbon_mod.f" (tmf, 2/10/09) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AIRVOL + USE LOGICAL_MOD, ONLY : LCARB, LDUST, LSOA, LSSALT, LSULF + USE TRACER_MOD, ONLY : STT + USE TRACERID_MOD, ONLY : IDTBCPI, IDTBCPO, IDTDST1, IDTDST2 + USE TRACERID_MOD, ONLY : IDTDST3, IDTDST4, IDTNH4, IDTNIT + USE TRACERID_MOD, ONLY : IDTOCPO, IDTOCPI, IDTSALA, IDTSALC + USE TRACERID_MOD, ONLY : IDTSOA1, IDTSOA2, IDTSOA3, IDTSOA4 + USE TRACERID_MOD, ONLY : IDTSO4 + USE TRACERID_MOD, ONLY : IDTSOAG, IDTSOAM + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: I, J, L, N + + ! We carry carbon mass only in OC and here need to multiply by + ! 1.4 to account for the mass of the other chemical components + ! (rjp, bmy, 7/15/04) + !----------------------------------------------------------------- + ! Prior to 2/10/09: + ! Now change OCF to 2.1 to be consistent w/ "carbon_mod.f" + ! (tmf, 2/10/09) + !REAL*8, PARAMETER :: OCF = 1.4d0 + !----------------------------------------------------------------- + REAL*8, PARAMETER :: OCF = 2.1d0 + + ! For SOAG, assume the total aerosol mass/glyoxal mass = 1.d0 + ! for now (tmf, 1/7/09) + REAL*8, PARAMETER :: OCFG = 1.d0 + + ! For SOAM, assume the total aerosol mass/methylglyoxal mass = 1.d0 + ! for now (tmf, 1/7/09) + REAL*8, PARAMETER :: OCFM = 1.d0 + !================================================================= + ! AEROSOL_CONC begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_AEROSOL + FIRST = .FALSE. + ENDIF + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N ) +!$OMP+SCHEDULE( DYNAMIC ) + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + + !============================================================== + ! S U L F A T E A E R O S O L S + ! + ! Dump hydrophilic aerosols into one array that will be passed + ! to RDAER and then used for heterogeneous chemistry as well + ! as photolysis rate calculations interatively. + ! + ! For the full-chemistry run, If LSULF=F, then we read these + ! aerosol data from Mian's simulation. If LSULF=T then we use + ! the online tracers. + ! + ! Now assume that all sulfate, ammonium, and nitrate are + ! hydrophilic but sooner or later we can pass only hydrophilic + ! aerosols from the thermodynamic calculations for this + ! purpose. This dumping should be done before calling INITGAS, + ! which converts the unit of STT from kg/box to molec/cm3. + ! + ! Units of SO4_NH4_NIT are [kg/m3]. (rjp, bmy, 3/23/03) + !============================================================== + IF ( LSULF ) THEN + + ! Compute SO4 aerosol concentration [kg/m3] + SO4_NH4_NIT(I,J,L) = ( STT(I,J,L,IDTSO4) + + & STT(I,J,L,IDTNH4) + + & STT(I,J,L,IDTNIT) ) / AIRVOL(I,J,L) + + ENDIF + + !============================================================== + ! C A R B O N & 2 n d A R Y O R G A N I C A E R O S O L S + ! + ! Compute hydrophilic and hydrophobic BC and OC in [kg/m3] + ! Also add online 2ndary organics if necessary + !============================================================== + IF ( LCARB ) THEN + + ! Hydrophilic BC [kg/m3] + BCPI(I,J,L) = STT(I,J,L,IDTBCPI) / AIRVOL(I,J,L) + + ! Hydrophobic BC [kg/m3] + BCPO(I,J,L) = STT(I,J,L,IDTBCPO) / AIRVOL(I,J,L) + + ! Hydrophobic OC [kg/m3] + OCPO(I,J,L) = STT(I,J,L,IDTOCPO) * OCF / AIRVOL(I,J,L) + + IF ( LSOA ) THEN + + ! Hydrophilic primary OC plus SOA [kg/m3A. We need + ! to multiply by OCF to account for the mass of other + ! components which are attached to the OC aerosol. + ! (rjp, bmy, 7/15/04) + OCPI(I,J,L) = ( STT(I,J,L,IDTOCPI) * OCF + & + STT(I,J,L,IDTSOA1) + & + STT(I,J,L,IDTSOA2) + & + STT(I,J,L,IDTSOA3) + & + STT(I,J,L,IDTSOA4) ) / AIRVOL(I,J,L) + + ! Check to see if we are simulating SOAG and SOAM (tmf, 1/7/09) + IF ( IDTSOAG > 0 ) THEN + OCPI(I,J,L) = OCPI(I,J,L) + + & STT(I,J,L,IDTSOAG) * OCFG / AIRVOL(I,J,L) + ENDIF + + IF ( IDTSOAM > 0 ) THEN + OCPI(I,J,L) = OCPI(I,J,L) + + & STT(I,J,L,IDTSOAM) * OCFM / AIRVOL(I,J,L) + ENDIF + ELSE + + ! Hydrophilic primary and SOA OC [kg/m3]. We need + ! to multiply by OCF to account for the mass of other + ! components which are attached to the OC aerosol. + ! (rjp, bmy, 7/15/04) + OCPI(I,J,L) = STT(I,J,L,IDTOCPI) * OCF / AIRVOL(I,J,L) + + ENDIF + + ! Now avoid division by zero (bmy, 4/20/04) + BCPI(I,J,L) = MAX( BCPI(I,J,L), 1d-35 ) + OCPI(I,J,L) = MAX( OCPI(I,J,L), 1d-35 ) + BCPO(I,J,L) = MAX( BCPO(I,J,L), 1d-35 ) + OCPO(I,J,L) = MAX( OCPO(I,J,L), 1d-35 ) + + ENDIF + + !=========================================================== + ! M I N E R A L D U S T A E R O S O L S + ! + ! NOTE: We can do better than this! Currently we carry 4 + ! dust tracers...but het. chem and fast-j use 7 dust bins + ! hardwired from Ginoux. + ! + ! Now, I apportion the first dust tracer into four smallest + ! dust bins equally in mass for het. chem and fast-j. + ! + ! Maybe we need to think about chaning our fast-j and het. + ! chem to use just four dust bins or more flexible + ! calculations depending on the number of dust bins. + ! (rjp, 03/27/04) + !=========================================================== + IF ( LDUST ) THEN + + ! Lump 1st dust tracer for het chem + DO N = 1, 4 + SOILDUST(I,J,L,N) = + & 0.25d0 * STT(I,J,L,IDTDST1) / AIRVOL(I,J,L) + ENDDO + + ! Other hetchem bins + SOILDUST(I,J,L,5) = STT(I,J,L,IDTDST2) / AIRVOL(I,J,L) + SOILDUST(I,J,L,6) = STT(I,J,L,IDTDST3) / AIRVOL(I,J,L) + SOILDUST(I,J,L,7) = STT(I,J,L,IDTDST4) / AIRVOL(I,J,L) + + ENDIF + + !=========================================================== + ! S E A S A L T A E R O S O L S + ! + ! Compute accumulation & coarse mode concentration [kg/m3] + !=========================================================== + IF ( LSSALT ) THEN + + ! Accumulation mode seasalt aerosol [kg/m3] + SALA(I,J,L) = STT(I,J,L,IDTSALA) / AIRVOL(I,J,L) + + ! Coarse mode seasalt aerosol [kg/m3] + SALC(I,J,L) = STT(I,J,L,IDTSALC) / AIRVOL(I,J,L) + + ! Avoid division by zero + SALA(I,J,L) = MAX( SALA(I,J,L), 1d-35 ) + SALC(I,J,L) = MAX( SALC(I,J,L), 1d-35 ) + + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE AEROSOL_CONC + +!------------------------------------------------------------------------------ + + SUBROUTINE RDAER( MONTH, YEAR ) +! +!****************************************************************************** +! Subroutine RDAER reads global aerosol concentrations as determined by +! Mian Chin. Calculates optical depth at each level for "set_prof.f". +! Also calculates surface area for heterogeneous chemistry. It uses aerosol +! parameters in FAST-J input file "jv_spec.dat" for these calculations. +! (rvm, rjp, tdf, bmy, 11/04/01, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) THISMONTH (INTEGER) : Number of the current month (1-12) +! (2 ) THISYEAR (INTEGER) : 4-digit year value (e.g. 1997, 2002) + +! NOTES: +! (1 ) At the point in which "rdaer.f" is called, ABSHUM is actually +! absolute humidity and not relative humidity (rvm, bmy, 2/28/02) +! (2 ) Now force double-precision arithmetic by using the "D" exponent. +! (bmy, 2/28/02) +! (3 ) At present aerosol growth is capped at 90% RH. The data +! in jv_spec.dat could be used to allow a particle to grow to +! 99% RH if desired. (rvm, 3/15/02) +! (4 ) Bug fix: TEMP2 needs to be sized (IIPAR,JJPAR,LLPAR) (bmy, 5/30/02) +! (5 ) Now reference BXHEIGHT from "dao_mod.f". Also references ERROR_STOP +! from "error_mod.f". Delete local declaration of TIME, since that +! is also declared w/in comode.h -- this causes compile-time errors +! on the ALPHA platform. (gcc, bmy, 11/6/02) +! (6 ) Now use the online SO4, NH4, NIT aerosol, taken from the STT array, +! and passed via SO4_NH4_NIT argument if sulfate chemistry is turned on. +! Otherwise, read monthly mean sulfate from disk. (rjp, bmy, 3/23/03) +! (7 ) Now call READ_BPCH2 with QUIET=.TRUE., which prevents info from being +! printed to stdout. Also made cosmetic changes. (bmy, 3/27/03) +! (8 ) Add BCPI, BCPO, OCPI, OCPO to the arg list. Bug fix: for online +! sulfate & carbon aerosol tracers, now make sure these get updated +! every timestep. Now references "time_mod.f". Now echo info about +! which online/offline aerosols we are using. Updated comments. +! (bmy, 4/9/04) +! (9 ) Add SALA, SALC to the arg list (rjp, bec, bmy, 4/20/04) +! (10) Now references DATA_DIR from "directory_mod.f". Now references LSULF, +! LCARB, LSSALT from "logical_mod.f". Added minor bug fix for +! conducting the appropriate scaling for optical depth for ND21 +! diagnostic. Now make MONTH and YEAR optional arguments. Now bundled +! into "aerosol_mod.f". (rvm, aad, clh, bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_NAME_EXT, GET_RES_EXT + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE COMODE_MOD, ONLY : ABSHUM, ERADIUS, IXSAVE + USE COMODE_MOD, ONLY : IYSAVE, IZSAVE, TAREA + USE COMODE_MOD, ONLY : WTAREA, WERADIUS + USE DAO_MOD, ONLY : BXHEIGHT + USE DIAG_MOD, ONLY : AD21 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE ERROR_MOD, ONLY : ERROR_STOP + USE LOGICAL_MOD, ONLY : LSULF, LCARB, LSSALT + USE TIME_MOD, ONLY : ITS_A_NEW_MONTH + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM + USE TRANSFER_MOD, ONLY : TRANSFER_3D + + IMPLICIT NONE + +# include "cmn_fj.h" ! LPAR, CMN_SIZE +# include "jv_cmn.h" ! ODAER, QAA, RAA, QAA_AOD (clh) +# include "CMN_DIAG" ! ND21, LD21 +# include "comode.h" ! NTLOOP + + ! Arguments + INTEGER, INTENT(IN), OPTIONAL :: MONTH, YEAR + + ! Local variables + LOGICAL :: FIRST = .TRUE. + LOGICAL :: DO_READ_DATA + CHARACTER(LEN=255) :: FILENAME + INTEGER :: THISMONTH, THISYEAR + INTEGER :: I, J, L, N, R, JLOOP, IRH, IRHN + INTEGER, SAVE :: MONTH_LAST = -999 + REAL*4 :: TEMP(IGLOB,JGLOB,LGLOB) + REAL*8 :: TEMP2(IIPAR,JJPAR,LLPAR) + REAL*8 :: MSDENS(NAER), XTAU, DRYAREA + + + ! Mass of hydrophobic aerosol from Mian Chin + REAL*8, SAVE :: DAERSL(IIPAR,JJPAR,LLPAR,2) + + ! Mass of hydrophilic aerosol from Mian Chin + REAL*8, SAVE :: WAERSL(IIPAR,JJPAR,LLPAR,NAER) + + ! Fraction of aerosol from H2O + REAL*8 :: FWET + + ! Effective radius at RH bins read in from "jv_spec.dat" + REAL*8 :: RW(NRH) + + ! Effective radius at RH after interpolation + REAL*8 :: REFF + + ! Q at different RH bins read in from "jv_spec.dat" + REAL*8 :: QW(NRH) + + ! Used to interpolate between sizes + REAL*8 :: FRAC + + ! Change in Q (extinction efficiency) + REAL*8 :: SCALEQ + + ! Change in Radius with RH + REAL*8 :: SCALER + + ! Chnge in Optical Depth vs RH + REAL*8 :: SCALEOD(IIPAR,JJPAR,LLPAR,NRH) + + ! Change in Vol vs RH + REAL*8 :: SCALEVOL(IIPAR,JJPAR,LLPAR) + + ! Relative Humidities + REAL*8, SAVE :: RH(NRH) = (/0d0,0.5d0,0.7d0,0.8d0,0.9d0/) + + ! Index to aerosol types in jv_spec.dat + ! The following are ordered according to the mass densities below + INTEGER, SAVE :: IND(NAER) = (/22, 29, 36, 43, 50/) + + !================================================================= + ! RDAER begins here! + !================================================================= + + ! Copy MONTH argument to local variable THISMONTH + IF ( PRESENT( MONTH ) ) THEN + THISMONTH = MONTH + ELSE + THISMONTH = 0 + ENDIF + + ! Copy YEAR argument to local variable THISYEAR + IF ( PRESENT( YEAR ) ) THEN + THISYEAR = YEAR + ELSE + THISYEAR = 0 + ENDIF + + ! Set a logical flag if we have to read data from disk + ! (once per month, for full-chemistry simulations) + DO_READ_DATA = ( ITS_A_FULLCHEM_SIM() .and. ITS_A_NEW_MONTH() ) + + !================================================================= + ! For full-chemistry runs w/ offline fields, define filename + !================================================================= + IF ( DO_READ_DATA ) THEN + + ! Filename + FILENAME = TRIM( DATA_DIR ) // 'aerosol_200106/aerosol.' // + & GET_NAME_EXT() // '.' // GET_RES_EXT() + + ! Use the "generic" year 1996 + XTAU = GET_TAU0( THISMONTH, 1, 1996 ) + + ENDIF + + !================================================================= + ! S U L F A T E A E R O S O L S + ! + ! If LSULF = TRUE, then take the lumped SO4, NH4, NIT + ! concentrations [kg/m3] computed by AEROSOL_CONC, and save + ! into WAERSL(:,:,:,1) for use w/ FAST-J and hetchem. This is + ! updated every timestep. (For fullchem and offline runs) + ! + ! If LSULF = FALSE, then read monthly mean offline sulfate aerosol + ! concentrations [kg/m3] from disk at the start of each month. + ! (For fullchem simulations only) + !================================================================= + IF ( LSULF ) THEN + + !----------------------------------- + ! Use online aerosol concentrations + !----------------------------------- + IF ( FIRST ) THEN + WRITE( 6, 100 ) + 100 FORMAT( ' - RDAER: Using online SO4 NH4 NIT!' ) + ENDIF + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + WAERSL(I,J,L,1) = SO4_NH4_NIT(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE + + !----------------------------------- + ! Read from disk -- fullchem only + !----------------------------------- + IF ( DO_READ_DATA ) THEN + + ! Print filename + WRITE( 6, 105 ) TRIM( FILENAME ) + 105 FORMAT( ' - RDAER: Reading SULFATE from ', a ) + + ! Read data + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 1, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + ! Cast to REAL*8 and resize + CALL TRANSFER_3D( TEMP, WAERSL(:,:,:,1) ) + ENDIF + ENDIF + + !================================================================= + ! C A R B O N & 2 n d A R Y O R G A N I C A E R O S O L S + ! + ! If LCARB = TRUE, then take Hydrophilic OC, Hydrophobic OC, + ! Hydropilic BC, and Hydrophobic BC, and 2ndary organic aerosol + ! concentrations [kg/m3] that have been computed by AEROSOL_CONC. + ! Save these into DAERSL and WAERSL for use w/ FAST-J and hetchem. + ! These fields are updated every chemistry timestep. + ! (For both fullchem and offline simulations) + ! + ! If LCARB = FALSE, then read monthly mean carbon aerosol + ! concentrations [kg/m3] from disk at the start of each month. + ! (For full chemistry simulations only) + !================================================================= + IF ( LCARB ) THEN + + !----------------------------------- + ! Use online aerosol concentrations + !----------------------------------- + IF ( FIRST ) THEN + WRITE( 6, 110 ) + 110 FORMAT( ' - RDAER: Using online BCPI OCPI BCPO OCPO!' ) + ENDIF + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Hydrophilic BC (a.k.a EC) [kg/m3] + WAERSL(I,J,L,2) = BCPI(I,J,L) + + ! Hydrophilic OC [kg/m3] + WAERSL(I,J,L,3) = OCPI(I,J,L) + + ! Hydrophobic BC (a.k.a EC) [kg/m3] + DAERSL(I,J,L,1) = BCPO(I,J,L) + + ! Hydrophobic OC [kg/m3] + DAERSL(I,J,L,2) = OCPO(I,J,L) + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE + + !----------------------------------- + ! Read from disk -- fullchem only + !----------------------------------- + IF ( DO_READ_DATA ) THEN + + ! Print filename + WRITE( 6, 115 ) TRIM( FILENAME ) + 115 FORMAT( ' - RDAER: Reading BC and OC from ', a ) + + !-------------------------------- + ! Read Hydrophobic BC + !-------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 2, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, DAERSL(:,:,:,1) ) + + !--------------------------------- + ! Read Hydrophilic BC + !--------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 3, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, WAERSL(:,:,:,2) ) + + !--------------------------------- + ! Read Hydrophobic OC + !--------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 4, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, DAERSL(:,:,:,2) ) + + !--------------------------------- + ! Read Hydrophilic OC + !--------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 5, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, WAERSL(:,:,:,3) ) + ENDIF + ENDIF + + !================================================================= + ! S E A S A L T A E R O S O L S + ! + ! If LSSALT = TRUE, then take accumulation and coarse mode + ! seasalt aerosol concentrations [kg/m3] that are passed from + ! "chemdr.f". Save these into WAERSL for use w/ FAST-J and + ! hetchem. These fields are updated every chemistry timestep. + ! (For both fullchem and offline simulations) + ! + ! If LSSALT = FALSE, then read monthly-mean coarse sea-salt + ! aerosol concentrations [kg/m3] from the binary punch file. + ! Also merge the coarse sea salt aerosols into a combined bin + ! rather than carrying them separately. + ! (For fullchem simulations only) + !================================================================= + IF ( LSSALT ) THEN + + !----------------------------------- + ! Use online aerosol concentrations + !----------------------------------- + IF ( FIRST ) THEN + WRITE( 6, 120 ) + 120 FORMAT( ' - RDAER: Using online SALA SALC' ) + ENDIF + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Accumulation mode seasalt aerosol [kg/m3] + WAERSL(I,J,L,4) = SALA(I,J,L) + + ! Coarse mode seasalt aerosol [kg/m3] + WAERSL(I,J,L,5) = SALC(I,J,L) + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE + + !----------------------------------- + ! Read from disk -- fullchem only + !----------------------------------- + IF ( DO_READ_DATA ) THEN + + ! Print filename + WRITE( 6, 125 ) TRIM( FILENAME ) + 125 FORMAT( ' - RDAER: Reading SEASALT from ', a ) + + !---------------------------------- + ! Offline -- read Sea Salt (accum) + !---------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 6, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, WAERSL(:,:,:,4) ) + + !---------------------------------- + ! Offline -- read Sea Salt (coarse) + !---------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 7, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, WAERSL(:,:,:,5) ) + + !---------------------------------- + ! Offline -- read Sea Salt (coarse) + !---------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 8, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, TEMP2 ) + + ! Accumulate into one size bin + WAERSL(:,:,:,5) = WAERSL(:,:,:,5) + TEMP2 + + !---------------------------------- + ! Offline -- read Sea Salt (coarse) + !---------------------------------- + CALL READ_BPCH2( FILENAME, 'ARSL-L=$', 9, + & XTAU, IGLOB, JGLOB, + & LGLOB, TEMP, QUIET=.TRUE. ) + + CALL TRANSFER_3D( TEMP, TEMP2 ) + + ! Accumulate into one size bin + WAERSL(:,:,:,5) = WAERSL(:,:,:,5) + TEMP2 + + ENDIF + ENDIF + + !================================================================= + ! Calculate optical depth and surface area at each timestep + ! to account for the change in relative humidity + ! + ! For the optical depth calculation, this involves carrying the + ! optical depth at each RH as separate aerosols since OPMIE.f + ! treats the phase functions and single scattering albedos + ! separately. (An alternative would be to rewrite OPMIE.f) + ! + ! Scaling is sufficient for the surface area calculation + !================================================================= + MSDENS(1) = 1700.0d0 !SO4 + MSDENS(2) = 1000.0d0 !BC + MSDENS(3) = 1800.0d0 !OC + MSDENS(4) = 2200.0d0 !SS (accum) + MSDENS(5) = 2200.0d0 !SS (coarse) + + ! Loop over types of aerosol + DO N = 1, NAER + + ! Zero array + SCALEOD(:,:,:,:) = 0d0 + + !============================================================== + ! Determine aerosol growth rates from the relative + ! humidity in each box + ! + ! The optical depth scales with the radius and Q alone + ! since SCALEDENS cancels as follows + ! + ! SCALER = RW / RDRY + ! SCALEDENS = DENSWET / DENSDRY + ! SCALEM = SCALEDENS * SCALER**3 + ! SCALEOD = (SCALEQ * SCALEM) / (SCALEDENS * SCALER) + ! = SCALEQ * SCALER**2 + ! + ! Cap aerosol values at 90% relative humidity since + ! aerosol growth at that point becomes highly nonlinear and + ! relative humidities above this value essentially mean + ! there is a cloud in that grid box + ! + ! Q is the extinction efficiency + ! + ! Each grid box (I,J,L) will fall into one of the RH bins, + ! since each grid box will have a different RH value. So, + ! for SCALEOD(I,J,L,:), only one of the IRH bins will contain + ! nonzero data, while the other IRH bins will all be zero. + !============================================================== + + ! Loop over relative humidity bins + DO R = 1, NRH + + ! Wet radius in "jv_spec.dat" + RW(R) = RAA(4,IND(N)+R-1) + + ! Wet frac of aerosol + ! FWET = (RW(R)**3 - RW(1)**3) / RW(R)**3 (lzhang 06/18/2012) + + ! Extinction efficiency Q for each RH bin + QW(R) = QAA(4,IND(N)+R-1) ! lzhang(06/18/2012) + ENDDO + + ! Loop over SMVGEAR grid boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, IRH, JLOOP, SCALEQ, SCALER, REFF, FRAC ) +!$OMP+SCHEDULE( DYNAMIC ) + DO JLOOP = 1, NTLOOP + + ! Get 3-D grid box indices + I = IXSAVE(JLOOP) + J = IYSAVE(JLOOP) + L = IZSAVE(JLOOP) + + ! Sort into relative humidity bins + IF ( ABSHUM(JLOOP) <= RH(2) ) THEN + IRH = 1 + ELSE IF ( ABSHUM(JLOOP) <= RH(3) ) THEN + IRH = 2 + ELSE IF ( ABSHUM(JLOOP) <= RH(4) ) THEN + IRH = 3 + ELSE IF ( ABSHUM(JLOOP) <= RH(5) ) THEN + IRH = 4 + ELSE + IRH = 5 + ENDIF + + ! For the NRHth bin, we don't have to interpolate + ! For the other bins, we have to interpolate + IF ( IRH == NRH ) THEN + SCALEQ = QW(NRH) / QW(1) !QW(1) is dry extinction eff. + REFF = RW(NRH) + + ELSE + + ! Interpolate between different RH + FRAC = (ABSHUM(JLOOP)-RH(IRH)) / (RH(IRH+1)-RH(IRH)) + IF ( FRAC > 1.0d0 ) FRAC = 1.0d0 + + SCALEQ = (FRAC*QW(IRH+1) + (1.d0-FRAC)*QW(IRH)) / QW(1) + REFF = FRAC*RW(IRH+1) + (1.d0-FRAC)*RW(IRH) + + ENDIF + + SCALER = REFF / RW(1) + SCALEOD(I,J,L,IRH) = SCALEQ * SCALER * SCALER + SCALEVOL(I,J,L) = SCALER**3 + ERADIUS(JLOOP,NDUST+N) = 1.0D-4 * REFF + + !============================================================== + ! ND21 Diagnostic: + ! + ! Computed here: + ! -------------- + ! #7 Hygroscopic growth of SO4 [unitless] + ! #10 Hygroscopic growth of Black Carbon [unitless] + ! #13 Hygroscopic growth of Organic Carbon [unitless] + ! #16 Hygroscopic growth of Sea Salt (accum) [unitless] + ! #19 Hygroscopic growth of Sea Salt (coarse) [unitless] + !============================================================== + IF ( ND21 > 0 .and. L <= LD21 ) THEN + AD21(I,J,L,4+3*N) = AD21(I,J,L,4+3*N) +SCALEOD(I,J,L,IRH) + ENDIF + + ENDDO +!$OMP END PARALLEL DO + + !============================================================== + ! Convert concentration [kg/m3] to optical depth [unitless]. + ! + ! ODAER = ( 0.75 * BXHEIGHT * AERSL * QAA ) / + ! ( MSDENS * RAA * 1e-6 ) + ! (see Tegen and Lacis, JGR, 1996, 19237-19244, eq. 1) + ! + ! Units ==> AERSL [ kg/m3 ] + ! MSDENS [ kg/m3 ] + ! RAA [ um ] + ! BXHEIGHT [ m ] + ! QAA [ unitless ] + ! ODAER [ unitless ] + ! + ! NOTES: + ! (1 ) Do the calculation at QAA(4,:) (i.e. 999 nm). + ! (2 ) RAA is the 'effective radius', Hansen and Travis, 1974 + ! (3 ) Report at the more relevant QAA(2,:) (i.e. 400 nm) + ! Although SCALEOD would be slightly different at 400nm + ! than at 1000nm as done here, FAST-J does currently + ! allow one to provide different input optical depths at + ! different wavelengths. Therefore the reported value at + ! determined with QAA(2,:) is as used in FAST-J. + ! (4 ) Now use explicit indices in parallel DO-loops, since + ! some compilers may not like array masks in parallel + ! regions (bmy, 2/28/02) + !============================================================== +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, R, IRHN ) +!$OMP+SCHEDULE( DYNAMIC ) + DO R = 1, NRH + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Bin for aerosol type and relative humidity + IRHN = ( (N-1) * NRH ) + R + + ! Save aerosol optical depth for each combination + ! of aerosol type and relative humidity into ODAER, + ! which will get passed to the FAST-J routines + ODAER(I,J,L,IRHN) = SCALEOD(I,J,L,R) + & * 0.75d0 * BXHEIGHT(I,J,L) + & * WAERSL(I,J,L,N) * QAA(4,IND(N)) / + & ( MSDENS(N) * RAA(4,IND(N)) * 1.0D-6 ) + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !============================================================== + ! Calculate Aerosol Surface Area + ! + ! Units ==> AERSL [ kg aerosol m^-3 air ] + ! MSDENS [ kg aerosol m^-3 aerosol ] + ! ERADIUS [ cm ] + ! TAREA [ cm^2 dry aerosol/cm^3 air ] + ! + ! Note: first find volume of aerosol (cm^3 arsl/cm^3 air), then + ! multiply by 3/radius to convert to surface area in cm^2 + ! + ! Wet Volume = AERSL * SCALER**3 / MSDENS + ! Wet Surface Area = 3 * (Wet Volume) / ERADIUS + ! + ! Effective radius for surface area and optical depths + ! are identical. + !============================================================== +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, JLOOP ) +!$OMP+SCHEDULE( DYNAMIC ) + DO JLOOP = 1, NTLOOP + + ! Get 3-D grid box indices + I = IXSAVE(JLOOP) + J = IYSAVE(JLOOP) + L = IZSAVE(JLOOP) + + !======================================================== + ! NOTES: + ! WAERSL [ kg dry mass of wet aerosol m^-3 air ] + ! ERADIUS [ cm wet aerosol radius ] + ! MSDENS [ kg dry mass of aerosol m^-3 dry volume of aerosol ] + ! TAREA [ cm^2 wet sfc area of aerosol cm^-3 air ] + ! WTAREA : same as TAREA, but excludes dry dust, BCPO and OCPO + ! use same units as TAREA (tmf, 4/18/07) + ! WERADIUS : same as ERADIUS, but excludes dry dust, BCPO and OCPO + ! use same units as ERADIUS (tmf, 4/18/07) + ! Wet dust WTAREA and WERADIUS are archived in dust_mod.f. + !======================================================== + + ! Store aerosol surface areas in TAREA, and be sure + ! to list them following the dust surface areas + TAREA(JLOOP,N+NDUST) = 3.D0 * + & WAERSL(I,J,L,N) * + & SCALEVOL(I,J,L) / + & ( ERADIUS(JLOOP,NDUST+N) * + & MSDENS(N) ) + + WTAREA(JLOOP, N) = TAREA(JLOOP, N+NDUST) + WERADIUS(JLOOP, N) = ERADIUS(JLOOP, N+NDUST) + + + ENDDO +!$OMP END PARALLEL DO + + ENDDO !Loop over NAER + + !============================================================== + ! Account for hydrophobic aerosols (BC and OC), N=2 and N=3 + !============================================================== + DO N = 2, 3 + + ! Index for combination of aerosol type and RH + IRHN = ( (N-1) * NRH ) + 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) +!$OMP+SCHEDULE( DYNAMIC ) + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Aerosol optical depth + ODAER(I,J,L,IRHN) = ODAER(I,J,L,IRHN) + + & 0.75d0 * BXHEIGHT(I,J,L) * + & DAERSL(I,J,L,N-1) * QAA(4,IND(N)) / + & ( MSDENS(N) * RAA(4,IND(N)) * 1.0D-6 ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Effective radius + REFF = 1.0D-4 * RAA(4,IND(N)) + + ! Loop over grid boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, JLOOP, DRYAREA ) +!$OMP+SCHEDULE( DYNAMIC ) + DO JLOOP = 1, NTLOOP + + ! Get 3-D grid box indices + I = IXSAVE(JLOOP) + J = IYSAVE(JLOOP) + L = IZSAVE(JLOOP) + + ! Dry surface area + DRYAREA = 3.D0 * DAERSL(I,J,L,N-1) / ( REFF * MSDENS(N) ) + + ! Add surface area to TAREA array + TAREA(JLOOP,N+NDUST) = TAREA(JLOOP,N+NDUST) + DRYAREA + + ! Define a new effective radius that accounts + ! for the hydrophobic aerosol + ERADIUS(JLOOP,NDUST+N) = ( ERADIUS(JLOOP,NDUST+N) * + & TAREA(JLOOP,N+NDUST) + + & REFF * DRYAREA) / + & ( TAREA(JLOOP,N+NDUST) + DRYAREA ) + + ENDDO +!$OMP END PARALLEL DO + + ENDDO + + !============================================================== + ! ND21 Diagnostic: Aerosol OD's, Growth Rates, Surface Areas + ! + ! Computed in other routines: + ! --------------------------------- + ! #1: Cloud optical depths (1000 nm) --> from "optdepth_mod.f" + ! #2: Max Overlap Cld Frac --> from "optdepth_mod.f" + ! #3: Random Overlap Cld Frac --> from "optdepth_mod.f" + ! #4: Dust optical depths --> from "rdust.f" + ! #5: Dust surface areas --> from "rdust.f" + ! + ! Computed previously in "rdaer.f": + ! --------------------------------- + ! #7 Hygroscopic growth of SO4 [unitless] + ! #10 Hygroscopic growth of Black Carbon [unitless] + ! #13 Hygroscopic growth of Organic Carbon [unitless] + ! #16 Hygroscopic growth of Sea Salt (accum) [unitless] + ! #19 Hygroscopic growth of Sea Salt (coarse) [unitless] + ! + ! Computed here: + ! --------------------------------- + ! #6 Sulfate Optical Depth (400 nm) [unitless] + ! #8 Sulfate Surface Area [cm2/cm3 ] + ! #9 Black Carbon Optical Depth (400 nm) [unitless] + ! #11 Black Carbon Surface Area [cm2/cm3 ] + ! #12 Organic Carbon Optical Depth (400 nm) [unitless] + ! #14 Organic Carbon Surface Area [cm2/cm3 ] + ! #15 Sea Salt (accum) Opt Depth (400 nm) [unitless] + ! #17 Sea Salt (accum) Surface Area [cm2/cm3 ] + ! #18 Sea Salt (coarse) Opt Depth(400 nm) [unitless] + ! #20 Sea Salt (coarse) Surface Area [cm2/cm3 ] + ! #21: Dust optical depths (0.15 um) --> from "rdust.f" + ! #22: Dust optical depths (0.25 um) --> from "rdust.f" + ! #23: Dust optical depths (0.4 um) --> from "rdust.f" + ! #24: Dust optical depths (0.8 um) --> from "rdust.f" + ! #25: Dust optical depths (1.5 um) --> from "rdust.f" + ! #26: Dust optical depths (2.5 um) --> from "rdust.f" + ! #27: Dust optical depths (4.0 um) --> from "rdust.f" + ! + ! NOTE: The cloud optical depths are actually recorded at + ! 1000 nm, but vary little with wavelength. + !============================================================== + IF ( ND21 > 0 ) THEN + + ! Loop over aerosol types (dust handled in dust_mod.f) +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, IRHN, J, JLOOP, L, N, R ) +!$OMP+SCHEDULE( DYNAMIC ) + DO N = 1, NAER + + !------------------------------------ + ! Aerosol Optical Depths [uhitless] + ! Scale of optical depths w/ RH + !------------------------------------ + DO R = 1, NRH + DO L = 1, LD21 + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Index for type of aerosol and RH value + IRHN = ( (N-1) * NRH ) + R + + ! Optical Depths (scaled to jv_spec_aod.dat wavelength, clh) + AD21(I,J,L,3+3*N) = AD21(I,J,L,3+3*N) + + & ODAER(I,J,L,IRHN) * + & QAA_AOD(IND(N)+R-1) / QAA(4,IND(N)+R-1) + + ENDDO + ENDDO + ENDDO + ENDDO + + !------------------------------------ + ! Aerosol Surface Areas [cm2/cm3] + !------------------------------------ + DO JLOOP = 1, NTLOOP + + ! Get 3-D grid box indices + I = IXSAVE(JLOOP) + J = IYSAVE(JLOOP) + L = IZSAVE(JLOOP) + + ! Add aerosol surface areas + IF ( L <= LD21 ) THEN + AD21(I,J,L,5+3*N) = AD21(I,J,L,5+3*N) + + & TAREA(JLOOP,N+NDUST) + ENDIF + ENDDO + + ENDDO +!$OMP END PARALLEL DO + + ENDIF + + !================================================================= + ! To turn off the radiative effects of different aerososl + ! uncomment the following lines + !================================================================= + !DO R = 1,NRH + ! ODAER(:,:,:,R) = 0.d0 !sulfate + ! ODAER(:,:,:,R+NRH) = 0.d0 !BC + ! ODAER(:,:,:,R+2*NRH) = 0.d0 !OC + ! ODAER(:,:,:,R+3*NRH) = 0.d0 !SS(accum) + ! ODAER(:,:,:,R+4*NRH) = 0.d0 !SS(coarse) + !ENDDO + + !================================================================= + ! To turn off heterogeneous chemistry on different aerosols + ! uncomment the following lines + !================================================================= + !TAREA(:,NDUST+1) = 0.d0 !Sulfate + !TAREA(:,NDUST+2) = 0.d0 !BC + !TAREA(:,NDUST+3) = 0.d0 !OC + !TAREA(:,NDUST+4) = 0.d0 !SS (accum) + !TAREA(:,NDUST+5) = 0.d0 !SS (coarse) + + ! Reset first-time flag + FIRST = .FALSE. + + ! Return to calling program + END SUBROUTINE RDAER + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_AEROSOL +! +!****************************************************************************** +! Subroutine INIT_AEROSOL allocates and zeroes module arrays (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_AEROSOL begins here! + !================================================================= + + ALLOCATE( BCPI( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BCPI' ) + BCPI = 0d0 + + ALLOCATE( BCPO( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BCPO' ) + BCPO = 0d0 + + ALLOCATE( OCPI( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OCPI' ) + OCPI = 0d0 + + ALLOCATE( OCPO( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OCPO' ) + OCPO = 0d0 + + ALLOCATE( SALA( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SALA' ) + SALA = 0d0 + + ALLOCATE( SALC( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SALC' ) + SALC = 0d0 + + ALLOCATE( SO4_NH4_NIT( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SO4_NH4_NIT' ) + SO4_NH4_NIT = 0d0 + + ALLOCATE( SOILDUST( IIPAR, JJPAR, LLPAR, NDUST ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SOILDUST' ) + SOILDUST = 0d0 + + ! Return to calling program + END SUBROUTINE INIT_AEROSOL + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_AEROSOL +! +!****************************************************************************** +! Subroutine CLEANUP_AEROSOL deallocates all module arrays (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_AEROSOL begins here! + !================================================================= + IF ( ALLOCATED( BCPI ) ) DEALLOCATE( BCPI ) + IF ( ALLOCATED( BCPO ) ) DEALLOCATE( BCPO ) + IF ( ALLOCATED( OCPI ) ) DEALLOCATE( OCPI ) + IF ( ALLOCATED( OCPO ) ) DEALLOCATE( OCPO ) + IF ( ALLOCATED( SALA ) ) DEALLOCATE( SALA ) + IF ( ALLOCATED( SALC ) ) DEALLOCATE( SALC ) + IF ( ALLOCATED( SO4_NH4_NIT ) ) DEALLOCATE( SO4_NH4_NIT ) + IF ( ALLOCATED( SOILDUST ) ) DEALLOCATE( SOILDUST ) + + ! Return to calling program + END SUBROUTINE CLEANUP_AEROSOL + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE AEROSOL_MOD diff --git a/code/aircraft_nox_mod.f b/code/aircraft_nox_mod.f new file mode 100644 index 0000000..ae28055 --- /dev/null +++ b/code/aircraft_nox_mod.f @@ -0,0 +1,463 @@ +! $Id: aircraft_nox_mod.f,v 1.1 2009/06/09 21:51:54 daven Exp $ + MODULE AIRCRAFT_NOX_MOD +! +!****************************************************************************** +! Module AIRCRAFT_NOX_MOD contains variables and routines for emission +! of aircraft NOx fields into arrays for SMVGEAR. (bmy, 2/15/02, 10/3/07) +! +! The aircraft NOx fields are stored on grid with 1-km vertical resolution. +! These fields will be interpolated onto the GEOS-CHEM vertical grid. +! +! Module Variables: +! ============================================================================ +! (1 ) NAIR (INTEGER) : Max number of layers of the 1-km native grid +! (2 ) LAIREMS (INTEGER) : Highest GEOS-CHEM level we will emit NOx into +! (3 ) AIR (REAL*8 ) : Array for NOx emissions on the 1-km grid +! (4 ) AIREMIS (REAL*8 ) : Array for NOx emissions on the GEOS-CHEM grid +! (5 ) AIRPRESS (REAL*8 ) : Approx. pressure edges of the 1-km native grid +! (6 ) EMIS_AC_NOx (REAL*8) : Array to pass aircraft NOx to SMVGEAR +! +! Module Routines: +! ============================================================================ +! (1 ) READAIR : Routine to read NOx emissions from disk +! (2 ) AIREMISS : Routine to emit aircraft NOx into GEOS-CHEM +! (3 ) INIT_AIRCRAFT_NOX : Routine to allocate/initialize module variables +! (4 ) CLEANUP_AIRCRAFT_NOX : Routine to deallocate module variables +! +! GEOS-CHEM modules referenced by biomass_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module containing routines for binary punch file I/O +! (2 ) diag_mod.f : Module containing GEOS-CHEM diagnostic arrays +! (3 ) error_mod.f : Module containing NaN and other error check routines +! (4 ) file_mod.f : Module containing file unit numbers and error checks +! (5 ) grid_mod.f : Module containing horizontal grid information +! (6 ) pressure_mod.f : Module containing routines to compute P(I,J,L) +! +! NOTES: +! (1 ) Routines READAIR and AIREMISS were originally written by Yuhang Wang, +! 1993. These have been bundled into "aircraft_nox_mod.f" for easier +! bookkeeping. They have been kept mostly as-is, save for some +! cosmetic changes and improved I/O error trapping. (bmy, 2/14/02) +! (2 ) Updated comments, deleted some obsolete code (bmy, 3/8/02) +! (3 ) Bug fix: only allocate arrays the first call to READAIR. +! (yxw, bmy, 4/2/02) +! (4 ) Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Updated comments. Also deleted obsolete +! code. (bmy, 5/28/02) +! (5 ) Now references "file_mod.f" (bmy, 6/26/02) +! (6 ) Now references "pressure_mod.f". Also deleted obsolete, commented-out +! code from 6/02. (bmy, 8/20/02) +! (7 ) Now references BXHEIGHT from "dao_mod.f". Now references "error_mod.f". +! Also deleted obsolete code from various routines (bmy, 10/15/02) +! (8 ) Now references "grid_mod.f" and "time_mod.f" (bmy, 2/11/03) +! (9 ) Now references "directory_mod.f" (bmy, 7/19/04) +! (10) Replace GEMISNOX (from CMN_NOX) with a module variable (bmy, 10/3/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "aircraft_nox_mod.f" + !================================================================= + + ! PRIVATE module variables + PRIVATE :: NAIR + PRIVATE :: LAIREMS + PRIVATE :: AIR + PRIVATE :: AIREMIS + PRIVATE :: AIRPRESS + + ! PRIVATE module routines + PRIVATE INIT_AIRCRAFT_NOX + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! NAIR - Maximum number (km) for aircraft NOx emissions + INTEGER, PARAMETER :: NAIR = 20 + + ! LAIREMS GEOS-CHEM level where we will put emissions into + INTEGER :: LAIREMS + + ! AIR aft NOx emissions on native 1-km grid + REAL*8, ALLOCATABLE :: AIR(:,:,:) + + ! Aircraft NOx emissions on GEOS-CHEM grid + REAL*8, ALLOCATABLE :: AIREMIS(:,:,:) + + ! AIRPRESS - Approx. pressure edges of the 1-km native aircraft NOx grid + REAL*8 :: AIRPRESS(NAIR+1) = (/ + & 1013.25, 954.61, 845.56, 746.83, 657.64, 577.28, 505.07, + & 440.35, 382.52, 330.99, 285.24, 244.75, 209.04, 178.65, + & 152.59, 130.34, 111.33, 95.09, 81.22, 69.37, 59.26 /) + + ! Array to pass aircraft NOx emissions to SMVGEAR + ! (replacement for GEMISNOX array) + REAL*8, ALLOCATABLE :: EMIS_AC_NOx(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE READAIR +! +!****************************************************************************** +! Subroutine READAIR reads the aircraft NOx emissions from disk. +! (yhw, bmy, 7/5/01, 2/11/03) +! +! NOTES: +! (1 ) Now reference DATA_DIR from include file "CMN_SETUP". Also reference +! routine GET_RES_EXT from BPCH2_MOD. (bmy, 7/5/01) +! (2 ) Now also use F90 syntax for declarations. Also use IOERROR to trap +! I/O errors. Use D exponent to force REAL*8 precision. Also updated +! comments. (bmy, 7/5/01) +! (3 ) Removed obsolete code from 7/01 (bmy, 9/4/01) +! (4 ) Now read aircraft NOx files from the aircraft_NOx_200202/ subdirectory +! of DATA_DIR. Also updated comments. (bmy, 1/24/02) +! (5 ) Now bundled into "aircraft_nox_mod.f" (bmy, 2/14/02) +! (6 ) Updated comments (bmy, 3/8/02) +! (7 ) Bug fix: only call INIT_AIRCRAFT_NOX to allocate arrays on the +! first call to READAIR (yxw, bmy, 4/2/02) +! (8 ) Deleted obsolete code (bmy, 5/28/02) +! (9 ) Now use IU_FILE instead of IUNIT as the file unit number. Also +! reference IU_FILE and IOERROR from "file_mod.f" (bmy, 6/26/02) +! (10) Deleted obsolete code from 6/02. (bmy, 8/20/02) +! (11) Now use function GET_MONTH from "time_mod.f". Renamed INIT to +! FIRST and MONTHSAVE to LASTMONTH. (bmy, 2/11/03) +! (12) Removed reference to "CMN", it's obsolete. Now references DATA_DIR +! from "directory_mod.f" (bmy, 7/19/04) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : IU_FILE, IOERROR + USE TIME_MOD, ONLY : GET_MONTH + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER, SAVE :: LASTMONTH = -99 + INTEGER :: I, J, K, IOS + REAL*8 :: FUEL + + ! Conversion factor from [kg NO2/4h] to [molec NO2/s] + REAL*8 :: CONV=9.0927d+20 + + ! Month array + CHARACTER(LEN=7) :: MONTHSTR(12) = (/ + & 'airjan.', 'airfeb.', 'airmar.', 'airapr.', + & 'airmay.', 'airjun.', 'airjul.', 'airaug.', + & 'airsep.', 'airoct.', 'airnov.', 'airdec.'/) + + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READAIR begins here! + ! + ! NOTE: Aircraft NOx emissions have been stored in the input + ! files in units of [kg NO2/4h] instead of the more logical + ! [kg NO2/day]. This is primarily historical. Yuhang Wang + ! did it this way since the old GISS-II model had a timestep of + ! 4 hours. These routines were then ported into the GEOS-CHEM + ! as-is, thus leaving the units in [kg NO2/4h]. However, the + ! emissions are converted below into [molec NO2/s], by applying + ! the conversion factor CONV, and are then passed to SMVGEAR. + ! (bmy, 3/8/02) + !================================================================= + IF ( FIRST .or. GET_MONTH() /= LASTMONTH ) THEN + + ! Allocate and initialize arrays + IF ( FIRST ) THEN + CALL INIT_AIRCRAFT_NOX + FIRST = .FALSE. + ENDIF + + ! Save month in LASTMONTH + LASTMONTH = GET_MONTH() + + ! Zero emissions + AIR(:,:,:) = 0d0 + + ! Construct filename + FILENAME = TRIM( DATA_DIR ) // 'aircraft_NOx_200202/' // + & MONTHSTR( GET_MONTH() ) // GET_RES_EXT() + + ! Open file + OPEN( IU_FILE, FILE=TRIM( FILENAME ), STATUS='OLD', IOSTAT=IOS) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'readair:1' ) + + ! Read aircraft NOx + DO + +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +!%%% KLUDGE FOR NORTH AMERICAN NESTED GRID (bmy, 7/2/12) +!%%% For some reason there seems to be bad data within the N. American +!%%% nested grid data files. Some of the longitude indices are out of bounds +!%%% for the grid. Put in a simple kludge to just skip over these boxes. +!%%% We are going to be reinventing how emissions get done in GEOS-Chem, +!%%% so it's probably not worth recreating the the file at this time. +!%%% +!%%% READ( IU_FILE, *, IOSTAT=IOS ) I, J, K, AIR(I,J,K) +!%%% +!%%% ! IOS < 0 is end of file +!%%% ! IOS > 0 is an I/O error +!%%% IF ( IOS < 0 ) EXIT +!%%% IF ( IOS > 0 ) CALL IOERROR( IOS, IU_FILE, 'readair:2' ) + + ! Now read emissions into a scalar + READ( IU_FILE, *, IOSTAT=IOS ) I, J, K, FUEL + + ! IOS < 0 is end of file + ! IOS > 0 is an I/O error + IF ( IOS < 0 ) EXIT + IF ( IOS > 0 ) CALL IOERROR( IOS, IU_FILE, 'readair:2' ) + +#if defined( NESTED_NA ) + ! Error check, cycle if out of bounds + IF ( I > IIPAR ) CYCLE + IF ( J > JJPAR ) CYCLE +#endif + + ! Save emissions into the AIR array + AIR(I,J,K) = FUEL +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + ENDDO + + ! Close file + CLOSE( IU_FILE ) + + ! Convert the units from [kg NO2/4hr] -> [molecules/s] + DO K = 1, NAIR + DO J = 1, JGLOB + DO I = 1, IGLOB + IF ( AIR(I,J,K) > 0.0 ) AIR(I,J,K) = AIR(I,J,K) * CONV + ENDDO + ENDDO + ENDDO + ENDIF + + ! Return to calling program + END SUBROUTINE READAIR + +!------------------------------------------------------------------------------ + + SUBROUTINE AIREMISS +! +!****************************************************************************** +! Subroutine AIREMISS interpolates the aircraft NOx emissions from the 1-km +! native grid onto the given GEOS-CHEM grid. (bmy, 2/14/02, 10/3/07) +! +! Original code from Yuhang Wang (1993). +! +! NOTES: +! (1 ) Now bundled into "aircraft_nox_mod.f" (bmy, 2/14/02) +! (2 ) Replace P(IOFF,JOFF) with P(I,J), since P is now declared to be +! of size (IIPAR,JJPAR) instead of (IGLOB,JGLOB) (bmy, 2/14/02) +! (3 ) AIR has to be dimensioned (IGLOB,JGLOB,LGLOB), since it contains +! global emissions. AIREMIS can be declared (IIPAR,JJPAR,LAIREMS), +! since that way it will have the same horizontal dimensions as +! the GEMISNOX array. (bmy, 2/14/02) +! (4 ) Removed obsolete code (bmy, 3/8/02) +! (5 ) Now reference GET_PEDGE from "pressure_mod.f", which returns the +! correct "floating" pressure (bmy, 8/20/02) +! (6 ) Now reference BXHEIGHT from "dao_mod.f". (bmy, 9/18/02) +! (7 ) I0 and J0 are now local variables. Now use functions GET_XOFFSET +! and GET_YOFFSET from "grid_mod.f" (bmy, 2/11/03) +! (8 ) Replace GEMISNOX (from "CMN_NOX") with module variable EMIS_AC_NOx +! in order to avoid common block errors. (ltm, bmy, 10/3/07) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : BXHEIGHT + USE DIAG_MOD, ONLY : AD32_ac + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE PRESSURE_MOD, ONLY : GET_PEDGE + +# include "CMN_SIZE" ! Size parameters +# include "CMN" ! PTOP, SIGE, AVP +# include "CMN_DIAG" ! Diagnostic switches + + INTEGER :: I, J, IREF, JREF, L, K + INTEGER :: I0, J0 + REAL*8 :: PLOW, PHIGH, XSUM, PAIR1, PAIR2, TMP + + ! External functions + REAL*8, EXTERNAL :: BOXVL + + !================================================================= + ! AIREMISS begins here! + !================================================================= + + ! Read aircraft NOx emissions + CALL READAIR + + ! Zero accumulator array + EMIS_AC_NOx = 0d0 + + ! Get nested-grid offsets + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + + ! Loop over surface grid boxes + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + + !============================================================== + ! Loop over tropospheric GEOS-CHEM levels + !============================================================== + DO L = 1, LAIREMS + + ! PLOW is the pressure at the bottom edge of sigma level L + ! PHIGH is the pressure at the top edge of sigma level L + PLOW = GET_PEDGE(I,J,L) + PHIGH = GET_PEDGE(I,J,L+1) + + ! Make sure PLOW is not smaller than AIRPRESS(1) + IF ( L == 1 .AND. PLOW < AIRPRESS(1) ) PLOW = AIRPRESS(1) + + ! Initialize the summing variable + XSUM = 0.0 + + !=========================================================== + ! Loop over the native 1-km aircraft NOx grid layers + !=========================================================== + DO K = 1, NAIR + + ! PAIR1 is the pressure at the bottom of 1-km grid layer K + ! PAIR2 is the pressure at the top of 1-km grid layer K + PAIR1 = AIRPRESS(K) + PAIR2 = AIRPRESS(K+1) + + ! Compute the fraction of each 1-km layer K that + ! lies within the given GEOS-CHEM layer L + IF ( PHIGH >= PAIR1 ) THEN + GOTO 10 + + ELSE IF ( PLOW < PAIR1 .AND. PLOW > PAIR2 ) THEN + IF ( PHIGH < PAIR2 ) THEN + XSUM = XSUM + + & AIR(IREF,JREF,K) * (PLOW-PAIR2) / (PAIR1-PAIR2) + ELSE + XSUM = XSUM + + & AIR(IREF,JREF,K) * (PLOW-PHIGH) / (PAIR1-PAIR2) + ENDIF + + ELSE IF ( PHIGH < PAIR1 .AND. + & PHIGH > PAIR2 .AND. + * PLOW >= PAIR1) THEN + XSUM = XSUM + + & AIR(IREF,JREF,K) * (PAIR1-PHIGH) / (PAIR1-PAIR2) + + ELSE IF ( PHIGH <= PAIR2 .AND. PLOW >= PAIR1 ) THEN + XSUM = XSUM + AIR(IREF,JREF,K) + + ENDIF + ENDDO + + ! Store XSUM into AIREMIS array + 10 CONTINUE + + + AIREMIS(I,J,L) = XSUM + + !=========================================================== + ! Store nonzero AIREMIS into GEMISNOX array, + ! which will then be passed into SMVGEAR + !=========================================================== + IF ( AIREMIS(I,J,L) > 0.0 ) THEN + + ! Convert from [molec/s] to [molec/cm3/s] + TMP = AIREMIS(I,J,L) / BOXVL(I,J,L) + + ! Store in GEMISNOX in [molec/cm3/s] + EMIS_AC_NOx(I,J,L) = TMP + + ! ND32 -- save NOx in [molec/cm2], will convert to + ! [molec/cm2/s] in subroutine "diag3.f" (bmy, 3/16/00) + IF ( ND32 > 0 ) THEN + AD32_ac(I,J,L) = AD32_ac(I,J,L) + + & ( TMP * BXHEIGHT(I,J,L) * 1d2 ) + ENDIF + ENDIF + + ENDDO ! L + ENDDO ! I + ENDDO ! J + + ! Return to calling program + END SUBROUTINE AIREMISS + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_AIRCRAFT_NOX +! +!****************************************************************************** +! Subroutine INIT_AIRCRAFT_NOX allocates and initializes module variables. +! (bmy, 2/14/02, 10/3/07) +! +! NOTES: +! (1 ) Now references ALLOC_ERR from "error_mod.f" (bmy, 10/15/02) +! (2 ) Now allocate EMIS_AC_NOx array (bmy, 10/3/07) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" + + ! Local variables + INTEGER :: AS + + ! LAIREMS is only defined up to the GEOS-CHEM tropopause + LAIREMS = LLTROP + + ! AIR holds the aircraft NOx on the native 1-km grid (NAIR levels) + ALLOCATE( AIR( IGLOB, JGLOB, NAIR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AIR' ) + AIR = 0d0 + + ! AIREMIS holds the aircraft NOx on the GEOS grid (LAIREMS levels) + ALLOCATE( AIREMIS( IIPAR, JJPAR, LAIREMS ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AIREMS' ) + AIREMIS = 0d0 + + ! AIREMIS holds the aircraft NOx on the GEOS grid (LAIREMS levels) + ALLOCATE( EMIS_AC_NOx( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AIREMS' ) + EMIS_AC_NOx = 0d0 + + ! Return to calling program + END SUBROUTINE INIT_AIRCRAFT_NOX + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_AIRCRAFT_NOX +! +!****************************************************************************** +! Subroutine CLEANUP_AIRCRAFT_NOX deallocates module variables. (bmy, 2/14/02) +! +! NOTES: +! (1 ) Now deallocate EMIS_AC_NOx array (bmy, 10/3/07) +!****************************************************************************** +! + IF ( ALLOCATED( AIR ) ) DEALLOCATE( AIR ) + IF ( ALLOCATED( AIREMIS ) ) DEALLOCATE( AIREMIS ) + IF ( ALLOCATED( EMIS_AC_NOX ) ) DEALLOCATE( EMIS_AC_NOX ) + + ! Return to calling program + END SUBROUTINE CLEANUP_AIRCRAFT_NOX + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE AIRCRAFT_NOX_MOD diff --git a/code/airmas.f b/code/airmas.f new file mode 100644 index 0000000..58ffa45 --- /dev/null +++ b/code/airmas.f @@ -0,0 +1,35 @@ +! $Id: airmas.f,v 1.1 2009/06/09 21:51:51 daven Exp $ + FUNCTION AIRMAS( G, H ) +! +!****************************************************************************** +! Function AIRMAS corrects the optical path through the layer for the +! curvature of the earth. This correction is very small and according to +! RJS fairly laborious to derive --- Do it someday. Neglecting this +! correction, AIRMAS = 1/GMU. (lwh, jyl, gmg, djj, 1990's; bmy, 4/4/03) +! +! Arguments as Input: +! ============================================================================ +! (1 ) G (REAL*8) : Cosine of solar zenith angle [unitless] +! (2 ) H (REAL*8) : Scale height of atmosphere [m] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes (bmy, 4/4/03) +!****************************************************************************** +! + IMPLICIT NONE + + ! Arguments + REAL*8, INTENT(IN) :: G, H + + ! Function value + REAL*8 :: AIRMAS + + !================================================================= + ! AIRMAS begins here! + !================================================================= + AIRMAS = (1.0D0+H)/SQRT(G*G + 2.0D0*H*(1.0D0 - + & 0.6817D0*EXP(-57.3D0*ABS(G)/SQRT(1.0D0+5500.D0*H))/ + & (1.0D0+0.625D0*H))) + + ! Return to calling program + END FUNCTION AIRMAS diff --git a/code/anthroems.f b/code/anthroems.f new file mode 100644 index 0000000..f1a47b8 --- /dev/null +++ b/code/anthroems.f @@ -0,0 +1,693 @@ +! $Id: anthroems.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + SUBROUTINE ANTHROEMS( NSEASON ) +! +!****************************************************************************** +! Subroutine ANTHROEMS reads anthropogenic tracers for each season. +! NOx emissions at levels other than the surface are now accounted for. +! (bmy, 6/4/98, 7/18/06) +! +! Arguments as input: +! =========================================================================== +! (1) NSEASON: is the seasonal index for NOx emissions: +! NSEASON=1 --> winter (Dec, Jan, Feb) +! NSEASON=2 --> spring (Mar, Apr, May) +! NSEASON=3 --> summer (Jun, Jul, Aug) +! NSEASON=4 --> autumn (Sep, Oct, Nov) +! +! (2) LNAPAPNOX: logical flag to overwrite US emissions with NAPAP NOx +! +! Passed Via CMN: +! =========================================================================== +! (1) JYEAR: 4 digit integer variable for current year (1985, 1998, etc.) +! +! Passed Via CMN_O3: +! =========================================================================== +! Fossil Fuel arrays: EMISTNOX, EMISTCO, EMISTETHE, EMISTPRPE, +! EMISTC2H6, EMISTC3H8, EMISTALK4, EMISTACET, +! EMISTMEK, EMISTSOX +! +! Emissions arrays: EMIST, EMISTN, EMISR, EMISRN, EMISRR, EMISRRN +! +! NOTES: +! (1 ) We now read the new merge file, created for SASS. (bey, 2/99) +! (2 ) ANTHROEMS should be called each time the season changes, since +! the GEIA NOx emissions are seasonal. +! (3 ) NOx emissions are stored separately in EMISTN, EMISRN, EMISRRN. +! This is because the NOx emissions can be located across several +! sigma levels, whereas the other tracers are only emitted into +! the surface level. +! (4 ) NO2 is no longer emitted as the emission species for Ox. +! (bey, bmy, 4/14/99) +! (5 ) There are 3 different types of scale factors for anthro emissions: +! (a) Yearly since 1985: done in anthroems.f +! (b) Weekday/weekend: done in emf_scale.f +! (c) Time of day: done in emfossil.f +! (6 ) At present NEMANTHRO = Total number of emitted tracers +! (set in tracerid.f). We no longer use moments in emissions. +! ORDER = NOx, CO, PRPE, C3H8, ALK4, C2H6, ALD2. +! (7 ) NOx is assumed to be the first tracer (N=1). The first usable +! row for tracers other than NOx in EMIST(I,J,N), etc. is N=2. +! (8 ) Need to offset EMISR, which has global dimensions. +! EMIST has window dimensions. +! (9 ) Now trap I/O errors and stop gracefully if file open or read +! errors are encountered. Print an error message to alert user +! which file triggered the I/O error. (bmy, 4/14/99) +! (10) Eliminate GISS-specific code and PLUMES code (bmy, 4/14/99) +! (11) Now use F90 syntax where expedient. (bmy, 4/14/99) +! (12) Cosmetic changes, added comments (bmy, 3/17/00) +! (13) Do not let SCALYEAR go higher than 1996, since right now we don't +! have FF scaling data beyond 1996. Also cosmetic changes and +! updated comments. (bmy, 4/6/01) +! (14) Now reference routines from GEIA_MOD for reading scale factor and +! other emissions data from disk. (bmy, 4/23/01) +! (15) Now read fossil-fuel emissions from a binary punch file (bmy, 4/23/01) +! (16) CO and hydrocarbons are read from disk once per year. Fossil fuel +! scale factors are also applied once per +! (17) Now comment out LNAPAPNOX. Also total fossil fuel emissions +! and echo to std output. (bmy, 4/27/01) +! (18) Bug fix: Now convert units for CO, Hydrocarbon tracers only once +! per year. Convert units for NOx once per season. (bmy, 6/7/01) +! (19) Bug fix: Now index CH26 correctly when totaling it (bmy, 8/30/01) +! (20) Now take C3H8 and C2H6 emissions as scaled from natural gas. Read +! these in subroutine READ_C3H8_C2H6_NGAS. Also scale anthropogenic +! ACET by 0.82 in order to match the acetone paper (bdf, bmy, 9/10/01) +! (21) Removed obsolete, commented-out code from 6/01 (bmy, 11/26/01) +! (22) Eliminated obsolete code from 11/01 (bmy, 2/27/02) +! (23) Replaced all instances of IM with IIPAR and JM with JJPAR, in order +! to prevent namespace confusion for the new TPCORE (bmy, 6/25/02) +! (24) Now reference IDTNOX, IDENOX, etc. from "tracerid_mod.f". Also +! do not let SCALEYEAR exceed 1998. (bmy, 1/13/03) +! (25) Now replace DXYP(JREF)*1d4 with routine GET_AREA_CM2 from "grid_mod.f" +! Now use functions GET_XOFFSET and GET_YOFFSET from "grid_mod.f". +! Now I0 and J0 are local variables. Now use functions GET_TS_EMIS, +! GET_YEAR, GET_SEASON from "time_mod.f". (bmy, 2/11/03) +! (26) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (27) Now replace FMOL with TRACER_MW_KG (bmy, 10/25/05) +! (28) Modified for IPCC future emissions scale factors (swu, bmy, 5/30/06) +! (29) Extend max value for FSCALYR to 2002 (bmy, 7/18/06) +! (30) Use updated int'annual scale factors for 1985-2003 (amv, 08/24/07) +! (31) As default, use EDGARv2.0 emission (fossil fuel + industry) +! for year 1985, scale to target year with CO2 from liquid fuel, +! for aromatics, C2H4, and C2H2. (tmf, 6/13/07) +!****************************************************************************** +! + ! References to F90 modules + USE FUTURE_EMISSIONS_MOD,ONLY : GET_FUTURE_SCALE_ALK4ff + USE FUTURE_EMISSIONS_MOD,ONLY : GET_FUTURE_SCALE_C2H6ff + USE FUTURE_EMISSIONS_MOD,ONLY : GET_FUTURE_SCALE_C3H8ff + USE FUTURE_EMISSIONS_MOD,ONLY : GET_FUTURE_SCALE_COff + USE FUTURE_EMISSIONS_MOD,ONLY : GET_FUTURE_SCALE_NOxff + USE FUTURE_EMISSIONS_MOD,ONLY : GET_FUTURE_SCALE_PRPEff + USE FUTURE_EMISSIONS_MOD,ONLY : GET_FUTURE_SCALE_TONEff + USE GEIA_MOD, ONLY : READ_GEIA, READ_C3H8_C2H6_NGAS + USE GEIA_MOD, ONLY : READ_LIQCO2, READ_TODX + USE GEIA_MOD, ONLY : READ_TOTCO2, TOTAL_FOSSIL_TG + USE GRID_MOD, ONLY : GET_AREA_CM2, GET_XOFFSET + USE GRID_MOD, ONLY : GET_YOFFSET + USE LOGICAL_MOD, ONLY : LFUTURE + USE TIME_MOD, ONLY : GET_TS_EMIS, GET_YEAR + USE TIME_MOD, ONLY : GET_SEASON + USE TRACER_MOD, ONLY : TRACER_MW_KG + USE TRACERID_MOD, ONLY : IDEACET, IDEALK4 + USE TRACERID_MOD, ONLY : IDEC2H6, IDEC3H8 + USE TRACERID_MOD, ONLY : IDECO, IDEMEK + USE TRACERID_MOD, ONLY : IDENOX, IDEPRPE + USE TRACERID_MOD, ONLY : NEMANTHRO + USE TRACERID_MOD, ONLY : IDEBENZ, IDETOLU, IDEXYLE + USE TRACERID_MOD, ONLY : IDEC2H4, IDEC2H2 + USE TRACERID_MOD, ONLY : IDTBENZ, IDTTOLU, IDTXYLE + USE TRACERID_MOD, ONLY : IDTC2H4, IDTC2H2 + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_05x0666_NESTED_CH + USE EDGAR_MOD, ONLY : READ_AROMATICS, READ_C2H4 + USE EDGAR_MOD, ONLY : READ_C2H2 + USE EDGAR_MOD, ONLY : READ_AROMATICS_05x0666 + USE EDGAR_MOD, ONLY : READ_C2H4_05x0666 + USE EDGAR_MOD, ONLY : READ_C2H2_05x0666 + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_O3" ! EMIST, EMISR, EMISRR, etc. +# include "comode.h" ! IDEMS + + ! Arguments + INTEGER, INTENT(IN) :: NSEASON + + ! Local Variables + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: SCALEYEAR + INTEGER, SAVE :: LASTYEAR + INTEGER :: I, I0, IREF, J, J0, JREF + INTEGER :: K, L, LL, N, NN + REAL*8 :: DTSRCE, AREA_CM2 + + REAL*4 :: E_BENZ(IGLOB,JGLOB), E_TOLU(IGLOB,JGLOB), + & E_XYLE(IGLOB,JGLOB) + REAL*4 :: E_C2H4(IGLOB,JGLOB), E_C2H2(IGLOB,JGLOB) + REAL*8 :: GEOS1x1(I1x1,J1x1,1) + REAL*8 :: TEMP(IGLOB,JGLOB) + + + !================================================================= + ! ANTHROEMS begins here! + !================================================================= + + ! Echo info + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a)' ) 'A N T H R O P O G E N I C E M I S S I O N S' + WRITE( 6, '(a)' ) + WRITE( 6, 110 ) GET_YEAR(), GET_SEASON() + 110 FORMAT( 'ANTHROEMS: NYEAR, NSEASON = ', i4, 1x, i2 ) + + ! Emission timestep [s] + DTSRCE = GET_TS_EMIS() * 60d0 + + ! Get nested-grid offsets + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + + ! As of March 2009, the GEIA input files for GEOS_5, 0.5X0.666, + ! NESTED_CHINA are already cropped to the nested grid domain. + ! So there is no need for offsetting the emission data. + ! Reset I0 = 0, J0 = 0. (tmf, 3/5/09) +#if defined( GRID05x0666 ) && defined( NESTED_CH ) + + I0 = 0 + J0 = 0 + +#endif + !================================================================= + ! If FSCALYR < 0 then use this year (JYEAR) for the scaling + ! factors. Otherwise, use the value of FSCALYR as specified in + ! 'input.ctm'. + ! + ! Do not let SCALEYEAR exceed 1998 for now, since this is the + ! latest year for which we have data from CDIAC. (bmy, 1/13/03) + ! + ! Do not limit default SCALEYEAR - this is done in + ! GET_ANNUAL_SCALAR. Allow users to force the scaling year + ! as before with a value GT 0 in input.geos (phs, 3/11/08) + !================================================================= +!------------------ +! prior to 3/11/08 +! IF ( FSCALYR < 0 ) THEN +! SCALEYEAR = MIN( GET_YEAR(), 2002 ) +! ELSE +! SCALEYEAR = FSCALYR +! ENDIF +!------------------ + IF ( FSCALYR < 0 ) THEN + SCALEYEAR = GET_YEAR() + ELSE + SCALEYEAR = FSCALYR + ENDIF + + + + !================================================================= + ! Do the following only on the very first call to ANTHROEMS... + !================================================================= + IF ( FIRST ) THEN + + ! Zero emission arrays + EMISTNOX = 0e0 + EMISTCO = 0e0 + EMISTALK4 = 0e0 + EMISTACET = 0e0 + EMISTMEK = 0e0 + EMISTPRPE = 0e0 + EMISTC3H8 = 0e0 + EMISTC2H6 = 0e0 + EMISTETHE = 0e0 + EMISTSOX = 0e0 + EMISTBENZ = 0e0 + EMISTTOLU = 0e0 + EMISTXYLE = 0e0 + EMISTC2H4 = 0e0 + EMISTC2H2 = 0e0 + + ! Zero arrays for holding CO & Hydrocarbons + EMIST = 0d0 + EMISR = 0d0 + + ! Read time-of-day scale factors (TODN, TODH, TODB) + ! and weekday-weekend scale factors (SCNR89) + CALL READ_TODX( TODN, TODH, TODB, SCNR89 ) + + ! Read emissions from binary punch file format for entire year: + ! NOx [molec NOx/cm2/s], CO [molec CO/cm2/s], HC's [atoms C/cm2/s] + ! NOTE: We don't read in ETHE or SOx for our chemistry mechanism. + CALL READ_GEIA( E_NOX = EMISTNOX, E_CO = EMISTCO, + & E_ALK4 = EMISTALK4, E_ACET = EMISTACET, + & E_MEK = EMISTMEK, E_PRPE = EMISTPRPE ) + + ! Read C3H8 and C2H6 emissions, scaled from Natural Gas emissions + ! as computed by Yaping Xiao (xyp@io.harvard.edu) + CALL READ_C3H8_C2H6_NGAS( E_C3H8=EMISTC3H8, E_C2H6=EMISTC2H6 ) + + !================================================================ + ! Read EDGARv2 aromatics emission for 1985 (tmf, 7/30/08) + !================================================================ + IF ( IDTBENZ /= 0 .AND. IDTTOLU /= 0 .AND. IDTXYLE /= 0 ) THEN +#if defined(GRID05x0666) && defined( NESTED_CH ) + CALL READ_AROMATICS_05x0666( E_BENZ, E_TOLU, E_XYLE ) +#else + CALL READ_AROMATICS( E_BENZ, E_TOLU, E_XYLE ) +#endif + + EMISTBENZ = E_BENZ + EMISTTOLU = E_TOLU + EMISTXYLE = E_XYLE + ENDIF + !================================================================ + ! Read EDGARv2 C2H4 emission for 1985 (tmf, 7/30/08) + !================================================================ + IF ( IDTC2H4 /= 0 ) THEN +#if defined(GRID05x0666) && defined( NESTED_CH ) + CALL READ_C2H4_05x0666( E_C2H4 ) +#else + CALL READ_C2H4( E_C2H4 ) +#endif + + EMISTC2H4 = E_C2H4 + ENDIF + !================================================================ + ! Read EDGARv2 C2H2 emission for 1985 (tmf, 7/30/08) + !================================================================ + IF ( IDTC2H2 /= 0 ) THEN +#if defined(GRID05x0666) && defined( NESTED_CH ) + CALL READ_C2H2_05x0666( E_C2H2 ) +#else + CALL READ_C2H2( E_C2H2 ) +#endif + + EMISTC2H2 = E_C2H2 + ENDIF + !============================================================== + ! Apply IPCC future scale factors to emissions (if necessary) + !============================================================== + IF ( LFUTURE ) THEN + + ! Loop over grid boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Future CO [molec/cm2/s] + EMISTCO(I,J) = EMISTCO(I,J) * + & GET_FUTURE_SCALE_COff( I, J ) + + ! Future C2H6 [atoms C/cm2/s] + EMISTC2H6(I,J) = EMISTC2H6(I,J) * + & GET_FUTURE_SCALE_C2H6ff( I, J ) + + ! Future C3H8 emissions [atoms C/cm2/s] + EMISTC3H8(I,J) = EMISTC3H8(I,J) * + & GET_FUTURE_SCALE_C3H8ff( I, J ) + + ! Future ALK4 [atoms C/cm2/s] + EMISTALK4(I,J) = EMISTALK4(I,J) * + & GET_FUTURE_SCALE_ALK4ff( I, J ) + + ! Future PRPE [atoms C/cm2/s] + EMISTPRPE(I,J) = EMISTPRPE(I,J) * + & GET_FUTURE_SCALE_PRPEff( I, J ) + + ! Future ACET [atoms C/cm2/s] + EMISTACET(I,J) = EMISTACET(I,J) * + & GET_FUTURE_SCALE_TONEff( I, J ) + + ! Future MEK [atoms C/cm2/s] + EMISTMEK(I,J) = EMISTMEK(I,J) * + & GET_FUTURE_SCALE_TONEff( I, J ) + + ! Future NOx [molec/cm2/s] + EMISTNOX(I,J,:,:) = EMISTNOX(I,J,:,:) * + & GET_FUTURE_SCALE_NOxff( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + ENDIF + + !================================================================= + ! Do the following on the first call to ANTHROEMS, + ! or whenever we enter into a new year: + !================================================================= + IF ( FIRST .or. SCALEYEAR /= LASTYEAR ) THEN + + WRITE( 6, * ) +!------------------ +! prior to 3/11/08 +! ! Read in scale factors based on total fuel CO2 +! ! (relative to baseline year 1985) -- used for NOx +! CALL READ_TOTCO2( SCALEYEAR, FTOTCO2 ) +! +! ! Read in scale factors based on liquid fuel CO2 +! ! (relative to baseline year 1985) -- used for CO, HC's +! CALL READ_LIQCO2( SCALEYEAR, FLIQCO2 ) +!----------------- + ! now use updated scalars (amv, phs, 3/11/08) + CALL GET_ANNUAL_SCALAR( 71, 1985, SCALEYEAR, FTOTCO2 ) + CALL GET_ANNUAL_SCALAR( 72, 1985, SCALEYEAR, FLIQCO2 ) + + ! Set SCALEYEAR to this YEAR + LASTYEAR = SCALEYEAR + + !============================================================== + ! Apply scale factors to CO and Hydrocarbon emission species + ! These are aseasonal, so we only have to do this the first + ! time that anthroems.f is called. + ! + ! EMIST(I,J,N) contains CO and hydrocarbon emission species + ! in units of [molec (C)/cm2/s] + ! + ! NOTE: We always assume NOx is the first tracer (N=1), so the + ! first valid entry in EMIST(I,J,N) will be the N=2 row. + !============================================================== + + ! CO: Scale by liquid CO2 scale factors + IF ( IDECO /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDECO) = EMISTCO(IREF,JREF) * + & FLIQCO2(IREF,JREF) + ENDDO + ENDDO + + ! Print total in Tg CO + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDECO), IIPAR, JJPAR, + & 1, 28d-3, 'CO' ) + ENDIF + + ! ALK4: scale by liquid fuel CO scale factors + IF ( IDEALK4 /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEALK4) = EMISTALK4(IREF,JREF) * + & FLIQCO2(IREF,JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEALK4), IIPAR, JJPAR, + & 1, 12d-3, 'ALK4' ) + ENDIF + + ! ACET: scale by liquid fuel CO scale factors + IF ( IDEACET /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + + ! Also multiply by 0.82 in order to match the + ! a posteriori acetone source (bdf, bmy, 9/5/01) + EMIST(I,J,IDEACET) = EMISTACET(IREF,JREF) * + & FLIQCO2(IREF,JREF) * 0.82d0 + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEACET), IIPAR, JJPAR, + & 1, 12d-3, 'ACET' ) + ENDIF + + ! MEK: scale by liquid fuel CO scale factors + IF ( IDEMEK /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEMEK) = EMISTMEK(IREF,JREF) * + & FLIQCO2(IREF,JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEMEK), IIPAR, JJPAR, + & 1, 12d-3, 'MEK' ) + ENDIF + + ! PRPE: Scale by liquid CO2 scale factors + IF ( IDEPRPE /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEPRPE) = EMISTPRPE(IREF,JREF) * + & FLIQCO2(IREF,JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEPRPE), IIPAR, JJPAR, + & 1, 12d-3, 'PRPE' ) + ENDIF + + ! C3H8: scale by liquid fuel CO scale factors + IF ( IDEC3H8 /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEC3H8) = EMISTC3H8(IREF,JREF) * + & FLIQCO2(IREF,JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEC3H8), IIPAR, JJPAR, + & 1, 12d-3, 'C3H8' ) + ENDIF + + ! C2H6: scale by liquid fuel CO scale factors + IF ( IDEC2H6 /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEC2H6) = EMISTC2H6(IREF,JREF) * + & FLIQCO2(IREF,JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEC2H6), IIPAR, JJPAR, + & 1, 12d-3, 'C2H6' ) + ENDIF + + !============================================================= + ! Default emissions for BENZ, TOLU, XYLE, C2H2, C2H4 + ! are for year 1985 only. Scale to target year + !============================================================= + ! BENZ: for year 1985 + IF ( IDEBENZ /= 0 .AND. IDTBENZ /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEBENZ) = EMISTBENZ(IREF,JREF) * + & FLIQCO2(IREF, JREF) +! & FLIQCO2(IREF, JREF) / FLIQCO290(IREF, JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEBENZ), IIPAR, JJPAR, + & 1, 12d-3, 'BENZ' ) + ENDIF + + ! TOLU: for year 1985 + IF ( IDETOLU /= 0 .AND. IDTTOLU /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDETOLU) = EMISTTOLU(IREF,JREF) * + & FLIQCO2(IREF, JREF) +! & FLIQCO2(IREF, JREF) / FLIQCO290(IREF, JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDETOLU), IIPAR, JJPAR, + & 1, 12d-3, 'TOLU' ) + ENDIF + + ! XYLE: for year 1985 + IF ( IDEXYLE /= 0 .AND. IDTXYLE /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEXYLE) = EMISTXYLE(IREF,JREF) * + & FLIQCO2(IREF, JREF) +! & FLIQCO2(IREF, JREF) / FLIQCO290(IREF, JREF) + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEXYLE), IIPAR, JJPAR, + & 1, 12d-3, 'XYLE' ) + ENDIF + + ! C2H4: for year 1985 + IF ( IDEC2H4 /= 0 .AND. IDTC2H4 /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEC2H4) = EMISTC2H4(IREF,JREF) * + & FLIQCO2(IREF, JREF) +! & FLIQCO2(IREF, JREF) / FLIQCO290(IREF, JREF) + + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEC2H4), IIPAR, JJPAR, + & 1, 12d-3, 'C2H4' ) + ENDIF + + ! C2H2: for year 1985 + IF ( IDEC2H2 /= 0 .AND. IDTC2H2 /= 0 ) THEN + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,IDEC2H2) = EMISTC2H2(IREF,JREF) * + & FLIQCO2(IREF, JREF) +! & FLIQCO2(IREF, JREF) / FLIQCO290(IREF, JREF) + + ENDDO + ENDDO + + ! Print total in Tg C + CALL TOTAL_FOSSIL_TG( EMIST(:,:,IDEC2H2), IIPAR, JJPAR, + & 1, 12d-3, 'C2H2' ) + ENDIF + + !============================================================== + ! Convert CO and hydrocarbon emissions from [molec (C)/cm2/s] + ! to [kg (C)/box/emission timestep]. Store in array EMISR. + !============================================================== + + ! Loop over the anthropogenic tracers + DO N = 1, NEMANTHRO + + ! NN is the actual CTM tracer # + ! corresponding to emissions species N + NN = IDEMS(N) + + ! Skip NOx + IF ( N == IDENOX ) CYCLE + + ! Skip if some tracer is not present because there are more + ! anthro. tracers for dicarbonyl chemistry. (ccc, 4/16/09) + IF ( NN == 0 ) CYCLE + + ! Convert units + DO J = 1, JJPAR + JREF = J + J0 + + ! Grid box surface area [cm2] + AREA_CM2 = GET_AREA_CM2( J ) + + DO I = 1, IIPAR + IREF = I + I0 + EMIST(I,J,N) = EMIST(I,J,N) * TRACER_MW_KG(NN) * + & DTSRCE * AREA_CM2 / 6.023d23 + + EMISR(IREF,JREF,N) = EMIST(I,J,N) + ENDDO + ENDDO + ENDDO + + ENDIF ! FIRST or SCALEYEAR /= LASTYEAR + + !============================================================== + ! Apply total fuel CO2 scale factors to NOx emissions + ! This has to be done once per season (4x/year); + ! that is, every time that ANTHROEMS is called. + !============================================================== + + ! Zero NOx emission arrays + EMISTN = 0d0 + EMISRN = 0d0 + + ! NOX: scale by total CO2 scale factors + IF ( IDENOX > 0 ) THEN + DO LL = 1, 2 !fp to accomodate NEI08 + DO J = 1, JJPAR + JREF = J + J0 + DO I = 1, IIPAR + IREF = I + I0 + EMISTN(I,J,LL) = EMISTNOX(IREF,JREF,NSEASON,LL) * + & FTOTCO2(IREF,JREF) + ENDDO + ENDDO + ENDDO + + ! Print total in Tg N + CALL TOTAL_FOSSIL_TG( EMISTN, IIPAR, JJPAR, + & NOXLEVELS, 14d-3, 'NOx', NSEASON ) + ENDIF + + !================================================================= + ! Convert all emission species from [molec (C)/cm2/s] to + ! [kg/box/emission timestep] and store in EMISRN, EMISR arrays. + !================================================================= + + ! Loop over the anthropogenic tracers + DO N = 1, NEMANTHRO + + ! NN is the actual CTM tracer # + ! corresponding to emissions species N + NN = IDEMS(N) + + ! Do unit conversion for NOx separately, since it is multi-level + IF ( N == IDENOX ) THEN + DO LL = 1, NOXLEVELS + DO J = 1, JJPAR + JREF = J + J0 + + ! Grid box surface area [cm2] + AREA_CM2 = GET_AREA_CM2( J ) + + DO I = 1, IIPAR + IREF = I + I0 + + EMISTN(I,J,LL) = EMISTN(I,J,LL) *TRACER_MW_KG(NN) * + & DTSRCE * AREA_CM2 / 6.023d23 + + EMISRN(IREF,JREF,LL) = EMISTN(I,J,LL) + ENDDO + ENDDO + ENDDO + + ! Exit from the loop over anthropogenic tracers + EXIT + ENDIF + ENDDO + + !================================================================ + ! Cleanup and quit + !================================================================ + + ! Set first-time-flag FALSE for next iteration + FIRST = .FALSE. + + ! Pretty output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! Return to calling program + END SUBROUTINE ANTHROEMS + diff --git a/code/arctas_ship_emiss_mod.f b/code/arctas_ship_emiss_mod.f new file mode 100644 index 0000000..504bce3 --- /dev/null +++ b/code/arctas_ship_emiss_mod.f @@ -0,0 +1,549 @@ +! $Id: arctas_ship_emiss_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: ARCTAS_SHIP_EMISS_MOD +! +! !DESCRIPTION: Module ARCTAS\_SHIP\_EMISS\_MOD contains variables and +! routines to read the Arctas Ship emissions. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + MODULE ARCTAS_SHIP_EMISS_MOD +! +! !USES: +! + IMPLICIT NONE + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: CLEANUP_ARCTAS_SHIP + PUBLIC :: EMISS_ARCTAS_SHIP + PUBLIC :: GET_ARCTAS_SHIP +! +! !PRIVATE MEMBER FUNCTIONS: +! + PRIVATE :: INIT_ARCTAS_SHIP + PRIVATE :: READ_ARCTAS_SHIP + PRIVATE :: TOTAL_EMISS_TG +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +! +! !REMARKS: +! (1) This inventory is based on EDGAR 2000 for NOx, CO, and +! SO2. But SO2 has been updated by David Street for 2006. BC and OC +! (from Bond et al, 2004) are also provided. They are a 1996 +! inventory scaled to 2006. All these emissions were prepared for +! the ARCTAS 2008 campaign. +! (2) Only SO2 differs from existing EDGAR/BOND inventories. All other +! species are disregarded for now, except CO2 that we did not have +! before. +!EOP +!------------------------------------------------------------------------------ +! +! !PRIVATE DATA MEMBERS: +! + ! Arrays + REAL*8, ALLOCATABLE :: A_CM2(:) + + ! Anthro emiss arrays + REAL*8, TARGET, ALLOCATABLE :: SO2_SHIP(:,:) + REAL*8, TARGET, ALLOCATABLE :: CO2_SHIP(:,:) +! +! !DEFINED PARAMETERS: +! + REAL*8, PARAMETER :: SEC_IN_YEAR = 86400d0 * 365.25d0 + + CONTAINS + +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: GET_ARCTAS_SHIP +! +! !DESCRIPTION: Function GET\_ARCTAS\_SHIP returns the ARCTAS\_SHIP emission +! for GEOS-Chem grid box (I,J) and tracer N. Emissions can be returned in +! units of [kg/s] or [molec/cm2/s]. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_ARCTAS_SHIP( I, J, N, MOLEC_CM2_S, KG_S ) + & RESULT( VALUE ) +! +! !USES: +! + USE TRACER_MOD, ONLY : ITS_A_CO2_SIM + USE TRACER_MOD, ONLY : XNUMOL + USE TRACERID_MOD, ONLY : IDTSO2 +! +! !INPUT PARAMETERS: +! + ! Longitude, latitude, and tracer indices + INTEGER, INTENT(IN) :: I, J, N + + ! OPTIONAL -- return emissions in [molec/cm2/s] + LOGICAL, INTENT(IN), OPTIONAL :: MOLEC_CM2_S + + ! OPTIONAL -- return emissions in [kg/s] + LOGICAL, INTENT(IN), OPTIONAL :: KG_S +! +! !RETURN VALUE: +! + ! Emissions output + REAL*8 :: VALUE +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL :: DO_KGS, DO_MCS + + !================================================================= + ! GET_ARCTAS_SHIP begins here! + !================================================================= + + ! Initialize + DO_KGS = .FALSE. + DO_MCS = .FALSE. + + ! Return data in [kg/s] or [molec/cm2/s]? + IF ( PRESENT( KG_S ) ) DO_KGS = KG_S + IF ( PRESENT( MOLEC_CM2_S ) ) DO_MCS = MOLEC_CM2_S + + ! Test for simulation type + IF ( ITS_A_CO2_SIM() ) THEN + + !------------------- + ! CO2 simulation + !------------------- + VALUE = CO2_SHIP(I,J) + + ELSE + + !------------------- + ! Other simulations + !------------------- + IF ( N == IDTSO2 ) THEN + + ! SO2 [kg/yr] + VALUE = SO2_SHIP(I,J) + + ELSE + + ! Otherwise return a negative value to indicate + ! that there are no ARCTAS_SHIP emissions for tracer N + VALUE = -1d0 + RETURN + + ENDIF + + ENDIF + + !------------------------------ + ! Convert units (if necessary) + !------------------------------ + IF ( DO_KGS ) THEN + + ! Convert from [kg/yr] to [kg/s] + VALUE = VALUE / SEC_IN_YEAR + + ELSE IF ( DO_MCS ) THEN + + ! Convert from [kg/yr] to [molec/cm2/s] + VALUE = VALUE * XNUMOL(N) / ( A_CM2(J) * SEC_IN_YEAR ) + + ENDIF + + ! Return to calling program + END FUNCTION GET_ARCTAS_SHIP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: EMISS_ARCTAS_SHIP +! +! !DESCRIPTION: Subroutine EMISS\_ARCTAS\_SHIP reads the ARCTAS\_SHIP emissions +! from disk. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_ARCTAS_SHIP( YEAR ) +! +! !USES: +! + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE TRACER_MOD, ONLY : ITS_A_CO2_SIM + +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: YEAR ! Year of data to read +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL, SAVE :: FIRST = .TRUE. + CHARACTER(LEN=255) :: FILENAME, DIR + + !================================================================= + ! EMISS_ARCTAS_SHIP begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_ARCTAS_SHIP + FIRST = .FALSE. + ENDIF + + 100 FORMAT( ' - EMISS_ARCTAS_SHIP: Reading ', a ) + + ! Data directory + DIR = TRIM( DATA_DIR_1x1 ) // 'ARCTAS_SHIP_2008/' + + + IF ( ITS_A_CO2_SIM() ) THEN + + !-------------------------- + ! Read CO2 and regrid + !-------------------------- + FILENAME = TRIM( DIR ) // 'Arctas_CO2_ship_2008.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read data + CALL READ_ARCTAS_SHIP( FILENAME, 'CO2-SRCE', 1, CO2_SHIP, + $ YEAR ) + + ELSE + + !-------------------------- + ! Read SO2 + !-------------------------- + FILENAME = TRIM( DIR ) // 'Arctas_SO2_ship_2008.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read data + CALL READ_ARCTAS_SHIP( FILENAME, 'ANTHSRCE', 26, SO2_SHIP, + $ YEAR ) + + + ENDIF + + !-------------------------- + ! Print emission totals + !-------------------------- + CALL TOTAL_EMISS_Tg + + ! Return to calling program + END SUBROUTINE EMISS_ARCTAS_SHIP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: READ_ARCTAS_SHIP +! +! !DESCRIPTION: Subroutine READ\_ARCTAS\_SHIP reads data from one ARCTAS\_SHIP +! data file from disk, at GENERIC 1x1 resolution and regrids them to the +! current model resolution. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_ARCTAS_SHIP( FILENAME, CATEGORY, + & TRACERN, ARR, YEAR ) + +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1, DO_REGRID_G2G_1x1 + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_1x1 + +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + ! Year of data to read + INTEGER, INTENT(IN) :: YEAR + + ! Tracer number + INTEGER, INTENT(IN) :: TRACERN + + ! Filename & category under which data is stored in bpch file + CHARACTER(LEN=*), INTENT(IN) :: FILENAME, CATEGORY +! +! !INPUT/OUTPUT PARAMETERS: +! + ! Array containing output data + REAL*8, INTENT(INOUT) :: ARR(IIPAR,JJPAR) +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +! +! !REMARKS: +! (1) Even though the inventory was prepared for Arctas 2008 campaign, CO2 +! base year is 2000, and SO2 base year is 2006. Input YEAR is used to +! scale SO2 into 1985-2004! +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(I1x1,J1x1-1,1) + REAL*8 :: GEN_1x1(I1x1,J1x1-1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + REAL*8 :: SC_1x1(I1x1,J1x1) + REAL*8 :: TAU2008 + + ! TAU0 values for 2008 + TAU2008 = GET_TAU0( 1, 1, 2008 ) + + ! Initialize + SC_1x1 = 1d0 + + ! Read data + CALL READ_BPCH2( FILENAME, CATEGORY, TRACERN, + & TAU2008, I1x1, J1x1-1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 before regridding + GEN_1x1(:,:) = ARRAY(:,:,1) + + ! Regrid from GENERIC 1x1 --> GEOS 1x1 + CALL DO_REGRID_G2G_1x1( 'kg/yr', GEN_1x1, GEOS_1x1(:,:,1) ) + + + ! Get & apply scaling factor to GEOS 1x1 + IF ( TRACERN == 26 ) + $ CALL GET_ANNUAL_SCALAR_1x1( 73, 2000, YEAR, SC_1x1 ) + + GEOS_1x1(:,:,1) = GEOS_1x1(:,:,1) * SC_1x1(:,:) + + + ! Regrid from GEOS 1x1 --> current model resolution + CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, ARR ) + + END SUBROUTINE READ_ARCTAS_SHIP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: TOTAL_EMISS_TG +! +! !DESCRIPTION: Subroutine TOTAL\_EMISS\_TG prints the totals for the +! anthropogenic or biomass emissions. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE TOTAL_EMISS_TG +! +! !USES: +! + USE TRACER_MOD, ONLY : ITS_A_CO2_SIM + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*8 :: T_SO2, T_CO2 + + !================================================================= + ! TOTAL_EMISS_TG begins here! + !================================================================= + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 100 ) + 100 FORMAT( 'E D G A R S H I P E M I S S I O N S', / ) + + + ! Test for simulation type + IF ( ITS_A_CO2_SIM() ) THEN + + !----------------------- + ! CO2 simulation + !----------------------- + + ! Total CO2 [Tg CO2] + T_CO2 = SUM( CO2_SHIP ) * 1d-9 + + ! Print totals + WRITE( 6, 110 ) 'CO2 ', 2008, T_CO2, ' CO2' + + ELSE + + !----------------------- + ! Other simulations + !----------------------- + + ! Total SO2 [Tg S] + T_SO2 = SUM( SO2_SHIP ) * 1d-9 * ( 32d0 / 64d0 ) + + ! Print totals in [Tg] + WRITE( 6, 110 ) 'SO2 ', 2008, T_SO2, '[Tg S ]' + + ENDIF + + ! Format statement + 110 FORMAT( 'ARCTAS SHIP ', a5, + & 'for base year ', i4, ': ', f11.4, 1x, a8 ) + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! Return to calling program + END SUBROUTINE TOTAL_EMISS_Tg +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: INIT_ARCTAS_SHIP +! +! !DESCRIPTION: Subroutine INIT\_ARCTAS\_SHIP allocates and zeroes all module +! arrays. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE INIT_ARCTAS_SHIP +! +! !USES: +! + USE ERROR_MOD, ONLY : ALLOC_ERR + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE LOGICAL_MOD, ONLY : LARCSHIP + USE TRACER_MOD, ONLY : ITS_A_CO2_SIM + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: AS, J + + !================================================================= + ! INIT_ARCTAS_SHIP begins here! + !================================================================= + + ! Allocate ANTHRO arrays if LARCTAS_SHIP is TRUE + IF ( LARCSHIP ) THEN + + !-------------------------------------------------- + ! Allocate and zero arrays for SHIP emissions + !-------------------------------------------------- + ! Test for simulation type + IF ( ITS_A_CO2_SIM() ) THEN + + !----------------------- + ! CO2 simulation + !----------------------- + ALLOCATE( CO2_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'CO2_SHIP' ) + CO2_SHIP = 0d0 + + ELSE + + !----------------------- + ! Other simulations + !----------------------- + ALLOCATE( SO2_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SO2_SHIP' ) + SO2_SHIP = 0d0 + + ENDIF + + !--------------------------------------------------- + ! Allocate array for grid box surface area in cm2 + !--------------------------------------------------- + ALLOCATE( A_CM2( JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'A_CM2' ) + + ! Fill array + DO J = 1, JJPAR + A_CM2(J) = GET_AREA_CM2( J ) + ENDDO + + ENDIF + + + ! Return to calling program + END SUBROUTINE INIT_ARCTAS_SHIP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: CLEANUP_ARCTAS_SHIP +! +! !DESCRIPTION: Subroutine CLEANUP\_ARCTAS\_SHIP deallocates all module +! arrays. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE CLEANUP_ARCTAS_SHIP +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! CLEANUP_ARCTAS_SHIP begins here! + !================================================================= + IF ( ALLOCATED( A_CM2 ) ) DEALLOCATE( A_CM2 ) + IF ( ALLOCATED( SO2_SHIP ) ) DEALLOCATE( SO2_SHIP ) + IF ( ALLOCATED( CO2_SHIP ) ) DEALLOCATE( CO2_SHIP ) + + ! Return to calling program + END SUBROUTINE CLEANUP_ARCTAS_SHIP + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE ARCTAS_SHIP_EMISS_MOD +!EOC diff --git a/code/arsl1k.f b/code/arsl1k.f new file mode 100644 index 0000000..50580eb --- /dev/null +++ b/code/arsl1k.f @@ -0,0 +1,94 @@ +! $Id: arsl1k.f,v 1.2 2010/03/09 15:03:46 daven Exp $ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !ROUTINE: arsl1k +! +! !DESCRIPTION: Function ARSL1K calculates the 1st-order loss rate of species +! on wet aerosol surface. +!\\ +!\\ +! !INTERFACE: +! + REAL*8 FUNCTION ARSL1K( AREA, RADIUS, DENAIR, STKCF, STK, SQM ) +! +! !USES: +! + IMPLICIT NONE +! +! !INPUT PARAMETERS: +! + ! Surface area of wet aerosols/volume of air [cm2/cm3] + REAL*8, INTENT(IN) :: AREA + + ! Radius of wet aerosol [cm], order of 0.01-10 um; + ! Note that radius here is Rd, not Ro + REAL*8, INTENT(IN) :: RADIUS + + ! Density of air [#/cm3] + REAL*8, INTENT(IN) :: DENAIR + + ! Sticking coefficient [unitless], order of 0.1 + REAL*8, INTENT(IN) :: STKCF + + ! Square root of temperature [K] + REAL*8, INTENT(IN) :: STK + + ! Square root of molecular weight [g/mole] + REAL*8, INTENT(IN) :: SQM +! +! !REMARKS: +! The 1st-order loss rate on wet aerosol (Dentener's Thesis, p. 14) +! is computed as: +! . +! ARSL1K [1/s] = area / [ radius/dfkg + 4./(stkcf * xmms) ] +! . +! where XMMS = Mean molecular speed [cm/s] = sqrt(8R*TK/pi/M) for Maxwell +! DFKG = Gas phase diffusion coeff [cm2/s] (order of 0.1) + +! !REVISION HISTORY: +! 01 Jul 1994 - lwh, jyl, gmg, djj - Initial version +! 04 Apr 2003 - R. Yantosca - Updated comments, cosmetic changes +! 07 Apr 2004 - R. Yantosca - Now return w/ default value if RADIUS is zero +! (i.e. is smaller than a very small number) +! 03 Dec 2009 - R. Yantosca - Prevent div-by-zero errors by returning the +! default value if any of the args are zero +! 03 Dec 2009 - R. Yantosca - Added ProTeX Header +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*8 :: DFKG + + !================================================================= + ! ARSL1K begins here! + !================================================================= + !---------------------------------------------------------------------- + ! Prior to 12/3/09: + ! Also check other values to avoid div-by-zero errors (bmy, 12/3/09) + !IF ( AREA < 0d0 .or. RADIUS < 1d-30 ) THEN + !---------------------------------------------------------------------- + IF ( AREA < 0d0 .or. DENAIR < 1d-30 .or. RADIUS < 1d-30 .or. + & SQM < 1d-30 .or. STK < 1d-30 .or. STKCF < 1d-30 ) THEN + + ! Use default value if any of the above values are zero + ! This will prevent div-by-zero errors in the eqns below + ARSL1K = 1.D-3 + + ELSE + + ! DFKG = Gas phase diffusion coeff [cm2/s] (order of 0.1) + DFKG = 9.45D17/DENAIR * STK * SQRT(3.472D-2 + 1.D0/(SQM*SQM)) + + ! Compute ARSL1K according to the formula listed above + ARSL1K = AREA / ( RADIUS/DFKG + 2.749064E-4*SQM/(STKCF*STK) ) + + ENDIF + + ! Return to calling program + END FUNCTION ARSL1K +!EOC diff --git a/code/backsub.f b/code/backsub.f new file mode 100644 index 0000000..c317a70 --- /dev/null +++ b/code/backsub.f @@ -0,0 +1,314 @@ +! $Id: backsub.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + SUBROUTINE BACKSUB +! +!****************************************************************************** +! Subroutine BACKSUB does the back-substitution on the decomposed matrix. +! (M. Jacobson 1997; bdf, bmy, 4/1/03, 7/9/03) +! +! NOTES: +! (1 ) Comment out counter variable NUM_BACKSUB, you can get the same info +! w/ a profiling run. (bmy, 7/9/03) +!****************************************************************************** +! + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "comode.h" ! SMVGEAR II arrays + + ! Local variables + INTEGER IJ,I,KZT,KL5,KH5,KL4,KH4,KL3,KH3,KL2,KH2,KL1,KH1,KC + INTEGER J0,IJ0,IJ1,IJ2,IJ3,IJ4,J1,J2,J3,J4,K,MZT,ML5,MH5,ML4,MH4 + INTEGER ML3,MH3,ML2,MH2,ML1,MH1,MC +C +C ********************************************************************* +C ************ WRITTEN BY MARK JACOBSON (1993) ************ +C *** (C) COPYRIGHT, 1993 BY MARK Z. JACOBSON *** +C *** U.S. COPYRIGHT OFFICE REGISTRATION NO. TXu 670-279 *** +C *** (650) 723-6836 *** +C ********************************************************************* +C +C BBBBBBB A CCCCCCC K K SSSSSSS U U BBBBBBB +C B B A A C K K S U U B B +C BBBBBBB A A C K K SSSSSSS U U BBBBBBB +C B B AAAAAAA C K K S U U B B +C BBBBBBB A A CCCCCCC K K SSSSSSS UUUUUUUU BBBBBBB +C +C ********************************************************************* +C ******* PERFORM BACK-SUBSTITUTIONS ON THE DECOMPOSED MATRIX ******* +C ********************************************************************* + +C ********************************************************************* +C * THIS SUBROUTINE SOLVES THE LINEAR SET OF EQUATIONS Ax = B FOR x, * +C * THE CORRECTION VECTOR, WHERE "A" IS THE L-U DECOMPOSTION OF THE * +C * ORIGINAL MATRIX, * +C * * +C * P = I - H x Bo x J, * +C * * +C * I = IDENTITY MATRIX, H = TIME-STEP, Bo = A COEFFICIENT THAT * +C * DEPENDS ON THE ORDER OF THE INTEGRATION METHOD, AND J IS THE * +C * MATRIX OF PARTIAL DERIVATIVES. B IS SENT FROM SMVGEAR AS A * +C * CORRECTED VALUE OF THE FIRST DERIVATIVES OF THE ORDINARY DIFFER- * +C * ENTIAL EQUATIONS. SUBROUTINE DECOMP.F SOLVED FOR "A", THE * +C * DECOMPOSED MATRIX. SEE PRESS ET AL. (1992) NUMERICAL RECIPES. * +C * CAMBRIDGE UNIVERSITY PRESS, FOR A BETTER DESCRIPTION OF THE BACK- * +C * SUBSTITUTION PROCESS. * +C * * +C * THIS BACK-SUBSTITUTION PROCESS USES SPARSE-MATRIX TECHNIQUES, * +C * VECTORIZES AROUND THE GRID-CELL DIMENSION, AND USES NO PARTIAL * +C * PIVOTING. TESTS BY SHERMAN & HINDMARSH (1980) LAWRENCE LIVERMORE * +C * REP. UCRL-84102 AND BY US HAVE CONFIRMED THAT THE REMOVAL OF * +C * PARTIAL PIVOTING HAS LITTLE EFFECT ON RESULTS. * +C * * +C * HOW TO CALL SUBROUTINE: * +C * ---------------------- * +C * CALL BACKSUB.F FROM SMVGEAR.F WITH * +C * NCS = 1..NCSGAS FOR GAS CHEMISTRY * +C * NCSP = NCS FOR DAYTIME GAS CHEM * +C * NCSP = NCS +ICS FOR NIGHTTIME GAS CHEM * +C ********************************************************************* +C +C ********************************************************************* +C * BACKSUB LOOP # 1 * +C * FIRST, ADJUST RIGHT SIDE OF Ax = B USING LOWER TRIANGULAR MATRIX * +C ********************************************************************* +C SUM 1,2,3,4, OR 5 TERMS AT A TIME TO IMPROVE VECTORIZATION. +C +C KTLOOP = NUMBER OF GRID-CELLS IN A GRID-BLOCK +C ISCHAN = ORDER OF MATRIX +C CC2 = ARRAY HOLDING VALUES OF DECOMPOSED MATRIX. +C GLOSS = ARRAY INITIALLY HOLDING RIGHT SIDE OF EQUATION. THESE +C VALUES ARE CONVERTED TO THE SOLUTION DURING BACK-SUBSTITUTION. +C KZEROA,..= ARRAYS IDENTIFYING TERMS IN GLOSS ARRAY +C + IJ = 1 + DO 310 KZT = KZTLO(NCSP), KZTHI(NCSP) + I = IKZTOT(KZT) + KL5 = KBL5( KZT) + KH5 = KBH5( KZT) + KL4 = KBL4( KZT) + KH4 = KBH4( KZT) + KL3 = KBL3( KZT) + KH3 = KBH3( KZT) + KL2 = KBL2( KZT) + KH2 = KBH2( KZT) + KL1 = KBL1( KZT) + KH1 = KBH1( KZT) +C +C *********************** SUM 5 TERMS AT A TIME ********************* +C + DO 105 KC = KL5, KH5 + IJ0 = IJ + IJ1 = IJ + 1 + IJ2 = IJ + 2 + IJ3 = IJ + 3 + IJ4 = IJ + 4 + IJ = IJ + 5 + J0 = KZEROA(KC) + J1 = KZEROB(KC) + J2 = KZEROC(KC) + J3 = KZEROD(KC) + J4 = KZEROE(KC) + DO 100 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 3 - CC2(K,IJ2) * GLOSS(K,J2) + 4 - CC2(K,IJ3) * GLOSS(K,J3) + 5 - CC2(K,IJ4) * GLOSS(K,J4) + 100 CONTINUE + 105 CONTINUE +C +C *********************** SUM 4 TERMS AT A TIME ********************* +C + DO 155 KC = KL4, KH4 + IJ0 = IJ + IJ1 = IJ + 1 + IJ2 = IJ + 2 + IJ3 = IJ + 3 + IJ = IJ + 4 + J0 = KZEROA(KC) + J1 = KZEROB(KC) + J2 = KZEROC(KC) + J3 = KZEROD(KC) + DO 150 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 3 - CC2(K,IJ2) * GLOSS(K,J2) + 4 - CC2(K,IJ3) * GLOSS(K,J3) + 150 CONTINUE + 155 CONTINUE +C +C *********************** SUM 3 TERMS AT A TIME ********************* +C + DO 205 KC = KL3, KH3 + IJ0 = IJ + IJ1 = IJ + 1 + IJ2 = IJ + 2 + IJ = IJ + 3 + J0 = KZEROA(KC) + J1 = KZEROB(KC) + J2 = KZEROC(KC) + DO 200 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 3 - CC2(K,IJ2) * GLOSS(K,J2) + 200 CONTINUE + 205 CONTINUE +C +C *********************** SUM 2 TERMS AT A TIME ********************* +C + DO 255 KC = KL2, KH2 + IJ0 = IJ + IJ1 = IJ + 1 + IJ = IJ + 2 + J0 = KZEROA(KC) + J1 = KZEROB(KC) + DO 250 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 250 CONTINUE + 255 CONTINUE +C +C *********************** SUM 1 TERM AT A TIME ********************** +C + DO 305 KC = KL1, KH1 + IJ0 = IJ + IJ = IJ + 1 + J0 = KZEROA(KC) + DO 300 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 300 CONTINUE + 305 CONTINUE + 310 CONTINUE +C +C ********************************************************************* +C * BACKSUB LOOP # 2 * +C * BACKSUBSTITE WITH UPPER TRIANGULAR MATRIX TO FIND SOLUTION * +C ********************************************************************* +C AGAIN, SUM UP SEVERAL TERMS AT A TIME TO IMPROVE VECTORIZATION. +C VDIAG = DIAGONAL TERM FROM L-U DECOMPOSTION. +C GLOSS = SOLUTION ON OUTPUT +C + DO 710 I = ISCHAN, 1, -1 + MZT = IMZTOT(I,NCSP) + IF (MZT.GT.0) THEN + ML5 = MBL5( MZT) + MH5 = MBH5( MZT) + ML4 = MBL4( MZT) + MH4 = MBH4( MZT) + ML3 = MBL3( MZT) + MH3 = MBH3( MZT) + ML2 = MBL2( MZT) + MH2 = MBH2( MZT) + ML1 = MBL1( MZT) + MH1 = MBH1( MZT) +C +C *********************** SUM 5 TERMS AT A TIME ********************* +C + DO 405 MC = ML5, MH5 + IJ0 = IJ + IJ1 = IJ + 1 + IJ2 = IJ + 2 + IJ3 = IJ + 3 + IJ4 = IJ + 4 + IJ = IJ + 5 + J0 = MZEROA(MC) + J1 = MZEROB(MC) + J2 = MZEROC(MC) + J3 = MZEROD(MC) + J4 = MZEROE(MC) + DO 400 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 3 - CC2(K,IJ2) * GLOSS(K,J2) + 4 - CC2(K,IJ3) * GLOSS(K,J3) + 5 - CC2(K,IJ4) * GLOSS(K,J4) + 400 CONTINUE + 405 CONTINUE +C +C *********************** SUM 4 TERMS AT A TIME ********************* +C + DO 455 MC = ML4, MH4 + IJ0 = IJ + IJ1 = IJ + 1 + IJ2 = IJ + 2 + IJ3 = IJ + 3 + IJ = IJ + 4 + J0 = MZEROA(MC) + J1 = MZEROB(MC) + J2 = MZEROC(MC) + J3 = MZEROD(MC) + DO 450 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 3 - CC2(K,IJ2) * GLOSS(K,J2) + 4 - CC2(K,IJ3) * GLOSS(K,J3) + 450 CONTINUE + 455 CONTINUE +C +C *********************** SUM 3 TERMS AT A TIME ********************* +C + DO 505 MC = ML3, MH3 + IJ0 = IJ + IJ1 = IJ + 1 + IJ2 = IJ + 2 + IJ = IJ + 3 + J0 = MZEROA(MC) + J1 = MZEROB(MC) + J2 = MZEROC(MC) + DO 500 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 3 - CC2(K,IJ2) * GLOSS(K,J2) + 500 CONTINUE + 505 CONTINUE +C +C *********************** SUM 2 TERMS AT A TIME ********************* +C + DO 555 MC = ML2, MH2 + IJ0 = IJ + IJ1 = IJ + 1 + IJ = IJ + 2 + J0 = MZEROA(MC) + J1 = MZEROB(MC) + DO 550 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 2 - CC2(K,IJ1) * GLOSS(K,J1) + 550 CONTINUE + 555 CONTINUE +C +C *********************** SUM 1 TERM AT A TIME ********************** +C + DO 605 MC = ML1, MH1 + IJ0 = IJ + IJ = IJ + 1 + J0 = MZEROA(MC) + DO 600 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) + 1 - CC2(K,IJ0) * GLOSS(K,J0) + 600 CONTINUE + 605 CONTINUE + ENDIF +C ENDIF MZT.GT.0 +C +C *************** ADJUST GLOSS WITH DIAGONAL ELEMENT **************** +C + DO 700 K = 1, KTLOOP + GLOSS(K,I) = GLOSS(K,I) * VDIAG(K,I) + 700 CONTINUE + 710 CONTINUE +C +C ********************************************************************* +C ******************** END OF SUBROUTINE BACKSUB ********************** +C ********************************************************************* +C + RETURN + END SUBROUTINE BACKSUB diff --git a/code/benchmark_mod.f b/code/benchmark_mod.f new file mode 100644 index 0000000..daeebd6 --- /dev/null +++ b/code/benchmark_mod.f @@ -0,0 +1,185 @@ +! $Id: benchmark_mod.f,v 1.1 2009/06/09 21:51:54 daven Exp $ + MODULE BENCHMARK_MOD +! +!****************************************************************************** +! Module BENCHMARK_MOD contains routines to save out initial and final +! tracer masses which are needed for GEOS-CHEM benchmark diagnostics. +! (bmy, 7/20/04, 10/3/05) +! +! Module Variables: +! ============================================================================ +! (1 ) INITIAL_FILE (CHAR*255) : Name of file w/ initial tracer mass +! (2 ) FINAL_FILE (CHAR*255) : Name of file w/ final tracer mass +! +! Module Routines: +! ============================================================================ +! (1 ) STDRUN : Saves initial or final tracer mass to bpch file format +! +! GEOS-CHEM modules referenced by biomass_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module containing routines for binary punch file I/O +! (2 ) file_mod.f : Contains file unit numbers and error checks +! (3 ) logical_mod.f : Module containing GEOS-CHEM logical switches +! (4 ) time_mod.f : Module containing routines for computing time & date +! (5 ) tracer_mod.f : Module containing GEOS-CHEM tracer array STT etc. +! (6 ) tracerid_mod.f : Module containing pointers to tracers & emissions +! +! NOTES: +! (1 ) Now expand date & time tokens in filenames (bmy, 1/31/05) +! (2 ) Now modified for GCAP grid (swu, bmy, 6/28/05) +! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE VARIABLES + !================================================================= + CHARACTER(LEN=255) :: INITIAL_FILE + CHARACTER(LEN=255) :: FINAL_FILE + + !================================================================= + ! MODULE ROUTINES -- Follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE STDRUN( LBEGIN ) +! +!****************************************************************************** +! Subroutine STDRUN dumps the mass of either Ox [kg] or 222Rn, 210Pb, and 7Be +! [kg] at the start & end of each run. This is necessary for GEOS-CHEM +! benchmarking. (bmy, 8/12/02, 10/3/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) LBEGIN (LOGICAL) : TRUE denotes beginning of the run; +! FALSE denotes the end of the run +! +! NOTES: +! (1 ) Changed name from STDRUN_Ox to STDRUN, since we now can also save out +! Rn/Pb/Be for NSRCX==1. Also deleted obsolete code from 6/02. Added +! LBEGIN as an argument to determine if this is the start or end of the +! run. (bmy, 8/12/02) +! (2 ) Bundled into "benchmark_mod.f" (bmy, 7/20/04) +! (3 ) Now expand date tokens in the filename (bmy, 1/31/05) +! (4 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids . Also removed references to CMN_DIAG +! and TRCOFFSET. (bmy, 6/28/05) +! (5 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : OPEN_BPCH2_FOR_WRITE, BPCH2 + USE BPCH2_MOD, ONLY : GET_HALFPOLAR, GET_MODELNAME + USE FILE_MOD, ONLY : IU_FILE, IOERROR + USE TIME_MOD, ONLY : EXPAND_DATE, GET_NYMD + USE TIME_MOD, ONLY : GET_NHMS, GET_TAU + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM, ITS_A_RnPbBe_SIM + USE TRACER_MOD, ONLY : STT, N_TRACERS + USE TRACERID_MOD, ONLY : IDTOX + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: LBEGIN + + ! Local variables + INTEGER :: N, NYMD, NHMS + INTEGER, PARAMETER :: IFIRST=1, JFIRST=1, LFIRST=1 + INTEGER, PARAMETER :: CENTER180=1 + INTEGER :: HALFPOLAR + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR) + REAL*4 :: LONRES, LATRES + REAL*8 :: TAU + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY, RESERVED, UNIT + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! STDRUN begins here! + !================================================================= + + ! Return if we are not doing either a radon or fullchem stdrun + IF ( ( .not. ITS_A_FULLCHEM_SIM() ) .and. + & ( .not. ITS_A_RnPbBe_SIM() ) ) RETURN + + ! Define variables for binary punch file + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + CATEGORY = 'TCMASS-$' + UNIT = 'kg' + RESERVED = '' + LONRES = DISIZE + LATRES = DJSIZE + NYMD = GET_NYMD() + NHMS = GET_NHMS() + TAU = GET_TAU() + + ! Define filename for beginning or end of benchmark run + IF ( LBEGIN ) THEN + TITLE = 'GEOS-CHEM Benchmark: Initial Tracer Mass' + FILENAME = INITIAL_FILE + ELSE + TITLE = 'GEOS-CHEM Benchmark: Final Tracer Mass' + FILENAME = FINAL_FILE + ENDIF + + ! Expand any date tokens in the filename + CALL EXPAND_DATE( FILENAME, NYMD, NHMS ) + + !================================================================= + ! Save the mass of 222Rn, 210Pb, 7Be to a file + !================================================================= + IF ( ITS_A_RnPbBE_SIM() ) THEN + + ! Open binary punch file for writing + CALL OPEN_BPCH2_FOR_WRITE( IU_FILE, FILENAME, TITLE ) + + ! Loop over tracers + DO N = 1, N_TRACERS + + ! Save Rn, Pb, Be as REAL*4 + ARRAY(:,:,:) = STT(:,:,:,N) + + ! Write Rn, Pb, Be to binary punch file + CALL BPCH2( IU_FILE, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, TAU, TAU, RESERVED, + & IIPAR, JJPAR, LLPAR, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,:) ) + + ENDDO + + !================================================================= + ! Save the mass of Ox to a file + !================================================================= + ELSE IF ( ITS_A_FULLCHEM_SIM() .and. IDTOX > 0 ) THEN + + ! Open binary punch file for writing + CALL OPEN_BPCH2_FOR_WRITE( IU_FILE, FILENAME, TITLE ) + + ! Save Ox as REAL*4 + ARRAY(:,:,:) = STT(:,:,:,IDTOX) + + ! Write Ox to binary punch file + CALL BPCH2( IU_FILE, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTOX, + & UNIT, GET_TAU(), GET_TAU(), RESERVED, + & IIPAR, JJPAR, LLPAR, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,:) ) + + ENDIF + + ! Close file + CLOSE( IU_FILE ) + + ! Return to MAIN program + END SUBROUTINE STDRUN + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE BENCHMARK_MOD diff --git a/code/biofit.f b/code/biofit.f new file mode 100644 index 0000000..b35e9a4 --- /dev/null +++ b/code/biofit.f @@ -0,0 +1,40 @@ +C $Id: biofit.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + REAL*8 FUNCTION BIOFIT(COEFF1,XLAI1,SUNCOS1,CFRAC1) + + IMPLICIT NONE +C=============================================== +C Calculate the light correction +C=============================================== +C* BIOFIT and SUNPARAM were written by Y.H. Wang. See comment +C* in subroutine DEPVEL on what these subroutines do. +C************************************************************* +# include "CMN_SIZE" +# include "CMN_DEP" + INTEGER KK + PARAMETER (KK=4) + REAL*8 COEFF1(NPOLY),TERM(KK),REALTERM(NPOLY) + REAL*8 XLAI1,SUNCOS1,CFRAC1 + INTEGER K,K1,K2,K3 + + TERM(1)=1. + TERM(2)=XLAI1 + TERM(3)=SUNCOS1 + TERM(4)=CFRAC1 + CALL SUNPARAM(TERM(2)) + K=0 + DO K3=1,KK + DO K2=K3,KK + DO K1=K2,KK + K=K+1 + REALTERM(K)=TERM(K1)*TERM(K2)*TERM(K3) + END DO + END DO + END DO + BIOFIT=0 + DO K=1,NPOLY + BIOFIT=BIOFIT+COEFF1(K)*REALTERM(K) + END DO + IF (BIOFIT.LT.0.1) BIOFIT=0.1 + + RETURN + END diff --git a/code/biofuel_mod.f b/code/biofuel_mod.f new file mode 100644 index 0000000..d2234b3 --- /dev/null +++ b/code/biofuel_mod.f @@ -0,0 +1,1416 @@ +! $Id: biofuel_mod.f,v 1.2 2011/02/23 00:08:47 daven Exp $ + MODULE BIOFUEL_MOD +! +!****************************************************************************** +! Module BIOFUEL_MOD contains arrays and routines to compute yearly +! biofuel emissions for NOx, CO, ALK4, ACET, MEK, ALD2, PRPE, C3H8, +! CH2O, and C2H6. (bmy, 9/12/00, 9/18/07) +! +! Module Variables: +! ============================================================================ +! (1 ) NBFMAX : Maximum # of biofuel burning species +! (2 ) NBFTRACE : # of emitted biofuel burning species (<= NBFMAX) +! (3 ) BFTRACE : Array of tracer #'s for emitted biofuel species +! (4 ) BIOFUEL : array containing biofuel emissions +! +! Module Routines: +! ============================================================================ +! (1 ) BIOFUEL_BURN : Reads data from disk & computes biofuel emissions +! (2 ) SCALE_BIOFUEL_CO : Scales biofuel CO to account for VOC oxidation +! (3 ) SCALE_BIOFUEL_ACET : Scales biofuel ACET to match a posteriori source +! (4 ) SCALE_FUTURE : Applies future scale factors to biofuel emissions +! (5 ) SET_BFTRACE : Initializes NBFTRACE counter and BFTRACE array +! (6 ) INIT_BIOFUEL : Initializes the BIOFUEL array +! (7 ) CLEANUP_BIOFUEL : Deallocates the BIOFUEL array +! +! GEOS-CHEM modules referenced by biofuel_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ DAO met field arrays +! (3 ) diag_mod.f : Module w/ GEOS-CHEM diagnostic arrays +! (4 ) directory_mod.f : Module w/ GEOS-CHEM data & met field dirs +! (5 ) epa_nei_mod.f : Module w/ routines to read EPA/NEI99 data +! (6 ) error_mod.f : Module w/ NaN and other error check routines +! (7 ) logical_mod.f : Module w/ GEOS-CHEM logical switches +! (8 ) tracer_mod.f : Module w/ GEOS-CHEM tracer array etc. +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! (10) transfer_mod.f : Module w/ routines to cast & resize arrays +! +! NOTES: +! (1 ) Now account for extra production of CO from VOC's for Tagged CO +! and CO-OH simulations (bmy, 1/3/01) +! (2 ) Now read NBIOFUEL=10 biofuel species. Also archive biofuel emissions +! in the ND34 diagnostic. (bmy, 4/17/01) +! (3 ) Now dimension BFTRACE arrays to be of size NBFMAX instead of having +! them be made allocatable. Also updated comments. (bmy, 4/17/01) +! (4 ) Bug fix: now make sure to index biofuel tracers w/ the correct tracer +! number, even when there are less than the maximum species being +! requested (bmy, 8/24/01) +! (5 ) Bug fix: now index biofuel CH2O correctly (bmy, 8/28/01) +! (6 ) Now scale biofuel ACET by 0.82, in order to match the a posteriori +! acetone source from Jacob et al 2001. Also updated comments. +! (bdf, bmy, 9/10/01) +! (7 ) BIOFUEL is now declared (NBFTRACE,IIPAR,JJPAR). Now use TRANSFER_2D +! from "transfer_mod.f" to copy data into BIOFUEL. (bmy, 9/28/01) +! (8 ) Deleted obsolete code from 9/01 (bmy, 11/15/01) +! (9 ) Now do unit conversion every time step. Also added private +! array BIOFUEL_KG to hold emissions in kg over the entire +! month. (bmy, 5/9/02) +! (10) Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Updated comments. BIOMASS_KG is now +! an allocatable module array instead of a local array in routine +! "biofuel_burn.f". (bmy, 5/28/02) +! (11) Now reference BXHEIGHT from "dao_mod.f". Now references "error_mod.f". +! Also deleted obsolete code from various routines. Also references +! "tracerid_mod.f" Added routine SET_NBFTRACE. (bmy, 11/6/02) +! (12) Now call READ_BPCH2 with QUIET=.TRUE. to suppress output (bmy, 3/14/03) +! (13) Now references "directory_mod.f" (bmy, 7/19/04) +! (14) Now references "time_mod.f" and "epa_nei_mod.f" (bmy, 11/5/04) +! (15) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +! (16) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (17) Rewrite IF statements to avoid seg fault errors when LNEI99 is turned +! off (bmy, 2/1/06) +! (18) Modified for IPCC future emissions scale factors. Added private +! routine SCALE_FUTURE. (swu, bmy, 5/30/06) +! (19) Modified for VOC-scaling of CO emissions for H2/HD sim (phs, 5/16/07) +! (20) Added 9 gaseous biofuel emissions: GLYX, MGLY, BENZ, +! TOLU, XYLE, C2H4, C2H2, GLYC, HAC. (tmf, 1/7/09) +! (21) Emissions for these 9 tracers are scaled from CO emissions. (tmf, 1/7/09) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "biofuel_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: NBFMAX + PUBLIC :: NBFTRACE + PUBLIC :: BFTRACE + PUBLIC :: BIOFUEL + + ! ... and these routines + PUBLIC :: BIOFUEL_BURN + PUBLIC :: CLEANUP_BIOFUEL + PUBLIC :: INIT_BIOFUEL + PUBLIC :: SET_BFTRACE + + !================================================================= + ! MODULE VARIABLES + !================================================================= + INTEGER, PARAMETER :: NBFMAX = 19 + + INTEGER :: NBFTRACE + INTEGER :: BFTRACE(NBFMAX) + + REAL*8, ALLOCATABLE :: BIOFUEL(:,:,:) + REAL*8, ALLOCATABLE :: BIOFUEL_KG(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE BIOFUEL_BURN +! +!****************************************************************************** +! Subroutine BIOFUEL_BURN computes the yearly biofuel burning emissions +! and also archives them into GEOS-CHEM diagnostics. +! (rvm, acs, bnd, bmy, 9/12/00, 5/30/06) +! +! Biofuel emissions are based on estimates by Rose Yevich and Jennifer +! Logan (reference TBA). +! +! NOTES: +! (1 ) Renamed array that held biofuel emissions from TWOODIJ to BIOFUEL, +! and also expaneded to hold NOx. (rvm, acs, bmy, 9/12/00) +! (2 ) BIOFUEL is a true global array -- use offsets IREF, JREF to index +! it as you would T, P, or other global CTM variables (bmy, 9/12/00) +! (3 ) ND29 and ND32 diagnostics are now computed within BIOFUEL_BURN +! instead of in "emissdr.f", as was done previously. (bmy, 9/12/00) +! (4 ) Enhance CO from biofuel burning by 10% for Tagged CO and CO-OH +! simulations, to account for extra production of CO from VOC's. +! (bnd, bmy, 1/3/01) +! (5 ) Now read NBIOFUEL=10 biofuel species. Also archive biofuel emissions +! in the ND34 diagnostic. Updated output information. (bmy, 4/17/01) +! (6 ) Now read new biofuel emissions (Apr 2001) from the "biofuel_200104" +! subdirectory of DATA_DIR (bmy, 4/18/01) +! (7 ) Bug fix: now make sure to index biofuel tracers w/ the correct tracer +! number, even when there are less than the maximum species being +! requested (bmy, 8/24/01) +! (8 ) Bug fix: now use tracer #20 to read biofuel CH2O (bmy, 8/28/01) +! (9 ) Now scale biofuel ACET by 0.5, in order to match the a posteriori +! acetone source from Jacob et al 2001 (bdf, bmy, 9/5/01) +! (10) Remove IREF, JREF -- they are obsolete. BIOFUEL(:,IREF,JREF) is now +! BIOFUEL(:,I,J). Make sure to use IDBFCO and IDBFNOX in ND29 and +! ND32 diagnostics. Now use TRANSFER_2D from "transfer_mod.f" to +! cast data from REAL*4 to REAL*8 and copy to BIOFUEL (bmy, 9/28/01) +! (11) Deleted obsolete code from 9/01 (bmy, 11/15/01) +! (12) Bug fix -- need to convert from kg --> molec/cm3/s on every time +! step since the box volumes change w/ the surface pressure over +! the course of the year. Add parallel DO-loop for unit conversion. +! Also archive diagnostics w/in the parallel DO-loop. MOLWT needs to +! be an array of size (NBFMAX). Now read biofuel file w/ the correct +! amt of Tg C for ACET, C2H6, C3H8. (bmy, 6/11/02) +! (13) Now reference BXHEIGHT from "dao_mod.f". Also reference IDTNOX, +! IDBFNOX, etc. from "tracerid_mod.f". (bmy, 11/6/02) +! (14) Now call READ_BPCH2 with QUIET=.TRUE. flag to suppress extra info +! from being printed (bmy, 3/14/03) +! (15) Added fancy output (bmy, 4/26/04) +! (16) Now references "tracer_mod.f" and "directory_mod.f" (bmy, 7/19/04) +! (17) Now can overwrite USA with EPA/NEI biofuel emissions. Now references +! function GET_DAY_OF_WEEK from "time_mod.f". Now references LNEI99 +! from "logical_mod.f". Now reference GET_EPA_BIOFUEL and +! GET_USA_MASK from "epa_nei_mod.f". (rch, rjp, bmy, 11/5/04) +! (18) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +! (19) Now make sure all USE statements are USE, ONLY. Eliminate reference +! to TRACER_MOD, it's obsolete (bmy, 10/3/05) +! (20) Rewrite IF statements to avoid seg fault errors when LNEI99 is turned +! off (bmy, 2/1/06) +! (21) Now references LFUTURE from "logical_mod.f". +! (22) Now reference ITS_A_H2HD_SIM from "tracer_mod.f" for ND29. +! (phs, 9/18/07) +! (23) Switch off biofuel in S.E.-Asia if Streets 2006 inventory is used, +! accounting for FSCLYR from CMN_O3 (phs,3/17/08) +! (24) Add scaling of aromatic emissions over the US. (hotp, 11/23/09) +! 7 Feb 2011 - R. Yantosca - If we are using the EPA/NEI05 anthropogenic +! emissions, get biofuels from EPA/NEI99 over USA +! 15 Nov 2012 - C. Keller - Set biofuel emissions to zero if BRAVO, CAC or +! EMEP emissions are used, since these +! inventories already contain biofuel emiss +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D, GET_RES_EXT + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DAO_MOD, ONLY : BXHEIGHT + USE DIAG_MOD, ONLY : AD29, AD32_bf, AD34 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE EPA_NEI_MOD, ONLY : GET_EPA_BIOFUEL, GET_USA_MASK + USE LOGICAL_MOD, ONLY : LFUTURE, LNEI99, LSTREETS + USE LOGICAL_MOD, ONLY : LNEI05 + USE LOGICAL_MOD, ONLY : LRETRO ! (dbm, 8/18/2011) + USE STREETS_ANTHRO_MOD, ONLY : GET_SE_ASIA_MASK + USE TIME_MOD, ONLY : GET_DAY_OF_WEEK, GET_YEAR + USE TRACER_MOD, ONLY : ITS_A_H2HD_SIM + USE TRACERID_MOD, ONLY : IDBFCO, IDBFNOX, IDTACET + USE TRACERID_MOD, ONLY : IDTALD2, IDTALK4, IDTC2H6 + USE TRACERID_MOD, ONLY : IDTC3H8, IDTCH2O, IDTCO + USE TRACERID_MOD, ONLY : IDTMEK, IDTNOX, IDTPRPE + USE TRACERID_MOD, ONLY : IDTGLYX, IDTMGLY, IDTBENZ + USE TRACERID_MOD, ONLY : IDTTOLU, IDTXYLE, IDTC2H4 + USE TRACERID_MOD, ONLY : IDTC2H2, IDTGLYC, IDTHAC + USE TRACERID_MOD, ONLY : IDTNO2, IDTNH3, IDTSO2 + USE TRACERID_MOD, ONLY : IDTBCPO, IDTOCPO + USE TRANSFER_MOD, ONLY : TRANSFER_2D + ! for US emission fix (hotp 11/20/09) + USE TRACERID_MOD, ONLY : IDBFBENZ,IDBFTOLU,IDBFXYLE + USE TRACERID_MOD, ONLY : IDBFGLYX,IDBFMGLY,IDBFC2H4 + USE TRACERID_MOD, ONLY : IDBFC2H2,IDBFGLYC,IDBFHAC + ! for CAC / BRAVO emissions fix (ckeller, 11/15/12) + USE LOGICAL_MOD, ONLY : LBRAVO, LCAC, LEMEP + USE BRAVO_MOD, ONLY : GET_BRAVO_MASK + USE CAC_ANTHRO_MOD, ONLY : GET_CANADA_MASK + USE EMEP_MOD, ONLY : GET_EUROPE_MASK + ! RCP Emissions + USE LOGICAL_MOD, ONLY : LRCP ! (cdh, 10/18/2011) + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! ND29, ND32, ND34 +# include "CMN_O3" ! FSCLYR + + ! Local variables + LOGICAL :: WEEKDAY + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: DO_ND29, DO_ND32, DO_ND34 + INTEGER :: AS, I, J, N, NN, DAY_NUM + INTEGER :: SIM_YEAR + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*8, SAVE :: MOLWT(NBFMAX) + REAL*8 :: TOTAL, BXHEIGHT_CM, EPA_NEI + CHARACTER(LEN=255) :: FILENAME + + ! External functions + REAL*8, EXTERNAL :: BOXVL + + REAL*8 :: BF_CO( IIPAR, JJPAR ) ! Biofuel emission of CO [molec/cm2/s] + + !================================================================= + ! B i o f u e l B u r n i n g B e g i n s H e r e !! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + + ! Allocate and zero the BIOFUEL array + CALL INIT_BIOFUEL + + ! Flags for whether or not to archive diagnostics + DO_ND29 = ( ND29 > 0 .and. IDBFCO /= 0 ) + DO_ND32 = ( ND32 > 0 .and. IDBFNOX /= 0 ) + DO_ND34 = ( ND34 > 0 ) + + ! Fancy output.. + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a,/)' ) 'B I O F U E L E M I S S I O N S' + + !============================================================== + ! GEOS-CHEM has the following biofuel burning species: + ! + ! Species Index CTM Tracer # Units as read from file + ! --------------------------------------------------------- + ! NOX 1 1 [kg NOx /box/year] + ! CO 2 4 [kg CO /box/year] + ! ALK4 3 5 [kg C /box/year] + ! ACET 4 9 [kg C /box/year] + ! MEK 5 10 [kg C /box/year] + ! ALD2 6 11 [kg C /box/year] + ! PRPE 7 18 [kg C /box/year] + ! C3H8 8 19 [kg C /box/year] + ! CH2O 9 20 [kg CH2O/box/year] + ! C2H6 10 21 [kg C /box/year] + ! + ! These emissions are converted to [molec/cm3/s] (or + ! [molec C/cm3/s] for hydrocarbons), since the chemistry + ! requires these units. + ! + ! There are NBFMAX=10 maximum allowed biofuel species, but + ! only NBFTRACE of these are actually emitted. Species are + ! turned off/on with the switches in the "tracer.dat" file. + ! + ! The BIOFUEL array is only of size NBFTRACE, to save memory. + ! We only read in the NBFTRACE species that are emitted. + ! + ! Biofuel burning emissions are aseasonal, so we only have + ! to read from disk on the very first model timestep. + ! However, we have to convert from kg --> molec/cm3/s every + ! timestep to ensure that we use the box heights and box + ! volumes throughout the year, instead of only at the + ! first timestep (bmy, 5/3/02) + !============================================================== + FILENAME = TRIM( DATA_DIR ) // + & 'biofuel_200202/biofuel.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Echo filename to log file + WRITE( 6, 110 ) TRIM( FILENAME ) + + ! Loop over the emitted biofuel burning tracers only + DO N = 1, NBFTRACE + + ! NN is the actual CTM tracer number of species N + NN = BFTRACE(N) + + ! Test for each tracer + IF ( NN == IDTNOX ) THEN + + !---------------- + ! Biofuel NOx + !---------------- + + ! Read biofuel NOx emissions in [kg/box/yr] -- tracer #1 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 1 , + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future NOx emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'NOxbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total of biofuel NOx + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'NOx ', TOTAL, '[Tg /yr]' + + ! Define MOLWT for use below + MOLWT(N) = 46d-3 + + ELSE IF ( NN == IDTCO ) THEN + + !---------------- + ! Biofuel CO + !---------------- + + ! Read biofuel CO emissions in [kg/box/yr] -- tracer #4 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 4, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Save BF_CO before scaling (tmf, 6/15/07) + BF_CO = ARRAY(:,:,1) + + ! Scale CO to account for oxidation of extra VOC's + CALL SCALE_BIOFUEL_CO( BIOFUEL_KG(N,:,:) ) + + ! Compute future CO emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'CObf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Print total CO + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'CO ', TOTAL, '[Tg /yr]' + + ! Define MOLWT for use below + MOLWT(N) = 28d-3 + + ELSE IF ( NN == IDTALK4 ) THEN + + !---------------- + ! Biofuel ALK4 + !---------------- + + ! Read biofuel ALK4 emissions in [kg/box/yr] -- tracer #5 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 5, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future ALK4 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total ALK4 + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'ALK4', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTACET ) THEN + + !---------------- + ! Biofuel ACET + !---------------- + + ! Read biofuel ACET emissions in [kg/box/yr] -- tracer #9 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 9, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Scale to match a posteriori source (bdf, bmy, 9/10/01) + CALL SCALE_BIOFUEL_ACET( BIOFUEL_KG(N,:,:) ) + + ! Compute future ACET emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total ACET + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'ACET', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTMEK ) THEN + + !---------------- + ! Biofuel MEK + !---------------- + + ! Read biofuel MEK emissions in [kg/box/yr] -- tracer #10 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 10, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future MEK emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total MEK + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'MEK ', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTALD2 ) THEN + + !---------------- + ! Biofuel ALD2 + !---------------- + + ! Read biofuel ALD2 emissions in [kg/box/yr] -- tracer #11 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 11, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future ALD2 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total ALD2 + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'ALD2', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTPRPE ) THEN + + !---------------- + ! Biofuel PRPE + !---------------- + + ! Read biofuel PRPE emissions in [kg/box/yr] -- tracer #18 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 18, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future PRPE emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total PRPE + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'PRPE', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTC3H8 ) THEN + + !---------------- + ! Biofuel C3H8 + !---------------- + + ! Read biofuel C3H8 emissions in [kg/box/yr] -- tracer #19 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 19, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future C3H8 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total C3H8 + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'C3H8', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTCH2O ) THEN + + !---------------- + ! Biofuel CH2O + !---------------- + + ! Read biofuel CH2O emissions in [kg/box/yr] -- tracer #20 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 20, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future CH2O emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total CH2O + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'CH2O', TOTAL, '[Tg /yr]' + + ! Define MOLWT for use below + MOLWT(N) = 30d-3 + + ELSE IF ( NN == IDTC2H6 ) THEN + + !---------------- + ! Biofuel C2H6 + !---------------- + + ! Read biofuel C2H6 emissions in [kg/box/yr] -- tracer #21 + CALL READ_BPCH2( FILENAME, 'BIOFSRCE', 21, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + BIOFUEL_KG(N,:,:) = ARRAY(:,:,1) + + ! Compute future C2H6 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbf', BIOFUEL_KG(N,:,:) ) + ENDIF + + ! Compute total C2H6 + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'C2H6', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTGLYX ) THEN + + !---------------- + ! Biofuel GLYX + !---------------- + + ! Emission ratio GLYX/CO = 6.62d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 58d-3 * 6.62d-3 ! [kg/box/yr] + + ! Compute total GLYX + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'GLYX', TOTAL, '[Tg/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 58d-3 + + + ELSE IF ( NN == IDTMGLY ) THEN + + !---------------- + ! Biofuel MGLY + !---------------- + + ! Emission ratio MGLY/CO = 3.47d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 72d-3 * 3.47d-3 ! [kg/box/yr] + + ! Compute total MGLY + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'MGLY', TOTAL, '[Tg/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 72d-3 + + ELSE IF ( NN == IDTBENZ ) THEN + + !---------------- + ! Biofuel BENZ + !---------------- + + ! Emission ratio BENZ/CO = 4.06d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 12d-3 * 6d0 * 4.06d-3 ! [kg C/box/yr] + + ! Compute total BENZ + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'BENZ', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + + ELSE IF ( NN == IDTTOLU ) THEN + + !---------------- + ! Biofuel TOLU + !---------------- + + ! Emission ratio TOLU/CO = 2.01d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 12d-3 * 7d0 * 2.01d-3 ! [kg C/box/yr] + + ! Compute total TOLU + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'TOLU', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTXYLE ) THEN + + !---------------- + ! Biofuel XYLE + !---------------- + + ! Emission ratio XYLE/CO = 0.82d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 12d-3 * 8d0 * 0.82d-3 ! [kg C/box/yr] + + ! Compute total XYLE + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'XYLE', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTC2H4 ) THEN + + !---------------- + ! Biofuel C2H4 + !---------------- + + ! Emission ratio C2H4/CO = 15.7d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 12d-3 * 2d0 * 15.7d-3 ! [kg C/box/yr] + + ! Compute total C2H4 + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'C2H4', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTC2H2 ) THEN + + !---------------- + ! Biofuel C2H2 + !---------------- + + ! Emission ratio C2H2/CO = 19d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 12d-3 * 2d0 * 19d-3 ! [kg C/box/yr] + + ! Compute total C2H2 + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'C2H2', TOTAL, '[Tg C/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 12d-3 + + ELSE IF ( NN == IDTGLYC ) THEN + + !---------------- + ! Biofuel GLYC + !---------------- + + ! Emission ratio GLYC/CO = 3.66d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 60d-3 * 3.66d-3 ! [kg/box/yr] + + ! Compute total GLYC + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'GLYC', TOTAL, '[Tg/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 60d-3 + + ELSE IF ( NN == IDTHAC ) THEN + + !---------------- + ! Biofuel HAC + !---------------- + + ! Emission ratio HAC/CO = 3.31d-3 [mole/mole] + BIOFUEL_KG(N,:,:) = + & BF_CO(:,:) / 28d-3 * 74d-3 * 3.31d-3 ! [kg/box/yr] + + ! Compute total HAC + TOTAL = SUM( BIOFUEL_KG(N,:,:) ) * 1d-9 + WRITE( 6, 120 ) 'HAC', TOTAL, '[Tg/yr]' + + ! Define MOLWT for use below + MOLWT(N) = 74d-3 + + ENDIF + ENDDO + + ! Reset first time flag + FIRST = .FALSE. + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + ENDIF + + !================================================================= + ! Do the following on each emission timestep... + ! + ! Convert from [kg/box/yr] (or [kg C/box/yr]) to [molec/cm3/s] + ! (or [molec C/cm3/s]), since the emissions need to be in these + ! units for the chemistry. Now use parallel DO loops. + ! + ! NOTE: Need to do the unit conversion outside the IF (FIRST) + ! block, so that we use the same airmass quantities as are used + ! for the diagnostics. (bmy, 5/30/02) + ! + ! Also archive diagnostics w/in parallel loop (bmy, 5/30/02) + !================================================================= + + ! Get current day of the week + DAY_NUM = GET_DAY_OF_WEEK() + + ! Is it a weekday? + WEEKDAY = ( DAY_NUM > 0 .and. DAY_NUM < 6 ) + + ! get emissions year to test Streets + IF ( FSCALYR < 0 ) THEN + SIM_YEAR = GET_YEAR() + ELSE + SIM_YEAR = FSCALYR + ENDIF + + + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, BXHEIGHT_CM, N, NN, EPA_NEI ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! BXHEIGHT_CM = the surface grid box height in cm + BXHEIGHT_CM = BXHEIGHT(I,J,1) * 1d2 + + ! Loop over all biofuel tracers + DO N = 1, NBFTRACE + + ! Get GEOS-CHEM tracer number + NN = BFTRACE(N) + + ! Biofuel emissions in [molec/cm3/s] + BIOFUEL(N,I,J) = BIOFUEL_KG(N,I,J) * + & ( 6.023d23 / MOLWT(N) ) / + & ( 365d0 * 86400d0 * BOXVL(I,J,1) ) + + !----------------------------------------------------------- + ! RETRO anthropogenic emissions include residential biofuel, + ! so set this to zero if we are using RETRO for anthro VOCs + ! (dbm, 8/18/2011) + !----------------------------------------------------------- + IF ( LRETRO ) THEN + IF ( (NN == IDTC2H2) .or. (NN == IDTC2H4) .or. + & (NN == IDTC2H6) .or. (NN == IDTPRPE) .or. + & (NN == IDTC3H8) .or. (NN == IDTALK4) .or. + & (NN == IDTCH2O) .or. (NN == IDTALD2) .or. + & (NN == IDTACET) .or. (NN == IDTMEK ) .or. + & (NN == IDTBENZ) .or. (NN == IDTTOLU) .or. + & (NN == IDTXYLE) ) THEN + + BIOFUEL(N,I,J) = 0.d0 + + ENDIF + ENDIF + + !----------------------------------------------------------- + ! RCP anthropogenic emissions include residential biofuel, + ! so set this to zero if we are using the RCP inventory + ! (cdh, 10/18/2011) + !----------------------------------------------------------- + IF ( LRCP ) THEN + IF ( (NN == IDTNOX ) .or. (NN == IDTCO ) .or. + & (NN == IDTBCPO) .or. (NN == IDTOCPO) .or. + & (NN == IDTSO2 ) .or. (NN == IDTNH3 ) .or. + & (NN == IDTC2H2) .or. (NN == IDTC2H4) .or. + & (NN == IDTC2H6) .or. (NN == IDTPRPE) .or. + & (NN == IDTC3H8) .or. (NN == IDTALK4) .or. + & (NN == IDTCH2O) .or. (NN == IDTALD2) .or. + & (NN == IDTACET) .or. (NN == IDTMEK ) .or. + & (NN == IDTBENZ) .or. (NN == IDTTOLU) .or. + & (NN == IDTXYLE) ) THEN + + BIOFUEL(N,I,J) = 0.d0 + + ENDIF + ENDIF + + + !----------------------------------------------------------- + ! Overwrite biofuels w/ EPA/NEI emissions over the USA + ! + ! NOTE: The NEI05 inventory only contains anthro emissions, + ! so we are forced to take the biofuel emissions over the + ! USA from the NEI99 inventory. (bmy, 2/7/11) + !----------------------------------------------------------- + + ! If EPA/NEI99 emissions are turned on.... + IF ( LNEI99 .or. LNEI05 ) THEN + + ! If we are over the USA ... + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + + ! We do not have EPA/NEI biofuel emission. + ! Use default emission for the newly added species. + ! (tmf, 1/8/08) + IF ( (NN /= IDTGLYX) .and. (NN /= IDTMGLY) .and. + & (NN /= IDTBENZ) .and. (NN /= IDTTOLU) .and. + & (NN /= IDTXYLE) .and. (NN /= IDTC2H4) .and. + & (NN /= IDTC2H2) .and. (NN /= IDTGLYC) .and. + & (NN /= IDTHAC ) ) THEN + + ! Get EPA/NEI biofuel [molec/cm2/s or atoms C/cm2/s] + EPA_NEI = GET_EPA_BIOFUEL( I, J, NN, WEEKDAY ) + + ! Convert [molec/cm2/s] to [molec/cm3/s] + BIOFUEL(N,I,J) = EPA_NEI / BXHEIGHT_CM + + ENDIF + ENDIF + ENDIF + + !----------------------------------------------------------- + ! If we are over SE ASIA and are using Streets 2006 (that is + ! emission year is GE 2001), set BIOFUEL to zero since they + ! are already accounted for (phs, 3/17/08) + !----------------------------------------------------------- + IF ( LSTREETS .and. ( SIM_YEAR >= 2001 ) ) THEN + + ! If we are over the SE Asia region + IF ( GET_SE_ASIA_MASK( I, J ) > 0d0 ) THEN + + ! Only zero BIOFUEL for tracers included in Streets emiss + IF ( (NN /= IDTGLYX) .AND. (NN /= IDTMGLY) .AND. + & (NN /= IDTGLYC) .AND. (NN /= IDTHAC ) .AND. + & (NN /= IDTBENZ) .AND. (NN /= IDTTOLU) .AND. + & (NN /= IDTXYLE) .AND. (NN /= IDTC2H4) .AND. + & (NN /= IDTC2H2) ) THEN + + BIOFUEL(N,I,J) = 0.d0 + + ENDIF + ENDIF + ENDIF + + !-------------------------------------------------------- + ! BRAVO anthropogenic emissions include residential + ! biofuel, so set this to zero if we are using BRAVO + ! (ckeller, 11/15/2012) + !-------------------------------------------------------- + + IF ( LBRAVO ) THEN + ! If we are over the BRAVO region + IF ( GET_BRAVO_MASK( I, J ) > 0d0 ) THEN + + ! If it's a BRAVO species + IF ( (NN == IDTNOX) .or. (NN == IDTCO) ) THEN + + BIOFUEL(N,I,J) = 0.d0 + + ENDIF + ENDIF + ENDIF + + !-------------------------------------------------------- + ! CAC anthropogenic emissions include residential + ! biofuel, so set this to zero if we are using CAC + ! (ckeller, 11/15/2012) + !-------------------------------------------------------- + IF ( LCAC ) THEN + + ! If we are over the CAC region + IF ( GET_CANADA_MASK( I, J ) > 0d0 ) THEN + + ! If it's a CAC species + IF ( (NN == IDTNOX) .or. (NN == IDTCO) ) THEN + + BIOFUEL(N,I,J) = 0.d0 + + ENDIF + ENDIF + ENDIF + + !-------------------------------------------------------- + ! EMEP anthropogenic emissions include residential + ! biofuel, so set this to zero if we are using EMEP + ! (ckeller, 11/15/2012) + !-------------------------------------------------------- + IF ( LEMEP ) THEN + + ! If we are over the EMEP region + IF ( GET_EUROPE_MASK( I, J ) > 0d0 ) THEN + + ! If it's an EMEP species + IF ( (NN == IDTNOX) .OR. (NN == IDTCO) .OR. + & (NN == IDTALK4) .OR. (NN == IDTMEK) .OR. + & (NN == IDTALD2) .OR. (NN == IDTPRPE) .OR. + & (NN == IDTC2H6) ) THEN + + BIOFUEL(N,I,J) = 0.d0 + + ENDIF + ENDIF + ENDIF + + ! move below so that BIOFUEL array is complete before + ! archiving diagnostic info (hotp 11/23/09) +! ! ND34 -- archive biofuel burning species [molec/cm2/s] +! IF ( DO_ND34 ) THEN +! AD34(I,J,N) = AD34(I,J,N) + ( BIOFUEL(N,I,J) * +! & BXHEIGHT_CM ) +! ENDIF + ENDDO + + ! ND29 -- CO source diagnostics [molec/cm2/s] + IF ( DO_ND29 ) THEN + + IF ( ITS_A_H2HD_SIM() ) THEN + AD29(I,J,3) = AD29(I,J,3) + ( BIOFUEL(IDBFCO,I,J) * + & BXHEIGHT_CM ) * 1.189d0 + ELSE + AD29(I,J,3) = AD29(I,J,3) + ( BIOFUEL(IDBFCO,I,J) * + & BXHEIGHT_CM ) + ENDIF + + ENDIF + + ! ND32 -- NOx source diagnostics [molec/cm2/s] + IF ( DO_ND32 ) THEN + AD32_bf(I,J) = AD32_bf(I,J) + ( BIOFUEL(IDBFNOX,I,J) * + & BXHEIGHT_CM ) + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! update aromatics based on CO over US (hotp 11/23/09) +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + !----------------------------------------------------------- + ! Scale VOC's based on the EPA/NEI99 biofuels over the USA + ! + ! NOTE: The NEI05 inventory only contains anthro emissions, + ! so we are forced to take the biofuel emissions over the + ! USA from the NEI99 inventory. (bmy, 2/7/11) + !----------------------------------------------------------- + IF ( LNEI99 .or. LNEI05 ) THEN + + ! If we are over the USA ... + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + ! update aromatics if necessary (hotp 11/20/09) + ! molecC/cm3/s XXXX = molec/cm3/s CO * + ! mol XXXX/mol CO * + ! molec C/molec XXXX + + ! BENZ (6 carbon/molec) + IF ( IDBFBENZ > 0 ) THEN + BIOFUEL(IDBFBENZ,I,J) = + & BIOFUEL(IDBFCO,I,J) * 4.06d-3 * 6.d0 + ENDIF + + ! TOLU (7 carbon/molec) + IF ( IDBFTOLU > 0 ) THEN + BIOFUEL(IDBFTOLU,I,J) = + & BIOFUEL(IDBFCO,I,J) * 2.01d-3 * 7.d0 + ENDIF + + ! XYLE (8 carbon/molec) + IF ( IDBFXYLE > 0 ) THEN + BIOFUEL(IDBFXYLE,I,J) = + & BIOFUEL(IDBFCO,I,J) * 0.82d-3 * 8.d0 + ENDIF + + ! GLYX (molec/cm3/s) + IF ( IDBFGLYX > 0 ) THEN + BIOFUEL(IDBFGLYX,I,J) = + & BIOFUEL(IDBFCO,I,J) * 6.62d-3 + ENDIF + + ! MGLY + IF ( IDBFMGLY > 0 ) THEN + BIOFUEL(IDBFMGLY,I,J) = + & BIOFUEL(IDBFCO,I,J) * 3.47d-3 + ENDIF + + ! C2H4 (2 carbons/molec) + IF ( IDBFC2H4 > 0 ) THEN + BIOFUEL(IDBFC2H4,I,J) = + & BIOFUEL(IDBFCO,I,J) * 15.7d-3 * 2.d0 + ENDIF + + ! C2H2 (2 carbons/molec) + IF ( IDBFC2H2 > 0 ) THEN + BIOFUEL(IDBFC2H2,I,J) = + & BIOFUEL(IDBFCO,I,J) * 19.0d-3 * 2.d0 + ENDIF + + ! GLYC + IF ( IDBFGLYC > 0 ) THEN + BIOFUEL(IDBFGLYC,I,J) = + & BIOFUEL(IDBFCO,I,J) * 3.66d-3 + ENDIF + + ! HAC + IF ( IDBFHAC > 0 ) THEN + BIOFUEL(IDBFHAC,I,J) = + & BIOFUEL(IDBFCO,I,J) * 3.31d-3 + ENDIF + + ENDIF ! USA_MASK + + ENDIF ! LNEI99 + ENDDO ! I + ENDDO ! J +!$OMP END PARALLEL DO + + + ! Save diagnostic information (biofuel burning emissions) (hotp 11/23/09) + ! ND34 -- archive biofuel burning species [molec/cm2/s] or + ! [molecC/cm2/s] for species transported as carbon + IF ( DO_ND34 ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, BXHEIGHT_CM, N ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! BXHEIGHT_CM = the surface grid box height in cm + BXHEIGHT_CM = BXHEIGHT(I,J,1) * 1d2 + + ! loop over biofuel species + DO N = 1, NBFTRACE + ! ND34 -- archive biofuel burning species [molec/cm2/s] + AD34(I,J,N) = AD34(I,J,N) + ( BIOFUEL(N,I,J) * + & BXHEIGHT_CM ) + ENDDO ! NBFTRACE + + ENDDO ! I + ENDDO ! J +!$OMP END PARALLEL DO + ENDIF ! ND34 + + !================================================================= + ! FORMAT statements + !================================================================= + 110 FORMAT( 'BIOFUEL_BURN: Reading ', a ) + 120 FORMAT( 'Sum Biofuel ', a4, 1x, ': ', f9.3, 1x, a9 ) + + ! Return to calling program + END SUBROUTINE BIOFUEL_BURN + +!------------------------------------------------------------------------------ + + SUBROUTINE SCALE_BIOFUEL_CO( BFARRAY ) +! +!****************************************************************************** +! Subroutine SCALE_BIOFUEL_CO multiplies the CO biofuel emissions by scale +! factors to account for CO production from VOC's that are not explicitly +! carried in the chemistry mechanisms. (bnd, bmy, 3/19/01, 7/19/04) +! +! Arguments as Input: +! ============================================================================ +! (1) BFARRAY (REAL*8) : Array containing biofuel burning CO emissions +! +! NOTES: +! (1 ) Scale factors were determined by Jennifer Logan (jal@io.harvard.edu), +! Bryan Duncan (bnd@io.harvard.edu) and Daniel Jacob (djj@io.harvard.edu) +! (2 ) BFARRAY is now of size (IIPAR,JJPAR) (bmy, 9/28/01) +! (3 ) Deleted obsolete code from 9/01 (bmy, 11/15/01) +! (4 ) Now use inquiry functions in "tracer_mod.f" instead of the variable +! NSRCX (bmy, 7/19/04) +!****************************************************************************** +! + ! References to F90 modules + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM, ITS_A_TAGCO_SIM + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: BFARRAY(IIPAR,JJPAR) + + !================================================================= + ! SCALE_BIOFUEL_CO begins here! + !================================================================= + IF ( ITS_A_FULLCHEM_SIM() ) THEN + + ! Full chemistry w/ SMVGEAR -- enhance by 8.6% + BFARRAY = BFARRAY * 1.086d0 + + ELSE IF ( ITS_A_TAGCO_SIM() ) THEN + + ! Tagged CO -- enhance by 18.9% + BFARRAY = BFARRAY * 1.189d0 + + ENDIF + + ! Return to calling program + END SUBROUTINE SCALE_BIOFUEL_CO + +!------------------------------------------------------------------------------ + + SUBROUTINE SCALE_BIOFUEL_ACET( BFARRAY ) +! +!****************************************************************************** +! Subroutine SCALE_BIOFUEL_ACET multiplies the ACET biofuel emissions by a +! scale factor in order to match the source from the Jacob et al 2001 paper. +! (bdf, bmy, 9/10/01, 11/15/01) +! +! Arguments as Input: +! ============================================================================ +! (1) BFARRAY (REAL*8) : Array containing biofuel burning ACET emissions +! +! Reference: +! ============================================================================ +! Jacob, D.J., B.D. Field, E. Jin, I. Bey, Q. Li, J.A. Logan, and +! R.M. Yantosca, Atmospheric budget of acetone, submitted to +! Geophys. Res. Lett., 2001. +! +! NOTES: +! (1 ) Adapted from SCALE_BIOMASS_CO (bdf, bmy, 9/10/01) +! (2 ) BFARRAY is now of size (IIPAR,JJPAR) (bmy, 9/28/01) +! (3 ) Deleted obsolete code from 9/01 (bmy, 11/15/01) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: BFARRAY(IIPAR,JJPAR) + + !================================================================= + ! SCALE_BIOFUEL_ACET begins here! + !================================================================= + + ! Scale by 0.82 to match the a posteriori source + BFARRAY = BFARRAY * 0.82d0 + + ! Return to calling program + END SUBROUTINE SCALE_BIOFUEL_ACET + +!------------------------------------------------------------------------------ + + SUBROUTINE SCALE_FUTURE( NAME, BF ) +! +!****************************************************************************** +! Subroutine SCALE_FUTURE applies the IPCC future emissions scale factors +! to the biofuel emisisons in order to compute the future biofuel emissions +! for NOx, CO, and VOC's (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) NAME (CHARACTER) : Denotes type of scale factor to use (e.g. NOx) +! (2 ) BF (REAL*8 ) : Array w/ biomass burning emisisons [molec/cm2] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_CObf + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxbf + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_VOCbf + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: BF(IIPAR,JJPAR) + CHARACTER(LEN=*), INTENT(IN) :: NAME + + ! Local variables + INTEGER :: I, J + + !================================================================= + ! SCALE_FUTURE begins here! + !================================================================= + + IF ( NAME == 'NOxbf' ) THEN + + ! Compute future NOx emissions +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + BF(I,J) = BF(I,J) * GET_FUTURE_SCALE_NOxbf( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( NAME == 'CObf' ) THEN + + ! Compute future CO emissions +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + BF(I,J) = BF(I,J) * GET_FUTURE_SCALE_CObf( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE + + ! Compute future hydrocarbon emissions +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + BF(I,J) = BF(I,J) * GET_FUTURE_SCALE_VOCbf( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ENDIF + + ! Return to calling program + END SUBROUTINE SCALE_FUTURE + +!------------------------------------------------------------------------------ + + SUBROUTINE SET_BFTRACE +! +!****************************************************************************** +! Subroutine SET_NBFTRACE sets the NBFTRACE variable with the number of +! biofuel tracers that are turned on. This was split off from "tracerid.f" +! in order to prevent circular module references. (bmy, 11/6/02, 10/3/05) +! +! NOTES: +! (1 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +!****************************************************************************** +! + ! References to F90 modules + USE TRACERID_MOD, ONLY : IDBFACET, IDBFALD2, IDBFALK4, IDBFC2H6 + USE TRACERID_MOD, ONLY : IDBFC3H8, IDBFCH2O, IDBFCO, IDBFMEK + USE TRACERID_MOD, ONLY : IDBFNOX, IDBFPRPE, IDTACET, IDTALD2 + USE TRACERID_MOD, ONLY : IDTALK4, IDTC2H6, IDTC3H8, IDTCH2O + USE TRACERID_MOD, ONLY : IDTCO, IDTMEK, IDTNOX, IDTPRPE + + USE TRACERID_MOD, ONLY : IDBFGLYX, IDBFMGLY, IDBFBENZ, IDBFTOLU + USE TRACERID_MOD, ONLY : IDBFXYLE, IDBFC2H4, IDBFC2H2, IDBFGLYC + USE TRACERID_MOD, ONLY : IDBFHAC + USE TRACERID_MOD, ONLY : IDTGLYX, IDTMGLY, IDTBENZ, IDTTOLU + USE TRACERID_MOD, ONLY : IDTXYLE, IDTC2H4, IDTC2H2, IDTGLYC + USE TRACERID_MOD, ONLY : IDTHAC + !================================================================= + ! SET_BFTRACE begins here! + !================================================================= + + ! Initialize + NBFTRACE = 0 + + ! Increment NBFTRACE for each turned on biofuel tracer + IF ( IDBFNOX /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFCO /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFALK4 /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFACET /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFMEK /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFALD2 /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFPRPE /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFC3H8 /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFCH2O /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFC2H6 /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFGLYX /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFMGLY /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFBENZ /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFTOLU /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFXYLE /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFC2H4 /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFC2H2 /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFGLYC /= 0 ) NBFTRACE = NBFTRACE + 1 + IF ( IDBFHAC /= 0 ) NBFTRACE = NBFTRACE + 1 + + ! Fill BFTRACE w/ appropriate TRACER ID #'s + IF ( IDBFNOX /= 0 ) BFTRACE(IDBFNOX ) = IDTNOX + IF ( IDBFCO /= 0 ) BFTRACE(IDBFCO ) = IDTCO + IF ( IDBFALK4 /= 0 ) BFTRACE(IDBFALK4) = IDTALK4 + IF ( IDBFACET /= 0 ) BFTRACE(IDBFACET) = IDTACET + IF ( IDBFMEK /= 0 ) BFTRACE(IDBFMEK ) = IDTMEK + IF ( IDBFALD2 /= 0 ) BFTRACE(IDBFALD2) = IDTALD2 + IF ( IDBFPRPE /= 0 ) BFTRACE(IDBFPRPE) = IDTPRPE + IF ( IDBFC3H8 /= 0 ) BFTRACE(IDBFC3H8) = IDTC3H8 + IF ( IDBFCH2O /= 0 ) BFTRACE(IDBFCH2O) = IDTCH2O + IF ( IDBFC2H6 /= 0 ) BFTRACE(IDBFC2H6) = IDTC2H6 + IF ( IDBFGLYX /= 0 ) BFTRACE(IDBFGLYX) = IDTGLYX + IF ( IDBFMGLY /= 0 ) BFTRACE(IDBFMGLY) = IDTMGLY + IF ( IDBFBENZ /= 0 ) BFTRACE(IDBFBENZ) = IDTBENZ + IF ( IDBFTOLU /= 0 ) BFTRACE(IDBFTOLU) = IDTTOLU + IF ( IDBFXYLE /= 0 ) BFTRACE(IDBFXYLE) = IDTXYLE + IF ( IDBFC2H4 /= 0 ) BFTRACE(IDBFC2H4) = IDTC2H4 + IF ( IDBFC2H2 /= 0 ) BFTRACE(IDBFC2H2) = IDTC2H2 + IF ( IDBFGLYC /= 0 ) BFTRACE(IDBFGLYC) = IDTGLYC + IF ( IDBFHAC /= 0 ) BFTRACE(IDBFHAC ) = IDTHAC + + ! Echo biofuel tracer information + WRITE( 6, 100 ) BFTRACE( 1:NBFTRACE ) + 100 FORMAT( 'TRACERID: Biofuel burning tracers :', 20i3 ) + + ! Return to calling program + END SUBROUTINE SET_BFTRACE + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_BIOFUEL +! +!****************************************************************************** +! Subroutine INIT_BIOFUEL allocates and zeroes the BIOFUEL array. +! (bmy, 9/12/00, 10/15/02) +! +! NOTES: +! (1 ) Increase BIOFUEL array from 2 to NBIOFUEL=10 elements (bmy, 3/15/01) +! (2 ) Make sure NBFTRACE > 0 before allocating BIOFUEL (bmy, 4/17/01) +! (3 ) BIOFUEL is now declared (NBFTRACE,IIPAR,JJPAR) (bmy, 9/28/01) +! (4 ) Deleted obsolete code from 9/01 (bmy, 11/15/01) +! (5 ) Now references ALLOC_ERR from "error_mod.f". Also references IDBFNOX, +! IDBFCO, etc from "tracerid_mod.f" (bmy, 11/6/02) +! (6 ) Replace LWOODCO w/ LBIOFUEL from "logical_mod.f" (bmy, 7/19/04) +! (7 ) Remove reference to TRACERID_MOD, it's obsolete (bmy, 10/3/05) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LBIOFUEL + +# include "CMN_SIZE" ! Size parameters, etc + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_BIOFUEL begins here! + !================================================================= + IF ( LBIOFUEL .and. NBFTRACE > 0 ) THEN + ALLOCATE( BIOFUEL( NBFTRACE, IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BIOFUEL' ) + BIOFUEL = 0d0 + + ! This is a local array to hold biofuel in kg + ALLOCATE( BIOFUEL_KG( NBFTRACE, IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BIOFUEL_KG' ) + BIOFUEL_KG = 0d0 + ENDIF + + ! Return to calling program + END SUBROUTINE INIT_BIOFUEL + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_BIOFUEL +! +!****************************************************************************** +! Subroutine CLEANUP_BIOFUEL deallocates the BIOFUEL array (bmy, 9/11/00) +!****************************************************************************** +! + ! CLEANUP_BIOFUEL begins here! + IF ( ALLOCATED( BIOFUEL ) ) DEALLOCATE( BIOFUEL ) + IF ( ALLOCATED( BIOFUEL_KG ) ) DEALLOCATE( BIOFUEL_KG ) + + ! Return to calling program + END SUBROUTINE CLEANUP_BIOFUEL + +!------------------------------------------------------------------------------ + + END MODULE BIOFUEL_MOD diff --git a/code/biomass_mod.f b/code/biomass_mod.f new file mode 100644 index 0000000..6e59d34 --- /dev/null +++ b/code/biomass_mod.f @@ -0,0 +1,517 @@ +! $Id: biomass_mod.f,v 1.3 2012/09/05 22:35:07 yanko Exp $ + MODULE BIOMASS_MOD +! +!****************************************************************************** +! Module BIOMASS_MOD is a "wrapper" module, which allows us to select either +! GFED2 biomass burning emissions, or the default GEOS-Chem biomass burning +! emissions (based on Bryan Duncan et al). (psk, bmy, 4/5/06, 9/18/07) +! +! GEOS-Chem has the following biomass burning gas-phase species: +! +! Species Index G-C Tracer # Units +! ---------------------------------------------------------------------------- +! GAS PHASE SPECIES (contained in both GFED2 & Duncan et al 2001) +! +! NOx 1 1 [molec NOx /cm2/s] +! CO 2 4 [molec CO /cm2/s] +! ALK4 3 5 [atoms C /cm2/s] +! ACET 4 9 [atoms C /cm2/s] +! MEK 5 10 [atoms C /cm2/s] +! ALD2 6 11 [atoms C /cm2/s] +! PRPE 7 18 [atoms C /cm2/s] +! C3H8 8 19 [atoms C /cm2/s] +! CH2O 9 20 [molec CH2O/cm2/s] +! C2H6 10 21 [atoms C /cm2/s] +! +! ---------------------------------------------------------------------------- +! AEROSOL SPECIES (contained in GFED2; read separately in Duncan et al 2001) +! +! SO2 11 26 [molec SO2 /cm2/s] +! NH3 12 32 [molec NH3 /cm2/s] +! BC 13 34 [atoms C /cm2/s] +! OC 14 35 [atoms C /cm2/s] +! +! ---------------------------------------------------------------------------- +! FOR CO2 SIMULATION ONLY +! +! CO2 24 1 [molec CO2 /cm2/s] +! +! ---------------------------------------------------------------------------- +! FOR CH4 SIMULATION ONLY (kjw) +! +! CH4 25 1 [molec CH4 /cm2/s]! +! +! Module Variables: +! ============================================================================ +! (1 ) BIOMASS (REAL*8 ) : Biomass emissions [molec/cm3/s] +! (2 ) BIOMASS_SAVE (REAL*8 ) : Internal array for biomass emissions +! (3 ) BIOTRCE (INTEGER) : Index array tracer #'s for biomass species +! (4 ) IDBNOX (INTEGER) : Index for NOx in BIOMASS, BIOMASS_SAVE +! (5 ) IDBCO (INTEGER) : Index for CO in BIOMASS,c BIOMASS_SAVE +! (6 ) IDBC2H6 (INTEGER) : Index for C2H6 in BIOMASS, BIOMASS_SAVE +! (7 ) NBIOMAX (INTEGER) : Number of biomass burning species +! (8 ) NBIOMAX_GAS (INTEGER) : Number of gas-phase biomass burning species +! +! Module Routines: +! ============================================================================ +! (1 ) COMPUTE_BIOMASS_EMISSIONS : Gets biomass emissions; updates diagnostics +! (2 ) SCALE_BIOMASS_CO : applies scale factors to CO for VOC +! oxidation +! (3 ) INIT_BIOMASS : Allocates & zeroes module arrays +! (4 ) CLEANUP_BIOMASS : Deallocates module arrays +! +! GEOS-Chem modules referenced by "biomass_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for bpch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) diag_mod.f : Module w/ GEOS-CHEM diagnostic arrays +! (4 ) directory_mod.f : Module w/ GEOS-CHEM data & met field dirs +! (5 ) error_mod.f : Module w/ I/O error and NaN check routines +! (6 ) gc_biomass_mod.f : Module w/ routines for default G-C biomass +! (7 ) gfed2_biomass_mod.f : Module w/ routines for GFED2 biomass +! (8 ) gfed3_biomass_mod.f : Module w/ routines for GFED3 biomass +! (9 ) grid_mod.f : Module w/ horizontal grid information +! (10) logical_mod.f : Module w/ GEOS-CHEM logical switches +! (11) time_mod.f : Module w/ routines for computing time/ date +! +! NOTES: +! (1 ) Rewrote so that all 15 biomass species (from either GFED2 or Duncan +! et al 2001) are contained in the BIOMASS array. Also removed the +! BIOMASS_SAVE array because we no longer need to convert the data +! to [molec/cm3/s] on each timestep (bmy, 9/28/06) +! (2 ) Modification for H2/HD simulation (phs, 9/18/07) +! (3 ) Added 9 gaseous emissions from biomass burning: BENZ, TOLU, XYLE +! C2H2, C2H4, GLYX, MGLY, GLYC, HAC (tmf, 1/8/08) +! (4 ) Hard-wired IDBCO2 and BIOTRCE (tmf, 7/30/08) +! (5 ) Add CO scaling for VOC production. Routine SCALE_BIOMASS_CO +! transfered from gc_biomass_mod.f (jaf, mak, 2/6/09) +! (6 ) Updates to include GFED3 (psk, 1/5/11) +! 14 Feb 2012 - M. Payer - Add modifications for CH4 simulation (K. Wecht) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "biomass_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables + PUBLIC :: NBIOMAX + PUBLIC :: NBIOMAX_GAS + PUBLIC :: BIOMASS + PUBLIC :: BIOTRCE + PUBLIC :: IDBBC + PUBLIC :: IDBCO + PUBLIC :: IDBCO2 + PUBLIC :: IDBC2H6 + PUBLIC :: IDBNH3 + PUBLIC :: IDBNOX + PUBLIC :: IDBOC + PUBLIC :: IDBSO2 + PUBLIC :: IDBCH4 + + ! ... and these routines + PUBLIC :: CLEANUP_BIOMASS + PUBLIC :: COMPUTE_BIOMASS_EMISSIONS + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Parameters + INTEGER, PARAMETER :: NBIOMAX = 25 ! add CH4 + INTEGER, PARAMETER :: NBIOMAX_GAS = 19 + INTEGER, PARAMETER :: IDBNOX = 1 + INTEGER, PARAMETER :: IDBCO = 2 + INTEGER, PARAMETER :: IDBC2H6 = 10 + INTEGER, PARAMETER :: IDBSO2 = 11 + INTEGER, PARAMETER :: IDBNH3 = 12 + INTEGER, PARAMETER :: IDBBC = 13 + INTEGER, PARAMETER :: IDBOC = 14 + INTEGER, PARAMETER :: IDBCO2 = 24 + INTEGER, PARAMETER :: IDBCH4 = 25 + + ! Arrays + INTEGER :: BIOTRCE(NBIOMAX) + REAL*8, ALLOCATABLE :: BIOMASS(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE COMPUTE_BIOMASS_EMISSIONS( YEAR, MONTH ) +! +!****************************************************************************** +! Subroutine COMPUTE_BIOMASS_EMISSIONS is a wrapper which allows us to select +! either the GFED2 biomass burning emissions, or the regular GEOS-Chem +! biomass burning emissions (Duncan et al 2001). (psk, bmy, 4/5/06, 9/18/07) +! +! This routine is called on each timestep. At the start of a new month, +! new biomass burning emissions are read from disk. The ND28, ND29, ND32 +! diagnostics are updated on each timestep. +! +! Arguments as Input: +! ============================================================================ +! (1 ) YEAR (INTEGER) : Current year +! (2 ) MONTH (INTEGER) : Current month (1-12) +! +! NOTES: +! (1 ) Now store all biomass species in BIOMASS, from GFED2 or Duncan et al +! 2001. Also remove obsolete BIOMASS_SAVE array. (bmy, 9/28/06) +! (2 ) Reference ITS_A_H2HD_SIM from "tracer_mod.f" to deal with ND29 +! (phs, 9/18/07) +! (3 ) Now make a more general call to GFED2 reader to account for all +! four options (phs, 17/12/08) +! (4 ) Add CO scaling for VOC production (jaf, mak, 2/6/09) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : AD28, AD29, AD32_bb + USE GC_BIOMASS_MOD, ONLY : GC_COMPUTE_BIOMASS + USE GC_BIOMASS_MOD, ONLY : GC_READ_BIOMASS_BCOC + USE GC_BIOMASS_MOD, ONLY : GC_READ_BIOMASS_CO2 + USE GC_BIOMASS_MOD, ONLY : GC_READ_BIOMASS_NH3 + USE GC_BIOMASS_MOD, ONLY : GC_READ_BIOMASS_SO2 + USE GFED2_BIOMASS_MOD, ONLY : GFED2_COMPUTE_BIOMASS + USE GFED3_BIOMASS_MOD, ONLY : GFED3_COMPUTE_BIOMASS + USE LOGICAL_MOD, ONLY : LBIOMASS, LGFED2BB, LGFED3BB + USE LOGICAL_MOD, ONLY : L8DAYBB, LSYNOPBB, L3HRBB + USE LOGICAL_MOD, ONLY : LDAYBB3, L3HRBB3 + USE TIME_MOD, ONLY : ITS_A_NEW_MONTH + USE TRACER_MOD, ONLY : ITS_A_CO2_SIM + USE TRACER_MOD, ONLY : ITS_A_H2HD_SIM + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : ITS_A_TAGCO_SIM + USE TRACERID_MOD, ONLY : IDTBCPO, IDTNH3, IDTOCPO, IDTSO2 + USE TRACERID_MOD, ONLY : IDTCO + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! Diagnostic flags + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL :: DO_ND28, DO_ND29, DO_ND32 + LOGICAL, SAVE :: USE_GFED + LOGICAL, SAVE :: USE_GFED2 + LOGICAL, SAVE :: USE_GFED3 + INTEGER :: I, J, N, N_BIOB + REAL*8 :: BXHT_CM, DTSRCE + + !================================================================= + ! COMPUTE_BIOMASS_EMISSIONS begins here! + !================================================================= + + ! If there are biomass emissions ... + IF ( LBIOMASS ) THEN + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_BIOMASS + FIRST = .FALSE. + USE_GFED2 = LGFED2BB .or. L8DAYBB .or. LSYNOPBB .or. L3HRBB + USE_GFED3 = LGFED3BB .or. LDAYBB3 .or. L3HRBB3 + USE_GFED = USE_GFED2 .or. USE_GFED3 + ENDIF + + ! Define diagnostic flags + DO_ND28 = ( ND28 > 0 ) + DO_ND29 = ( ND29 > 0 ) + DO_ND32 = ( ND32 > 0 ) + + !============================================================== + ! GFED2 updates BIOMASS if needed (phs, 12/17/08) + !============================================================== + IF ( USE_GFED2 ) THEN + + ! Get emissions [molec/cm2/s] or [atoms C/cm2/s] + CALL GFED2_COMPUTE_BIOMASS( YEAR, MONTH, BIOMASS ) + + ! Irrespective of inventory type, we need to scale biomass + ! CO to account for CO production from VOC's that are not + ! explicitly carried in the chemistry mechanisms. This used + ! to be done in gc_biomass_mod.f but then is not used for + ! GFED2, FLAMBE, etc. (jaf, mak, 2/6/09) + ! + ! Now make sure IDBCO is defined before using it. This will + ! avoid an out-of-bounds error. (bmy, 7/29/11) + IF ( IDBCO > 0 ) THEN + IF ( ITS_A_FULLCHEM_SIM() ) THEN + BIOMASS(:,:,IDBCO) = BIOMASS(:,:,IDBCO) * 1.05d0 + ELSE IF ( ITS_A_TAGCO_SIM() ) THEN + BIOMASS(:,:,IDBCO) = BIOMASS(:,:,IDBCO) * 1.11d0 + ENDIF + ENDIF + + !============================================================== + ! GFED3 updates BIOMASS if needed (psk, 1/5/11) + !============================================================== + ELSE IF ( USE_GFED3 ) THEN + + ! Get emissions [molec/cm2/s] or [atoms C/cm2/s] + CALL GFED3_COMPUTE_BIOMASS( YEAR, MONTH, BIOMASS ) + + ! Irrespective of inventory type, we need to scale biomass + ! CO to account for CO production from VOC's that are not + ! explicitly carried in the chemistry mechanisms. This used + ! to be done in gc_biomass_mod.f but then is not used for + ! GFED3, FLAMBE, etc. (jaf, mak, 2/6/09) + IF ( ITS_A_FULLCHEM_SIM() ) THEN + BIOMASS(:,:,IDBCO) = BIOMASS(:,:,IDBCO) * 1.05d0 + ELSE IF ( ITS_A_TAGCO_SIM() ) THEN + print*, 'scale bb by 11%' + BIOMASS(:,:,IDBCO) = BIOMASS(:,:,IDBCO) * 1.11d0 + ENDIF + + !============================================================== + ! Read GC biomass emissions at the start of a new month + !============================================================== + ELSE IF ( ITS_A_NEW_MONTH() ) THEN + + ! Zero the array for biomass burning + BIOMASS = 0d0 +!---------------------------------------------------------------------- +! prior 12/17/08 (phs) +! Now test for GFED2 above +! ! Test for type of biomass emissions +! IF ( LGFED2BB ) THEN +! +! !--------------------------------- +! ! GFED2 biomass inventory for +! ! gas-phase, aerosols, and CO2 +! !--------------------------------- +! +! ! Get emissions [molec/cm2/s] or [atoms C/cm2/s] +! CALL GFED2_COMPUTE_BIOMASS( YEAR, MONTH, BIOMASS ) +! +! ELSE +!---------------------------------------------------------------------- + ! Test if it's a CO2 simulation + IF ( ITS_A_CO2_SIM() ) THEN + + !------------------------------ + ! CO2 emissions (based on + ! Duncan et al 2001 CO) + !------------------------------ + + ! Get CO2 emissions [molec/cm2/s] + CALL GC_READ_BIOMASS_CO2( YEAR, MONTH, + & BIOMASS(:,:,IDBCO2) ) + ELSE + + !------------------------------ + ! Default GEOS-Chem inventory + ! (Bryan Duncan et al 2001) + !------------------------------ + + ! Get emissions of gas-phase species + ! in [molec/cm2/s] or [atoms C/cm2/s] + CALL GC_COMPUTE_BIOMASS( YEAR, MONTH, + & BIOMASS(:,:,1:NBIOMAX_GAS) ) + + ! Get biomass SO2 [molec/cm2/s] + IF ( IDTSO2 > 0 ) THEN + CALL GC_READ_BIOMASS_SO2( YEAR, MONTH, + & BIOMASS(:,:,IDBSO2) ) + ENDIF + + ! Get biomass NH3 [molec/cm2/s] + IF ( IDTNH3 > 0 ) THEN + CALL GC_READ_BIOMASS_NH3( YEAR, MONTH, + & BIOMASS(:,:,IDBNH3) ) + ENDIF + + ! Get biomass BC & OC [molec/cm2/s] + IF ( IDTBCPO > 0 .and. IDTOCPO > 0 ) THEN + CALL GC_READ_BIOMASS_BCOC( YEAR, MONTH, + & BIOMASS(:,:,IDBBC), + & BIOMASS(:,:,IDBOC) ) + ENDIF + ENDIF +! ENDIF + + ! Irrespective of inventory type, we need to scale biomass + ! CO to account for CO production from VOC's that are not + ! explicitly carried in the chemistry mechanisms. This used + ! to be done in gc_biomass_mod.f but then is not used for + ! GFED2, FLAMBE, etc. (jaf, mak, 2/6/09) + IF ( ITS_A_FULLCHEM_SIM() ) THEN + BIOMASS(:,:,IDBCO) = BIOMASS(:,:,IDBCO)*1.05d0 + ELSE IF ( ITS_A_TAGCO_SIM() ) THEN + BIOMASS(:,:,IDBCO) = BIOMASS(:,:,IDBCO)*1.11d0 + ENDIF + + ENDIF + + !============================================================== + ! Do the following on every timestep: + ! + ! ND28, ND29, ND32 diags [molec/cm2/s] or [atoms C/cm2/s] + !============================================================== +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, N ) + DO N = 1, NBIOMAX + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! ND28: biomass emissions in [molec/cm2/s] + IF ( DO_ND28 ) THEN + AD28(I,J,N) = AD28(I,J,N) + BIOMASS(I,J,N) + ENDIF + + ! ND29: CO biomass emissions [molec/cm2/s] + IF ( DO_ND29 .and. N == IDBCO ) THEN +!---------------------------------------------------------------------- +! prior 1/5/09 (phs) +! IF ( ITS_A_H2HD_SIM() .and. (.not. LGFED2BB ) ) THEN + IF ( ITS_A_H2HD_SIM() .and. (.not. USE_GFED ) ) THEN + AD29(I,J,2) = AD29(I,J,2) + + & BIOMASS(I,J,IDBCO) * 1.11d0 + ELSE + AD29(I,J,2) = AD29(I,J,2) + BIOMASS(I,J,IDBCO) + ENDIF + ENDIF + + ! ND32: NOx biomass emissions in [molec/cm2/s] + IF ( DO_ND32 .and. N == IDBNOx ) THEN + AD32_bb(I,J) = AD32_bb(I,J) + BIOMASS(I,J,IDBNOx) + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + ! Return to calling program + END SUBROUTINE COMPUTE_BIOMASS_EMISSIONS + +!------------------------------------------------------------------------------ + + SUBROUTINE SCALE_BIOMASS_CO( BBARRAY ) +! +!****************************************************************************** +! Subroutine SCALE_BIOMASS_CO multiplies the CO biomass emissions by scale +! factors to account for CO production from VOC's that are not explicitly +! carried in the chemistry mechanisms. (bnd, bmy, 8/21/01, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) BBARRAY (REAL*8) : Array containing biomass burning CO emissions +! +! NOTES: +! (1 ) Scale factors were determined by Jennifer Logan (jal@io.harvard.edu), +! Bryan Duncan (bnd@io.harvard.edu) and Daniel Jacob (djj@io.harvard.edu) +! (2 ) Scale factors have been corrected to 5% and 11% (bnd, bmy, 8/21/01) +! (3 ) BBARRAY is now dimensioned (IIPAR,JJPAR) (bmy, 9/28/01) +! (4 ) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (5 ) Now references ITS_A_FULLCHEM_SIM, ITS_A_TAGCO_SIM from "tracer_mod.f" +! (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM, ITS_A_TAGCO_SIM + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: BBARRAY(IIPAR,JJPAR) + + !================================================================= + ! SCALE_BIOMASS_CO begins here! + !================================================================= + IF ( ITS_A_FULLCHEM_SIM() ) THEN + + ! Full chemistry w/ SMVGEAR -- enhance by 5% + BBARRAY = BBARRAY * 1.05d0 + + ELSE IF ( ITS_A_TAGCO_SIM() ) THEN + + ! Tagged CO -- enhance by 11% + BBARRAY = BBARRAY * 1.11d0 + + ENDIF + + ! Return to calling program + END SUBROUTINE SCALE_BIOMASS_CO + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_BIOMASS +! +!****************************************************************************** +! Subroutine INIT_BIOMASS allocates and zeroes the module arrays. +! (bmy, 4/5/06, 9/28/06) +! +! NOTES: +! (1 ) Now set BIOTRCE for 15 biomass species (bmy, 9/28/06) +! (2 ) Now remove BIOMASS_SAVE array, it's redundant (bmy, 9/28/06) +! (3 ) Now set BIOTRCE for 24 biomass species (tmf, 7/30/08) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LBIOMASS + +# include "CMN_SIZE" ! Size parameters + + INTEGER :: AS + + !================================================================= + ! INIT_BIOMASS begins here! + !================================================================= + + ! If there are biomass emissions ... + IF ( LBIOMASS ) THEN + + ! Tracer numbers for each biomass species (CO2 is last) + ! IDBCH4 is placed at end after all full chem tracers and CO2 + BIOTRCE(:) = (/ 1, 4, 5, 9, 10, 11, 18, + & 19, 20, 21, 26, 30, 34, 35, + & 55, 56, 57, 58, 59, 63, 64, + & 66, 67, 1, 1 /) + + ! Allocate array to hold monthly biomass emissions + ALLOCATE( BIOMASS( IIPAR, JJPAR, NBIOMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BIOMASS' ) + BIOMASS = 0d0 + + ENDIF + + ! Return to calling program + END SUBROUTINE INIT_BIOMASS + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_BIOMASS +! +!****************************************************************************** +! Subroutine CLEANUP_BIOMASS deallocates all module arrays. +! (psk, bmy, 4/5/06, 9/28/06) +! +! NOTES: +! (1 ) Now remove BIOMASS_SAVE array, it's redundant (bmy, 9/28/06) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_BIOMASS begins here! + !================================================================= + IF ( ALLOCATED( BIOMASS ) ) DEALLOCATE( BIOMASS ) + + ! Return to calling program + END SUBROUTINE CLEANUP_BIOMASS + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE BIOMASS_MOD diff --git a/code/boxvl.f b/code/boxvl.f new file mode 100644 index 0000000..267aa92 --- /dev/null +++ b/code/boxvl.f @@ -0,0 +1,33 @@ +! $Id: boxvl.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + REAL*8 FUNCTION BOXVL (I,J,L) +! +!***************************************************************************** +! The new function BOXVL converts the DAO grid box volume values stored +! in AIRVOL from m^3 to cm^3. The conversion factor is (100)^3 = 10^6 +! cm^3 per m^3. (bmy, 1/30/98, 8/5/02) +! +! NOTES: +! (1 ) CMN_VOL is used to pass AIRVOL. +! (2 ) Use C-preprocessor #include statement to include CMN_SIZE, which +! has IIPAR, JJPAR, LLPAR, IGLOB, JGLOB, LGLOB. +! (3 ) Now use F90 syntax for declarations (bmy, 10/5/99) +! (4 ) Now reference AIRVOL from "dao_mod.f" instead of from common +! block header file "CMN_VOL". (bmy, 6/26/00) +! (5 ) Removed obsolete code from 6/26/00 (bmy, 8/31/00) +! (6 ) Updated comments (bmy, 8/5/02) +!***************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AIRVOL + + IMPLICIT NONE + + ! Arguments + INTEGER, INTENT(IN) :: I, J, L + + ! BOXVL begins here! + BOXVL = AIRVOL(I,J,L) * 1d6 + + ! Return to calling program + END FUNCTION BOXVL + diff --git a/code/bravo_mod.f b/code/bravo_mod.f new file mode 100644 index 0000000..55b2ec5 --- /dev/null +++ b/code/bravo_mod.f @@ -0,0 +1,676 @@ +! $Id: bravo_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: BRAVO_MOD +! +! !DESCRIPTION: \subsection*{Overview} +! Module BRAVO\_MOD contains variables and routines to read the BRAVO +! Mexican anthropogenic emission inventory for NOx, CO, and SO2. +! (rjp, kfb, bmy, 6/22/06, 1/30/09) +! +! \subsection*{References} +! \begin{enumerate} +! \item Kuhns, H., M. Green, and Etyemezian, V, \emph{Big Bend Regional +! Aerosol and Visibility Observational (BRAVO) Study Emissions +! Inventory}, Desert Research Institute, 2003. +! \end{enumerate} +! +! !INTERFACE: +! + MODULE BRAVO_MOD +! +! !USES: +! + IMPLICIT NONE + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: CLEANUP_BRAVO + PUBLIC :: EMISS_BRAVO + PUBLIC :: GET_BRAVO_MASK + PUBLIC :: GET_BRAVO_ANTHRO +! +! !PRIVATE MEMBER FUNCTIONS: +! + PRIVATE :: BRAVO_SCALE_FUTURE + PRIVATE :: INIT_BRAVO + PRIVATE :: READ_BRAVO_MASK +! +! !REVISION HISTORY: +! (1 ) Now pass the unit string to DO_REGRID_G2G_1x1 (bmy, 8/9/06) +! (2 ) Now scale emissions using int-annual scale factors (amv, 08/24/07) +! (3 ) Now accounts for FSCLYR (phs, 3/17/08) +! (4 ) Added ProTeX headers (bmy, 1/30/09) +!EOP +!------------------------------------------------------------------------------ +! +! !PRIVATE DATA MEMBERS: +! + ! Arrays + REAL*8, ALLOCATABLE :: BRAVO_MASK(:,:) + REAL*8, ALLOCATABLE :: BRAVO_NOx(:,:) + REAL*8, ALLOCATABLE :: BRAVO_CO(:,:) + REAL*8, ALLOCATABLE :: BRAVO_SO2(:,:) + + CONTAINS + +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: GET_BRAVO_MASK +! +! !DESCRIPTION: Function GET\_BRAVO\_MASK returns the value of the Mexico +! mask for BRAVO emissions at grid box (I,J). MASK=1 if (I,J) is in the +! BRAVO Mexican region, or MASK=0 otherwise. (rjp, kfb, bmy, 6/22/06) +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_BRAVO_MASK( I, J ) RESULT( MASK ) +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: I ! Longitude index + INTEGER, INTENT(IN) :: J ! Latitude index +! +! !RETURN VALUE: +! + REAL*8 :: MASK ! Returns the mask value @ (I,J) +! +! !REVISION HISTORY: +! 22 Jun 2006 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! GET_BRAVO_MASK begins here! + !================================================================= + MASK = BRAVO_MASK(I,J) + + ! Return to calling program + END FUNCTION GET_BRAVO_MASK +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: GET_BRAVO_ANTHRO +! +! !DESCRIPTION: Function GET\_BRAVO\_ANTHRO returns the BRAVO emission +! for GEOS-Chem grid box (I,J) and tracer N. Units are [molec/cm2/s]. +! (rjp, kfb, bmy, 6/22/06) +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_BRAVO_ANTHRO( I, J, N ) RESULT( BRAVO ) +! +! !USES: +! + USE TRACERID_MOD, ONLY : IDTNOX, IDTCO, IDTSO2 +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: I ! Longitude index + INTEGER, INTENT(IN) :: J ! Latitude index + INTEGER, INTENT(IN) :: N ! Tracer number +! +! RETURN VALUE: +! + REAL*8 :: BRAVO ! Returns emissions at (I,J) +! +! !REVISION HISTORY: +! (1 ) added SOx, SOx ship and NH3 emissions, plus optional kg/s output +! (amv, 06/2008) +! (2 ) Now returns ship emissions if requested (phs, 6/08) +! (3 ) Added checks to avoid calling unavailable ship emissions (phs, 6/08) +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! GET_BRAVO_ANTHRO begins here! + !================================================================= + + ! NOx + IF ( N == IDTNOX ) THEN + BRAVO = BRAVO_NOx(I,J) + + ! CO + ELSE IF ( N == IDTCO ) THEN + BRAVO = BRAVO_CO(I,J) + + ! SO2 + ELSE IF ( N == IDTSO2 ) THEN + BRAVO = BRAVO_SO2(I,J) + + ! Otherwise return a negative value to indicate + ! that there are no BRAVO emissions for tracer N + ELSE + BRAVO = -1d0 + + ENDIF + + ! Return to calling program + END FUNCTION GET_BRAVO_ANTHRO +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: EMISS_BRAVO +! +! !DESCRIPTION: Subroutine EMISS\_BRAVO reads the BRAVO emission fields at 1x1 +! resolution and regrids them to the current model resolution. +! (rjp, kfb, bmy, 6/22/06, 8/9/06) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_BRAVO +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE LOGICAL_MOD, ONLY : LFUTURE + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1, DO_REGRID_G2G_1x1 + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_1x1 + USE TIME_MOD, ONLY : GET_YEAR + +# include "CMN_SIZE" ! Size parameters +# include "CMN_O3" ! +! +! !REVISION HISTORY: +! (1 ) Now pass the unit string to DO_REGRID_G2G_1x1 (bmy, 8/9/06) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: SCALEYEAR + REAL*4 :: ARRAY(I1x1,J1x1-1,1) + REAL*8 :: GEN_1x1(I1x1,J1x1-1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + REAL*8 :: SC_1x1(I1x1,J1x1) + REAL*8 :: TAU0 + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! EMISS_BRAVO begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_BRAVO + FIRST = .FALSE. + ENDIF + + !================================================================= + ! Read data from disk + !================================================================= + + ! Use 1999 for BRAVO emission files (BASE YEAR) + TAU0 = GET_TAU0( 1, 1, 1999 ) + + ! Get emissions year + IF ( FSCALYR < 0 ) THEN + SCALEYEAR = GET_YEAR() + ELSE + SCALEYEAR = FSCALYR + ENDIF + + !--------------------- + ! Read and regrid NOx + !--------------------- + + ! 1x1 file name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'BRAVO_200607/BRAVO.NOx.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - EMISS_BRAVO: Reading ', a ) + + ! Read NOx [molec/cm2/s] on GENERIC 1x1 GRID + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 1, + & TAU0, I1x1, J1x1-1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 + GEN_1x1(:,:) = ARRAY(:,:,1) + + ! Regrid NOx [molec/cm2/s] to GEOS 1x1 GRID + CALL DO_REGRID_G2G_1x1( 'molec/cm2/s', GEN_1x1, GEOS_1x1(:,:,1) ) + + ! Get/Apply annual scalar factor (amv 08/21/2007) + CALL GET_ANNUAL_SCALAR_1x1( 71, 1999, SCALEYEAR, SC_1x1 ) + GEOS_1x1(:,:,1) = GEOS_1x1(:,:,1) * SC_1x1(:,:) + + ! Regrid NOx [molec/cm2/s] to current model resolution + CALL DO_REGRID_1x1( 'molec/cm2/s', GEOS_1x1, BRAVO_NOx ) + + !--------------------- + ! Read and regrid CO + !--------------------- + + ! 1x1 file name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'BRAVO_200607/BRAVO.CO.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read CO [molec/cm2/s] on GENERIC 1x1 GRID + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 4, + & TAU0, I1x1, J1x1-1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 + GEN_1x1(:,:) = ARRAY(:,:,1) + + ! Regrid CO [molec/cm2/s] to GEOS 1x1 GRID + CALL DO_REGRID_G2G_1x1( 'molec/cm2/s', GEN_1x1, GEOS_1x1(:,:,1) ) + + ! Get/Apply annual scalar factor (amv 08/21/2007) + CALL GET_ANNUAL_SCALAR_1x1( 72, 1999, SCALEYEAR, SC_1x1 ) + GEOS_1x1(:,:,1) = GEOS_1x1(:,:,1) * SC_1x1(:,:) + + ! Regrid CO [molec/cm2/s] to current model resolution + CALL DO_REGRID_1x1( 'molec/cm2/s', GEOS_1x1, BRAVO_CO ) + + !--------------------- + ! Read and regrid SO2 + !--------------------- + + ! 1x1 file name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'BRAVO_200607/BRAVO.SO2.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read SO2 [molec/cm2/s] on GENERIC 1x1 GRID + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 26, + & TAU0, I1x1, J1x1-1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 + GEN_1x1(:,:) = ARRAY(:,:,1) + + ! Regrid SO2 [molec/cm2/s] to GEOS 1x1 GRID + CALL DO_REGRID_G2G_1x1( 'molec/cm2/s', GEN_1x1, GEOS_1x1(:,:,1) ) + + ! Get/Apply annual scalar factor (amv 08/21/2007) + CALL GET_ANNUAL_SCALAR_1x1( 73, 1999, SCALEYEAR, SC_1x1 ) + GEOS_1x1(:,:,1) = GEOS_1x1(:,:,1) * SC_1x1(:,:) + + ! Regrid SO2 [molec/cm2/s] to current model resolution + CALL DO_REGRID_1x1( 'molec/cm2/s', GEOS_1x1, BRAVO_SO2 ) + + !================================================================= + ! Compute IPCC future emissions (if necessary) + !================================================================= + IF ( LFUTURE ) THEN + CALL BRAVO_SCALE_FUTURE + ENDIF + + !================================================================= + ! Print emission totals + !================================================================= + CALL TOTAL_ANTHRO_TG( SCALEYEAR ) + + ! Return to calling program + END SUBROUTINE EMISS_BRAVO +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: BRAVO_SCALE_FUTURE +! +! !DESCRIPTION: Subroutine BRAVO\_SCALE\_FUTURE applies the IPCC future +! scale factors to the BRAVO anthropogenic emissions. (swu, bmy, 5/30/06) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE BRAVO_SCALE_FUTURE +! +! !USES: +! + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_COff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2ff + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 30 May 2006 - S. Wu & R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + + !================================================================= + ! BRAVO_SCALE_FUTURE begins here! + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Future NOx [molec/cm2/s] + BRAVO_NOx(I,J) = BRAVO_NOx(I,J) * + & GET_FUTURE_SCALE_NOxff( I, J ) + + ! Future CO [molec/cm2/s] + BRAVO_CO(I,J) = BRAVO_CO(I,J) * + & GET_FUTURE_SCALE_COff( I, J ) + + ! Future ALK4 [atoms C/cm2/s] + BRAVO_SO2(I,J) = BRAVO_SO2(I,J) * + & GET_FUTURE_SCALE_SO2ff( I, J ) + + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE BRAVO_SCALE_FUTURE +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: TOTAL_ANTHRO_TG +! +! !DESCRIPTION: Subroutine TOTAL\_ANTHRO\_TG prints the amount of BRAVO +! anthropogenic emissions that are emitted each year. +! (rjp, kfb, bmy, 6/26/06) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE TOTAL_ANTHRO_TG( YEAR ) +! +! !USES: +! + ! References to F90 modules + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE TRACERID_MOD, ONLY : IDTNOX, IDTCO, IDTSO2 + +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: YEAR +! +! !REVISION HISTORY: +! (1 ) Now YEAR is input to reflect scaling factors applied (phs, 3/17/08) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + REAL*8 :: A, B(3), NOx, CO, SO2 + CHARACTER(LEN=3) :: UNIT + + !================================================================= + ! TOTAL_ANTHRO_TG begins here! + !================================================================= + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 100 ) + 100 FORMAT( 'B R A V O M E X I C A N E M I S S I O N S', /, + & 'Base year : 1999' ) + + !---------------- + ! Sum emissions + !---------------- + + ! Define conversion factors for kg/molec + ! (Undefined tracers will be zero) + B(:) = 0d0 + IF ( IDTNOx > 0 ) B(1) = 1d0 / ( 6.0225d23 / 14d-3 ) ! Tg N + IF ( IDTCO > 0 ) B(2) = 1d0 / ( 6.0225d23 / 28d-3 ) ! Tg CO + IF ( IDTSO2 > 0 ) B(3) = 1d0 / ( 6.0225d23 / 32d-3 ) ! Tg S + + ! Summing variables + NOX = 0d0 + CO = 0d0 + SO2 = 0d0 + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Convert [molec/cm2/s] to [Tg] + ! (Multiply by 1d-9 to convert from [kg] to [Tg]) + A = GET_AREA_CM2( J ) * 365.25d0 * 86400d0 * 1d-9 + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Sum emissions (list NOx as Tg N) + NOX = NOX + ( BRAVO_NOX(I,J) * A * B(1) ) + CO = CO + ( BRAVO_CO (I,J) * A * B(2) ) + SO2 = SO2 + ( BRAVO_SO2(I,J) * A * B(3) ) + ENDDO + ENDDO + + !---------------- + ! Print sums + !---------------- + + ! Print totals in [kg] + WRITE( 6, 110 ) 'NOx ', YEAR, NOx, ' N' + WRITE( 6, 110 ) 'CO ', YEAR, CO, ' ' + WRITE( 6, 110 ) 'SO2 ', YEAR, SO2, ' S' + + 110 FORMAT( 'BRAVO anthropogenic ', a4, + & 'for year ', i4, ': ', f9.4, ' Tg', a2 ) + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! Return to calling program + END SUBROUTINE TOTAL_ANTHRO_TG +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: READ_BRAVO_MASK +! +! !DESCRIPTION: Subroutine READ\_BRAVO\_MASK reads the Mexico mask from +! disk. The Mexico mask is the fraction of the grid box (I,J) which lies +! w/in the BRAVO Mexican emissions region. (rjp, kfb, bmy, 6/22/06, 8/9/06) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_BRAVO_MASK +! +! !USES: +! + 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 REGRID_1x1_MOD, ONLY : DO_REGRID_1x1, DO_REGRID_G2G_1x1 + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! (1 ) Now pass UNIT to DO_REGRID_G2G_1x1 (bmy, 8/9/06) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(I1x1,J1x1-1,1) + REAL*8 :: GEN_1x1(I1x1,J1x1-1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + REAL*8 :: XTAU + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_BRAVO_MASK begins here! + !================================================================= + + ! File name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'BRAVO_200607/BRAVO.MexicoMask.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_MEXICO_MASK: Reading ', a ) + + ! Get TAU0 for Jan 1985 + XTAU = GET_TAU0( 1, 1, 1999 ) + + ! Mask is stored in the bpch file as #2 + CALL READ_BPCH2( FILENAME, 'LANDMAP', 2, + & XTAU, I1x1, J1x1-1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 + GEN_1x1(:,:) = ARRAY(:,:,1) + + ! Regrid from GENERIC 1x1 GRID to GEOS 1x1 GRID + CALL DO_REGRID_G2G_1x1( 'unitless', GEN_1x1, GEOS_1x1(:,:,1) ) + + ! Regrid from GEOS 1x1 GRID to current model resolution + CALL DO_REGRID_1x1( 'unitless', GEOS_1x1, BRAVO_MASK ) + + ! Return to calling program + END SUBROUTINE READ_BRAVO_MASK +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: INIT_BRAVO +! +! !DESCRIPTION: Subroutine INIT\_BRAVO allocates and zeroes BRAVO module +! arrays, and also creates the mask which defines the Mexico region +! (rjp, kfb, bmy, 6/26/06) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE INIT_BRAVO +! +! !USES: +! + USE ERROR_MOD, ONLY : ALLOC_ERR + USE GRID_MOD, ONLY : GET_XMID, GET_YMID + USE LOGICAL_MOD, ONLY : LBRAVO + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 18 Oct 2006 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: AS + + !================================================================= + ! INIT_BRAVO begins here! + !================================================================= + + ! Return if LBRAVO is false + IF ( .not. LBRAVO ) RETURN + + !-------------------------- + ! Allocate and zero arrays + !-------------------------- + + ALLOCATE( BRAVO_NOx( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BRAVO_NOx' ) + BRAVO_NOx = 0d0 + + ALLOCATE( BRAVO_CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BRAVO_CO' ) + BRAVO_CO = 0d0 + + ALLOCATE( BRAVO_SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BRAVO_SO2' ) + BRAVO_SO2 = 0d0 + + !-------------------------- + ! Read Mexico mask + !-------------------------- + + ALLOCATE( BRAVO_MASK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'BRAVO_MASK' ) + BRAVO_MASK = 0d0 + + ! Read the mask + CALL READ_BRAVO_MASK + + ! Return to calling program + END SUBROUTINE INIT_BRAVO +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: CLEANUP_BRAVO +! +! !DESCRIPTION: Subroutine CLEANUP\_BRAVO deallocates all BRAVO module arrays. +! (rjp, kfb, bmy, 6/26/06) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE CLEANUP_BRAVO +! +! !REVISION HISTORY: +! 1 Nov 2005 - R. Yantosca - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! CLEANUP_BRAVO begins here! + !================================================================= + IF ( ALLOCATED( BRAVO_NOx ) ) DEALLOCATE( BRAVO_NOx ) + IF ( ALLOCATED( BRAVO_CO ) ) DEALLOCATE( BRAVO_CO ) + IF ( ALLOCATED( BRAVO_SO2 ) ) DEALLOCATE( BRAVO_SO2 ) + IF ( ALLOCATED( BRAVO_MASK ) ) DEALLOCATE( BRAVO_MASK ) + + ! Return to calling program + END SUBROUTINE CLEANUP_BRAVO + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE BRAVO_MOD +!EOC diff --git a/code/build b/code/build new file mode 100644 index 0000000..78145ff --- /dev/null +++ b/code/build @@ -0,0 +1,153 @@ +#!/usr/bin/perl -w + +# $Id: build,v 1.1 2009/06/09 21:51:53 daven Exp $ + +=head1 NAME + +BUILD + +=head1 SYNOPSIS + +BUILD is a Perl script which compiles the GEOS-CHEM code +for a given combination of platform and compiler. + +=head1 REQUIRES + +Perl 5.003 + +=head1 EXPORTS + +none + +=head1 DESCRIPTION + +build +Methods are provided for compiling the GEOS-CHEM model + +=head1 METHODS + +getMakeFile : Prints a separator line to stdout +main : Driver program + +=head1 MODIFICATION HISTORY + +bmy, 04 Dec 2002 - INITIAL VERSION +bmy, 03 Nov 2005 - Modified for Intel "ifort" compiler +bmy, 29 Nov 2005 - Now use "and" instead of double ampersands + +=head1 AUTHOR + +Bob Yantosca (bmy@io.harvard.edu) + +=head1 SEE ALSO + +trun, bmrun + +=head1 COPYRIGHT + +Copyright 2002-2005, Bob Yantosca. All rights reserved. + +=cut + +require 5.003; # need this version of Perl or newer +use English; # English language module +use Carp; # detailed error msgs +use strict; # forces implicit variable declarations + +#------------------------------------------------------------------------------ + +sub getMakeFile() { + + #========================================================================= + # Subroutine getMakeFile examines the "define.h" file in order to + # determine the name of the makefile which will be used to compile + # GEOS-CHEM for the given platform and compiler. (bmy, 12/4/03, 11/3/05) + # + # Calling Sequence: + # ------------------------------------------------------------------------ + # $makeFile = getMakeFile(); + # + # NOTES: + # (1 ) Now searches for Intel "ifort" compiler makefile "Makefile.ifort + # if LINUX_IFORT switch is #defined. (bmy, 11/3/05) + #========================================================================= + + # Local variables + my $line = ""; + my @lines = ""; + + # Read "define.h" into a string array + open( INPUT, "define.h" ) or croak "getDefaults: Can't open define.h"; + chomp( @lines = ); + close( INPUT ); + + # Process each line individually + foreach $line ( @lines ) { + + # Determine makefile name from the defined C-preprocessor switch + if ( $line =~ "#define" and !( $line =~ "!#define" ) ) { + if ( $line =~ "COMPAQ" ) { return( "Makefile.compaq" ); } + elsif ( $line =~ "IBM" ) { return( "Makefile.ibm" ); } + elsif ( $line =~ "LINUX_PGI" ) { return( "Makefile.pgi" ); } + elsif ( $line =~ "LINUX_IFC" ) { return( "Makefile.ifc" ); } + elsif ( $line =~ "LINUX_EFC" ) { return( "Makefile.efc" ); } + elsif ( $line =~ "LINUX_IFORT" ) { return( "Makefile.ifort" ); } + elsif ( $line =~ "LINUX" ) { return( "Makefile.linux" ); } + elsif ( $line =~ 'SGI' ) { return( "Makefile.sgi" ); } + elsif ( $line =~ 'SPARC' ) { return( "Makefile.sparc" ); } + } + } + + # Otherwise return failure + return( '' ); +} + +#------------------------------------------------------------------------------ + +sub main() { + + #========================================================================= + # Perl script "build" compiles GEOS-CHEM with the correct makefile for + # a given operating system and compiler. Examines the "define.h" file + # in order to determine the makefile name. (bmy, 12/4/03) + # + # Arguments as Input: + # ------------------------------------------------------------------------ + # (1 ) $target : Name of the makefile target to build (default is "geos") + # + # NOTES: + # (1 ) Need to set system variables for Intel IFORT compiler (bmy, 11/3/05) + # (2 ) Now use "and" to avoid conflict w/ the sub mit command (bmy, 11/18/05) + #========================================================================== + + # Local variables + my $makeFile = ""; + my $target = "geos"; + + # If an argument has been passed, then redefine $target + if ( scalar( @ARGV ) > 0 ) { $target = $ARGV[0]; } + + # Get the makefile name by examining "define.h" + $makeFile = getMakeFile(); + + # Compile GEOS-CHEM w/ the right makefile + if ( length( $makeFile ) > 0 ) { + print "Compiling $target in $makeFile\n"; + + # Need to set system variables for Intel IFORT compiler (bmy, 11/3/05) + #if ( $makeFile =~ "ifort" and !( $target =~ "clean" ) ) + # { qx( source /usr/local/bin/ifortvars.sh; make $target -f $makeFile ); } + #else + # { qx( make $target -f $makeFile ); } + qx( make $target -f $makeFile ); + + } else { die "Could not find makefile name!\n" } +} + +#------------------------------------------------------------------------------ + +# Execute MAIN program +main(); + +# Exit normally +exit(0); diff --git a/code/c2h6_mod.f b/code/c2h6_mod.f new file mode 100644 index 0000000..a17d00a --- /dev/null +++ b/code/c2h6_mod.f @@ -0,0 +1,523 @@ +! $Id: c2h6_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE C2H6_MOD +! +!****************************************************************************** +! Module C2H6_MOD contains variables and routines used for the tagged +! C2H6 (ethane) simulation. (xyp, qli, bmy, 7/28/01, 4/5/06) +! +! Setting LSPLIT = T in "input.geos" will run with the following tracers: +! (1) Total C2H6 +! (2) C2H6 from biomass burning +! (3) C2H6 from biofuel burning +! (4) C2H6 from natural gas leaking/venting (e.g. "anthro" C2H6) +! +! Setting LSPLIT = F in "input.geos" will run w/ the following tracers: +! (1) Total C2H6 +! +! Module Variables: +! ============================================================================ +! (1 ) NGASC2H6 : Array to store C2H6 emissions from natural gas +! (2 ) FMOL_C2H6 : Molecular weight of C2H6 [kg/mole] +! (3 ) XNUMOL_C2H6 : Ratio of molecules C2H6 per kg C2H6 +! +! Module Procedures: +! ============================================================================ +! (1 ) EMISSC2H6 : Routine that performs emission of C2H6 tracers +! (2 ) CHEMC2H6 : Routine that performs chemistry for C2H6 tracers +! (3 ) INIT_NGAS +! +! GEOS-Chem modules referenced by "c2h6_mod.f" +! ============================================================================ +! (1 ) biofuel_mod.f : Module containing routines to read biofuel emissions +! (2 ) biomass_mod.f : Module containing routines to read biomass emissions +! (3 ) dao_mod.f : Module containing arrays for DAO met fields! +! (4 ) diag_mod.f : Module containing GEOS-CHEM diagnostic arrays +! (5 ) error_mod.f : Module containing NaN and other error check routines +! (6 ) geia_mod.f : Module containing routines to read anthro emissions +! (7 ) grid_mod.f : Module containing horizontal grid information +! (8 ) global_oh_mod.f : Module containing routines to read 3-D OH field +! (9 ) time_mod.f : Module containing routines to compute date & time +! (10) tracerid_mod.f : Module containing pointers to tracers and emissions +! (11) transfer_mod.f : Module containing routines to cast and resize arrays +! +! NOTES: +! (1 ) Eliminated obsolete code from 1/02 (bmy, 2/27/02) +! (2 ) Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Updated comments (bmy, 5/28/02) +! (3 ) Now reference BXHEIGHT and T from "dao_mod.f". Also references +! "error_mod.f". Removed obsolete code. Now references F90 module +! tracerid_mod.f". (bmy, 11/15/02) +! (4 ) Now references "grid_mod.f" and the new "time_mod.f" (bmy, 2/11/03) +! (5 ) Now references "directory_mod.f", "logical_mod.f", and "tracer_mod.f". +! (bmy, 7/20/04) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) Now modified +!****************************************************************************** +! + IMPLICIT NONE + +# include "define.h" + + ! PUBLIC module variables + PUBLIC :: GET_C2H6_ANTHRO + + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "c2h6_mod.f" + !================================================================= + + ! PRIVATE module variables + PRIVATE NGASC2H6 + PRIVATE FMOL_C2H6 + PRIVATE XNUMOL_C2H6 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Array to store global monthly mean natural gas C2H6 emissions + REAL*8, ALLOCATABLE :: NGASC2H6(:,:) + + ! FMOL_C2H6: molecular weight of C2H6 [kg/mole] + REAL*8, PARAMETER :: FMOL_C2H6 = 30d-3 + + ! XNUMOL_C2H6 ratio of [molec C2H6/kg C2H6] + REAL*8, PARAMETER :: XNUMOL_C2H6 = 6.022d+23/FMOL_C2H6 + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE EMISSC2H6 +! +!****************************************************************************** +! Subroutine EMISSC2H6 reads in C2H6 emissions for the Tagged C2H6 run. +! (xyp, qli, bmy, 7/21/00, 4/5/06) +! +! NOTES: +! (1 ) BURNEMIS and BIOFUEL are now dimensioned with IIPAR,JJPAR instead of +! IGLOB,JGLOB. Remove BXHEIGHT from the arg list, since ND28 and ND36 +! diags are archived in BIOBURN and BIOFUEL_BURN. Now use routine +! TRANSFER_2D from "transfer_mod.f" to cast from REAL*4 to REAL*8. +! Now print emission totals for C2H6 emissions to stdout. (bmy, 1/25/02) +! (2 ) Eliminated obsolete code from 1/02 (bmy, 2/27/02) +! (3 ) Now references IDBC2H6 etc from "tracerid_mod.f". Now make FIRSTEMISS +! a local SAVEd variable instead of an argument. (bmy, 11/15/02) +! (4 ) Now use GET_AREA_CM2 from "grid_mod.f" to get grid box surface +! area in cm2. Remove references to DXYP. Use routines GET_MONTH +! and GET_TS_EMIS from "time_mod.f". Remove MONTH from call to +! BIOBURN. (bmy, 2/11/03) +! (5 ) Now replace CMN_SETUP w/ references from "logical_mod.f" and +! "directory_mod.f". Now references STT from "tracer_mod.f". +! Replace LFOSSIL with LANTHRO (bmy, 7/20/04) +! (6 ) Now make sure all USE statements are USE, ONLY. Also eliminate +! reference to BPCH2_MOD, it's obsolete. (bmy, 10/3/05) +! (7 ) Now modified for new "biomass_mod.f" (bmy, 4/5/06) +! (8 ) BIOMASS(:,:,IDBCO) from "biomass_mod.f" is now in units of +! [atoms C/cm2/s]. Adjust unit conversion accordingly. (bmy, 9/27/06) +!****************************************************************************** +! + ! References to F90 modules + USE BIOMASS_MOD, ONLY : BIOMASS, IDBC2H6 + USE BIOFUEL_MOD, ONLY : BIOFUEL, BIOFUEL_BURN + USE DIAG_MOD, ONLY : AD36 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE GEIA_MOD, ONLY : READ_C3H8_C2H6_NGAS, TOTAL_FOSSIL_TG + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE LOGICAL_MOD, ONLY : LSPLIT, LBIOMASS, LBIOFUEL, LANTHRO + USE TIME_MOD, ONLY : GET_MONTH, GET_TS_EMIS + USE TRACER_MOD, ONLY : STT, ITS_A_C2H6_SIM + USE TRACERID_MOD, ONLY : IDBFC2H6, IDEC2H6 + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters +# include "CMN" ! STT, etc. +# include "CMN_O3" ! EMISTC2H6 +# include "CMN_DIAG" ! Diagnostic arrays & switches + + ! Local variables + LOGICAL, SAVE :: FIRSTEMISS = .TRUE. + INTEGER, SAVE :: LASTMONTH = -99 + INTEGER :: I, J, L, AS + REAL*4 :: ARRAY(IIPAR,JJPAR) + REAL*8 :: AREA_CM2, XTAU + REAL*8 :: E_C2H6_BB, E_C2H6_BF + REAL*8 :: E_C2H6_NGAS, DTSRCE + CHARACTER(LEN=255) :: FILENAME + + ! External functions + REAL*8, EXTERNAL :: BOXVL + + !================================================================= + ! EMISS_C2H6 begins here! + !================================================================= + IF ( FIRSTEMISS ) THEN + + ! Allocate NGASC2H6 array, if this is the first emission + CALL INIT_C2H6 + + ! Set first-time flag to false + FIRSTEMISS = .FALSE. + ENDIF + + ! DTSRCE is the number of seconds per emission timestep + DTSRCE = GET_TS_EMIS() * 60d0 + + !================================================================= + ! Process biomass C2H6 emissions ored in BURNEMIS(IDBC2H6,:,:) + ! in [molec C/cm3/s]. Convert to [kg C2H6] and store in STT. + !================================================================= + IF ( LBIOMASS ) THEN + + ! Only process biomass C2H6 emissions if offline C2H6 sim. + ! For fullchem sim, C2H6 biomass emissions are read from GFED2/3. + ! (mpayer, 3/22/12) + IF ( ITS_A_C2H6_SIM() ) THEN + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, AREA_CM2, E_C2H6_BB ) + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Grid box area [cm2] + AREA_CM2 = GET_AREA_CM2( J ) + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Convert [atoms C/cm2/s] to [kg C2H6] and store in E_C2H6 + E_C2H6_BB = BIOMASS(I,J,IDBC2H6) / 2.0d0 / + & XNUMOL_C2H6 * AREA_CM2 * DTSRCE + + ! Add BB C2H6 to tracer #1 -- total C2H6 [kg C2H6] + STT(I,J,1,1) = STT(I,J,1,1) + E_C2H6_BB + + ! Add BB C2H6 to tracer #2 -- BB C2H6 + IF ( LSPLIT ) THEN + STT(I,J,1,2) = STT(I,J,1,2) + E_C2H6_BB + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + ENDIF + + !================================================================= + ! Process biofuel C2H6 emissions stored in BIOFUEL(IDBFC2H6,:,:) + ! in [molec C/cm3/s. Convert to [kg C2H6] and store in STT. + !================================================================= + IF ( LBIOFUEL ) THEN + + ! Only read biofuel burning emissions if offline C2H6 sim in order + ! to avoid double counting of biofuel emissions in fullchem sim + ! (mpayer, 3/22/12) + IF ( ITS_A_C2H6_SIM() ) THEN + + ! Read biofuel burning emissions (and update ND34 diagnostic) + CALL BIOFUEL_BURN + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, E_C2H6_BF ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Convert [molec C/cm3/s] to [kg C2H6] and store in E_C2H6 + E_C2H6_BF = BIOFUEL(IDBFC2H6,I,J) / 2.0d0 / + & XNUMOL_C2H6 * BOXVL(I,J,1) * DTSRCE + + ! Add BF C2H6 to tracer #1 -- total C2H6 [kg C2H6] + STT(I,J,1,1) = STT(I,J,1,1) + E_C2H6_BF + + ! Add BF C2H6 to tracer #3 -- BF C2H6 + IF ( LSPLIT ) THEN + STT(I,J,1,3) = STT(I,J,1,3) + E_C2H6_BF + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + ENDIF + + !================================================================= + ! Process anthro (natural gas venting/leakage) C2H6 emissions + ! This source is 6.3 Tg C/yr, following Wang et al. [1998]. + ! The distribution follows natural gas venting/leakage of CH4. + ! Contact: Yaping Xiao (xyp@io.harvard.edu) + !================================================================= + IF ( LANTHRO ) THEN + + ! Read C2H6 emissions only if it's a new month + IF ( GET_MONTH() /= LASTMONTH ) THEN + + ! Fancy output... + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a)' ) 'EMISSC2H6: Reading anthro C2H6!' + + ! Read C2H6 emissions [atoms C/cm2/s] + CALL READ_C3H8_C2H6_NGAS( E_C2H6=ARRAY ) + + ! Cast from REAL*4 to REAL*8, resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY, NGASC2H6 ) + + ! Print emission totals in Tg C + CALL TOTAL_FOSSIL_TG( NGASC2H6, IGLOB, JGLOB, + & 1, 12d-3, 'C2H6' ) + + ! Fancy output... + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! Save current month in LASTMONTH + LASTMONTH = GET_MONTH() + ENDIF + + ! Only add anthro emissions to STT if offline C2H6 sim. For + ! fullchem sim, this is done in emfossil (mpayer, 3/22/12) + IF ( ITS_A_C2H6_SIM() ) THEN + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, AREA_CM2, E_C2H6_NGAS ) + DO J = 1, JJPAR + + ! Grid box surface area [cm2] + AREA_CM2 = GET_AREA_CM2( J ) + + DO I = 1, IIPAR + + ! Convert NGAS C2H6 from [atoms C/cm2/s] to [kg C2H6] + E_C2H6_NGAS = NGASC2H6(I,J) / 2.0d0 / + & XNUMOL_C2H6 * AREA_CM2 * DTSRCE + + ! Add NGAS C2H6 to tracer #1 -- total C2H6 [kg C2H6] + STT(I,J,1,1) = STT(I,J,1,1) + E_C2H6_NGAS + + ! Add NGAS C2H6 to tracer #4 -- NGAS C2H6 + IF ( LSPLIT ) THEN + STT(I,J,1,4) = STT(I,J,1,4) + E_C2H6_NGAS + ENDIF + + ! ND36 = Anthro source diagnostic...store as [moleC/cm2] + ! and convert to [moleC/cm2/s] in DIAG3.F + IF ( ND36 > 0 ) THEN + AD36(I,J,IDEC2H6) = AD36(I,J,IDEC2H6) + + & ( NGASC2H6(I,J) * DTSRCE ) + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + ENDIF + + ! Return to calling program + END SUBROUTINE EMISSC2H6 + +!------------------------------------------------------------------------------ + + SUBROUTINE CHEMC2H6 +! +!****************************************************************************** +! Subroutine CHEM_C2H6 performs C2H6 chemistry. Loss of C2H6 is via reaction +! with OH. (xyp, qli, bmy, 10/19/99, 7/20/04) +! +! Arguments as input: +! ========================================================================== +! (1 ) FIRSTCHEM (LOGICAL) : First time flag for chemistry +! +! NOTES: +! (1 ) Now do chemistry all the way to the model top. +! (2 ) Use monthly mean OH fields for oxidation -- reference the monthly +! mean OH array and the routine which reads it from disk in +! "global_oh_mod.f" (bmy, 1/25/02) +! (3 ) Now reference T from "dao_mod.f". Also make FIRSTCHEM a local SAVEd +! variable. (bmy, 11/15/02) +! (4 ) Now use functions GET_MONTH and GET_TS_CHEM from "time_mod.f". +! (5 ) Now reference STT & N_TRACERS from "tracer_mod.f". Now reference +! LSPLIT from "logical_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AIRVOL, T + USE GLOBAL_OH_MOD, ONLY : OH, GET_GLOBAL_OH + USE LOGICAL_MOD, ONLY : LSPLIT + USE TIME_MOD, ONLY : GET_MONTH, GET_TS_CHEM + USE TRACER_MOD, ONLY : N_TRACERS, STT + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + LOGICAL, SAVE :: FIRSTCHEM = .TRUE. + INTEGER, SAVE :: LASTMONTH = -99 + INTEGER :: I, J, L, N + REAL*8 :: DTCHEM, KRATE + + ! External functions + REAL*8, EXTERNAL :: BOXVL + + !================================================================= + ! CHEMC2H6 begins here! + !================================================================= + IF ( FIRSTCHEM ) THEN + FIRSTCHEM = .FALSE. ! save for future use? + ENDIF + + ! DTCHEM is the chemistry timestep in seconds + DTCHEM = GET_TS_CHEM() * 60d0 + + !================================================================= + ! Read in the tropospheric OH fields of the (LMN)th month + ! OH data will be saved into the OH array of "global_oh_mod.f" + !================================================================= + IF ( GET_MONTH() /= LASTMONTH ) THEN + CALL GET_GLOBAL_OH( GET_MONTH() ) + LASTMONTH = GET_MONTH() + ENDIF + + !================================================================= + ! Do C2H6 chemistry -- C2H6 Loss due to chemical reaction with OH + ! + ! DECAY RATE: The decay rate (KRATE) is calculated by: + ! + ! OH + C2H6 -> H2O + C2H5 (JPL '97) + ! k = 8.7D-12 * exp(-1070/T) + ! + ! KRATE has units of [ molec^2 C2H6 / cm6 / s ]^-1. + !================================================================= +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N, KRATE ) + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Loss rate [molec2 C2H6/cm6/s]^-1 + KRATE = 8.7d-12 * EXP( -1070.0d0 / T(I,J,L) ) + + ! Apply loss to total C2H6 (tracer #1) + STT(I,J,L,1) = STT(I,J,L,1) * + & ( 1d0 - KRATE * OH(I,J,L) * DTCHEM ) + + ! If we are running w/ tagged tracers, + ! then also apply the loss to each of these + IF ( LSPLIT ) THEN + DO N = 2, N_TRACERS + + ! Subtract loss of C2H6 by OH and store in STT [kg C2H6] + ! Loss = k * [C2H6] * [OH] * dt + STT(I,J,L,N) = STT(I,J,L,N) * + & ( 1d0 - KRATE * OH(I,J,L) * DTCHEM ) + ENDDO + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE CHEMC2H6 + +!------------------------------------------------------------------------------ + +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_c2h6_anthro +! +! !DESCRIPTION: Function GET\_C2H6\_ANTHRO returns the monthly average +! anthropogenic C2H6 emissions at GEOS-Chem grid box (I,J). Data will +! be returned in units of [atoms C/cm2/s]. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_C2H6_ANTHRO( I, J, N ) RESULT( C2H6_ANTHRO ) +! +! !USES: +! + USE TRACERID_MOD, ONLY : IDTC2H6 +# include "CMN_SIZE" ! Size parameters + +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: I ! GEOS-Chem longitude index + INTEGER, INTENT(IN) :: J ! GEOS-Chem latitude index + INTEGER, INTENT(IN) :: N ! GEOS-Chem tracer index +! +! !RETURN VALUE: +! + REAL*8 :: C2H6_ANTHRO +! +! !REVISION HISTORY: +! 22 Mar 2012 - M. Payer - Initial version adapted from GET_RETRO_ANTHRO +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! GET_C2H6_ANTHRO begins here + !================================================================= + + IF ( N == IDTC2H6 ) THEN + C2H6_ANTHRO = NGASC2H6(I,J) + ENDIF + + END FUNCTION GET_C2H6_ANTHRO + +!----------------------------------------------------------------------------- + + SUBROUTINE INIT_C2H6 +! +!****************************************************************************** +! Subroutine INIT_C2H6 allocates and zeroes the NGASC2H6 array, which holds +! global monthly mean natural gas C2H6 emissions. (qli, bmy, 1/1/01, 10/15/02) +! +! NOTES: +! (1 ) Now references ALLOC_ERR from "error_mod.f" (bmy, 10/15/02) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" + + ! Local variables + INTEGER :: AS + + ! Allocate NGASC2H6 array + ALLOCATE( NGASC2H6( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'NGASC2H6' ) + + ! Zero NGASC2H6 array + NGASC2H6 = 0d0 + + ! Return to calling program + END SUBROUTINE INIT_C2H6 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_C2H6 +! +!****************************************************************************** +! Subroutine CLEANUP_C2H6 deallocates the natural gas C2H6 emission array. +! +! NOTES: +!****************************************************************************** +! + IF ( ALLOCATED( NGASC2H6 ) ) DEALLOCATE( NGASC2H6 ) + + ! Return to calling program + END SUBROUTINE CLEANUP_C2H6 + +!------------------------------------------------------------------------------ + + END MODULE C2H6_MOD diff --git a/code/cac_anthro_mod.f b/code/cac_anthro_mod.f new file mode 100644 index 0000000..e1283ee --- /dev/null +++ b/code/cac_anthro_mod.f @@ -0,0 +1,1201 @@ +!$Id: cac_anthro_mod.f,v 1.2 2012/03/01 22:00:26 daven Exp $ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: cac_anthro_mod +! +! !DESCRIPTION: Module CAC\_ANTHRO\_MOD contains variables and routines to +! read the Criteria Air Contaminant Canadian anthropogenic emissions +! (amv, phs, 1/28/2009) +!\\ +!\\ +! !INTERFACE: +! + MODULE CAC_ANTHRO_MOD +! +! !USES: +! + IMPLICIT NONE + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: CLEANUP_CAC_ANTHRO + PUBLIC :: EMISS_CAC_ANTHRO + PUBLIC :: EMISS_CAC_ANTHRO_05x0666 + PUBLIC :: GET_CANADA_MASK + PUBLIC :: GET_CAC_ANTHRO +! +! !PRIVATE MEMBER FUNCTIONS: +! + PRIVATE :: CAC_SCALE_FUTURE + PRIVATE :: READ_CANADA_MASK + PRIVATE :: READ_CANADA_MASK_05x0666 + PRIVATE :: INIT_CAC_ANTHRO + PRIVATE :: TOTAL_ANTHRO_TG +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +! 18 Dec 2009 - Aaron van D - Added EMISS_CAC_ANTHRO_05x0666 routine +! 18 Dec 2009 - Aaron van D - Added READ_CANADA_MASK_05x0666 routine +!EOP +!------------------------------------------------------------------------------ +! +! !PRIVATE DATA MEMBERS: +! + + ! Arrays for data masks + INTEGER, ALLOCATABLE :: MASK_CANADA_1x1(:,:) + REAL*8, ALLOCATABLE :: MASK_CANADA(:,:) + + ! Array for surface area + REAL*8, ALLOCATABLE :: A_CM2(:) + + ! Arrays for emissions + REAL*8, ALLOCATABLE :: NOx(:,:) + REAL*8, ALLOCATABLE :: CO(:,:) + REAL*8, ALLOCATABLE :: SO2(:,:) + REAL*8, ALLOCATABLE :: NH3(:,:) +! +! !DEFINED PARAMETERS: +! + REAL*8, PARAMETER :: SEC_IN_YEAR = 86400d0 * 365.25d0 + + CONTAINS +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_canada_mask +! +! !DESCRIPTION: Function GET\_CANADA\_MASK returns the value of the Canadian +! geographic mask at grid box (I,J). MASK=1 if (I,J) is within Canada, +! MASK=0 otherwise. (amv, phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_CANADA_MASK( I, J ) RESULT( THISMASK ) +! +! !INPUT PARAMETERS: +! + ! Longitude and latitude indices + INTEGER, INTENT(IN) :: I, J +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + ! Local variables + REAL*8 :: THISMASK + + !================================================================= + ! GET_CANADA_MASK begins here! + !================================================================= + THISMASK = MASK_CANADA(I,J) + + END FUNCTION GET_CANADA_MASK +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_cac_anthro +! +! !DESCRIPTION: Function GET\_CAC\_ANTHRO returns the Critical Air Contaminants +! emission for GEOS-Chem grid box (I,J) and tracer N. Emissions can be +! returned in units of [kg/s] or [molec/cm2/s]. (amv, phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_CAC_ANTHRO( I, J, N, + & MOLEC_CM2_S, KG_S ) RESULT( VALUE ) +! +! !USES: +! + USE TRACER_MOD, ONLY : XNUMOL + USE TRACERID_MOD, ONLY : IDTNOx, IDTCO, IDTSO2, IDTNH3 +! +! !INPUT PARAMETERS: +! + ! Longitude, latitude, and tracer indices + INTEGER, INTENT(IN) :: I, J, N + + ! OPTIONAL -- return emissions in [molec/cm2/s] + LOGICAL, INTENT(IN), OPTIONAL :: MOLEC_CM2_S + + ! OPTIONAL -- return emissions in [kg/s] + LOGICAL, INTENT(IN), OPTIONAL :: KG_S +! +! !RETURN VALUE: +! + ! Emissions output + REAL*8 :: VALUE +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL :: DO_KGS, DO_MCS + + !================================================================= + ! GET_CAC_ANTHRO begins here! + !================================================================= + + ! Initialize + DO_KGS = .FALSE. + DO_MCS = .FALSE. + + ! Return data in [kg/s] or [molec/cm2/s]? + IF ( PRESENT( KG_S ) ) DO_KGS = KG_S + IF ( PRESENT( MOLEC_CM2_S ) ) DO_MCS = MOLEC_CM2_S + + IF ( N == IDTNOx ) THEN + + ! NOx [kg/yr] + VALUE = NOx(I,J) + + ELSE IF ( N == IDTCO ) THEN + + ! CO [kg/yr] + VALUE = CO(I,J) + + ELSE IF ( N == IDTSO2 ) THEN + + ! SO2 [kg/yr] + VALUE = SO2(I,J) + + ELSE IF ( N == IDTNH3 ) THEN + + ! NH3 [kg/month] + VALUE = NH3(I,J) + + ELSE + + ! Otherwise return a negative value to indicate + ! that there are no CAC emissions for tracer N + VALUE = -1d0 + RETURN + + ENDIF + + !------------------------------ + ! Convert units (if necessary) + !------------------------------ + IF ( DO_KGS ) THEN + + IF ( N == IDTNH3 ) THEN + ! Use 30 days per month (actual number of + ! days may be required for the future) + ! 2592000 = 30days*24hrs*60min*60sec + VALUE = VALUE / 2592000d0 + ELSE + + ! Convert from [kg/yr] to [kg/s] + VALUE = VALUE / SEC_IN_YEAR + ENDIF + + ELSE IF ( DO_MCS ) THEN + + IF ( N == IDTNH3 ) THEN + VALUE = VALUE * XNUMOL(N) / ( A_CM2(J) * 2592000 ) + ELSE + ! Convert NOx from [kg/yr] to [molec/cm2/s] + ! Updated on May 3, 2012 by Wai-Ho Lo: Not only NOx, but + ! also NH3. + VALUE = VALUE * XNUMOL(N) / ( A_CM2(J) * SEC_IN_YEAR ) + ENDIF + + ENDIF + + END FUNCTION GET_CAC_ANTHRO +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emiss_cac_anthro +! +! !DESCRIPTION: Subroutine EMISS\_CAC\_ANTHRO reads the Critical Air +! Contaminants emission fields at 1x1 resolution and regrids them to the +! current model resolution. (amv, phs, 1/28/2009) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_CAC_ANTHRO +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE LOGICAL_MOD, ONLY : LFUTURE + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE TIME_MOD, ONLY : GET_YEAR, GET_MONTH + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_1x1 + +# include "CMN_SIZE" ! Size parameters +# include "CMN_O3" ! FSCALYR +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +! +! !REMARKS: +! (1 ) Emissions are read for a year b/w 2002-2005, and scaled +! (except NH3) between 1985-2003 if needed (phs, 3/10/08) +! (2 ) Now accounts for FSCALYR (phs, 3/17/08) +! 18 Dec 2009 - Aaron van D - Use 2005 scale factors for years beyond 2005 +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: I, J, THISYEAR, SPECIES, SNo, ScNo + INTEGER :: THISMONTH + REAL*4 :: ARRAY(I1x1,J1x1,1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + REAL*8 :: GEOS_1x1_2002(I1x1,J1x1,1) + REAL*8 :: GEOS_1x1_2005(I1x1,J1x1,1) + REAL*8 :: SC_1x1(I1x1,J1x1) + REAL*8 :: TAU2002, TAU2005, TAU + CHARACTER(LEN=255) :: FILENAME + CHARACTER(LEN=4) :: SYEAR, SNAME + CHARACTER(LEN=2) :: THISMONTHCHAR + REAL*8 :: NH3_SCALE(12) + + ! seasonal scalar for NH3 emission (lzh, amv, 12/11/2009) + ! Updated on May 13, 2012 by Wai-Ho Lo, since Agriculture Canada's + ! NH3 emission inventory is used, monthly scalars are not used + + NH3_SCALE = (/ + & 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /) + !& 0.426d0, 0.445d0, 0.526d0, 0.718d0, 1.179d0, 1.447d0, + !& 1.897d0, 1.884d0, 1.577d0, 0.886d0, 0.571d0, 0.445d0 /) + + !================================================================= + ! EMISS_CAC_ANTHRO begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_CAC_ANTHRO + FIRST = .FALSE. + ENDIF + + ! Get emissions year + IF ( FSCALYR < 0 ) THEN + THISYEAR = GET_YEAR() + ELSE + THISYEAR = FSCALYR + ENDIF + + THISMONTH = GET_MONTH() + + WRITE( THISMONTHCHAR, '(i2.2)' ) THISMONTH + THISMONTHCHAR = ADJUSTL( THISMONTHCHAR ) + + DO SPECIES = 1,4 + + IF ( SPECIES .eq. 1 ) THEN + SNAME = 'NOx' + SNo = 1 + ScNo = 71 + ELSEIF ( SPECIES .eq. 2 ) THEN + SNAME = 'CO' + SNo = 4 + ScNo = 72 + ELSEIF ( SPECIES .eq. 3 ) THEN + SNAME = 'SOx' + SNo = 26 + ScNo = 73 + ELSEIF ( SPECIES .eq. 4 ) THEN + SNAME = 'NH3' + SNo = 30 + ScNo = 0 + ENDIF + + IF ( ( THISYEAR .le. 2002 ) .OR. + & ( THISYEAR .ge. 2005 ) ) THEN + + ! TAU values for 2002/2005 + TAU = GET_TAU0( 1, 1, MIN( MAX( THISYEAR, 2002 ), 2005 ) ) + WRITE( SYEAR, '(i4)' ) MIN( MAX( THISYEAR, 2002 ), 2005 ) + + ! File name + IF (SPECIES .eq. 4 ) THEN + FILENAME = TRIM( DATA_DIR_1x1 ) // 'CAC_200801/CAC' // + & '2008-' // TRIM( SNAME ) // '-' // + & TRIM( THISMONTHCHAR ) // + & '.geos.1x1' + ELSE + FILENAME = TRIM( DATA_DIR_1x1 ) // 'CAC_200801/CAC' // + & SYEAR // '-' // TRIM( SNAME ) // '.geos.1x1' + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - EMISS_CAC_ANTHRO: Reading ', a ) + + ! Read data + IF (SPECIES .eq. 4 ) THEN + ! Since currently the 2005 data is read, a monthly + ! TAU value has to be read for 2008 for NH3 emissions + TAU = GET_TAU0( THISMONTH, 1, 2008 ) + ENDIF + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, +!phs & TAU, I1x1, J1x1-1, + & TAU, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 before regridding + GEOS_1x1(:,:,1) = ARRAY(:,:,1) + + ! Apply annual scalar factor. Available for 1985-2006, + ! and NOx, CO and SO2 only. + IF ( ( THISYEAR .lt. 2002 ) .and. SPECIES .ne. 4 ) THEN + + CALL GET_ANNUAL_SCALAR_1x1( ScNo, 2002, + & THISYEAR, SC_1x1 ) + + GEOS_1x1(:,:,1) = GEOS_1x1(:,:,1) * SC_1x1(:,:) + + ELSE IF ((THISYEAR .gt. 2005) .and. SPECIES .ne. 4) THEN + + CALL GET_ANNUAL_SCALAR_1x1( ScNo, 2005, + & THISYEAR, SC_1x1 ) + + GEOS_1x1(:,:,1) = GEOS_1x1(:,:,1) * SC_1x1(:,:) + + ENDIF + + ELSE + + TAU2002 = GET_TAU0( 1, 1, 2002) + TAU2005 = GET_TAU0( 1, 1, 2005) + + ! File name for 2002 data + IF (SPECIES .eq. 4) THEN + FILENAME = TRIM(DATA_DIR_1x1 ) // 'CAC_200801/CAC' // + & '2008-' // TRIM( SNAME ) // '-' // + & TRIM( THISMONTHCHAR ) // + & '.geos.1x1' + ELSE + FILENAME = TRIM( DATA_DIR_1x1 ) // 'CAC_200801/CAC2002-' + & // TRIM(SNAME) // '.geos.1x1' + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read data + IF (SPECIES .eq. 4 ) THEN + ! Since currently the 2002 or 2005 data is read, a + ! monthly TAU value has to be read for 2008 for NH3 + ! emissions + TAU = GET_TAU0( THISMONTH, 1, 2008 ) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, +!wl & TAU, I1x1, J1x1-1, + & TAU, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + ELSE + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, +!phs & TAU2002, I1x1, J1x1-1, + & TAU2002, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + ENDIF + + ! Cast to REAL*8 before regridding + GEOS_1x1_2002(:,:,1) = ARRAY(:,:,1) + + ! File name for 2005 data + IF (SPECIES .eq. 4) THEN + FILENAME = TRIM(DATA_DIR_1x1 ) // 'CAC_200801/CAC' // + & '2008-' // TRIM( SNAME ) // '-' // + & TRIM( THISMONTHCHAR ) // + & '.geos.1x1' + ELSE + FILENAME = TRIM( DATA_DIR_1x1 ) // 'CAC_200801/CAC2005-' + & // TRIM(SNAME) // '.geos.1x1' + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read data + IF (SPECIES .eq. 4 ) THEN + ! Since currently the 2002 or 2005 data is read, a + ! monthly TAU value has to be read for 2008 for NH3 + ! emissions + TAU = GET_TAU0( THISMONTH, 1, 2008 ) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, +!wl & TAU, I1x1, J1x1, + & TAU, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + ELSE + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, +!phs & TAU2005, I1x1, J1x1-1, + & TAU2005, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + ENDIF + + ! Cast to REAL*8 before regridding + GEOS_1x1_2005(:,:,1) = ARRAY(:,:,1) + + ! Scale b/w 2002-2005 + GEOS_1x1(:,:,1) = GEOS_1x1_2002(:,:,1) + ( THISYEAR - 2002.) + & / 3. * + & ( GEOS_1x1_2005(:,:,1) - GEOS_1x1_2002(:,:,1) ) + + !fp (check that it doesn't get negative) + DO I=1,I1x1 + DO J=1,J1x1 + + IF ( GEOS_1x1(I,J,1) .LT. 0 ) THEN + GEOS_1x1(I,J,1) = 0d0 + ENDIF + + ENDDO + ENDDO + + ENDIF + + ! Regrid from GEOS 1x1 --> current model resolution + IF ( SPECIES .eq. 1 ) THEN + + CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, NOx ) + + ELSEIF ( SPECIES .eq. 2 ) THEN + + CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, CO ) + + ELSEIF ( SPECIES .eq. 3 ) THEN + + ! Convert SOx to SO2, where SOx is assumed to be 1.4% SO4 and + ! 98.6% SO2 over NA, based upon Chin et al, 2000, and as + ! utilized in sulfate_mod.f + GEOS_1x1(:,:,1) = GEOS_1x1(:,:,1) * 0.986 + + CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, SO2 ) + + ELSEIF ( SPECIES .eq. 4 ) THEN + + ! Apply seasonality + ! Using Agriculture Canada's NH3 emission inventory, + ! no seasonality scalars are required + !GEOS_1x1(:,:,1) = NH3_SCALE(THISMONTH) * GEOS_1x1(:,:,1) + CALL DO_REGRID_1x1( 'kg/month', GEOS_1x1, NH3 ) + + ENDIF + + ENDDO + + !-------------------------- + ! Compute future emissions + !-------------------------- + IF ( LFUTURE ) THEN + CALL CAC_SCALE_FUTURE + ENDIF + + !-------------------------- + ! Print emission totals + !-------------------------- + CALL TOTAL_ANTHRO_Tg( THISYEAR ) + + END SUBROUTINE EMISS_CAC_ANTHRO +!EOC +!------------------------------------------------------------------------------ +! Dalhousie Atmospheric Compositional Analysis Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emiss_cac_anthro_05x0666 +! +! !DESCRIPTION: Subroutine EMISS\_CAC\_ANTHRO\_05x0666 reads the Critical Air +! Contaminants emission fields at nested NA resolution (1/2 x 2/3) +! (amv, phs, 11/03/2009) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_CAC_ANTHRO_05x0666 +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE LOGICAL_MOD, ONLY : LFUTURE + USE TIME_MOD, ONLY : GET_YEAR, GET_MONTH + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_05x0666_NESTED + +# include "CMN_SIZE" ! Size parameters +# include "CMN_O3" ! FSCALYR +! +! !REVISION HISTORY: +! 03 Nov 2009 - A. van Donkelaar - Initial Version +! +! !REMARKS: +! (1 ) Emissions are read for a year b/w 2002-2005, and scaled +! (except NH3) between 1985-2003 if needed (phs, 3/10/08) +! (2 ) Now accounts for FSCALYR (phs, 3/17/08) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: I, J, THISYEAR, SPECIES, SNo, ScNo + INTEGER :: THISMONTH + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*8 :: GEOS_05x0666(IIPAR,JJPAR,1) + REAL*8 :: GEOS_05x0666_2002(IIPAR,JJPAR,1) + REAL*8 :: GEOS_05x0666_2005(IIPAR,JJPAR,1) + REAL*4 :: SC_05x0666(IIPAR,JJPAR) + REAL*8 :: TAU2002, TAU2005, TAU + CHARACTER(LEN=255) :: FILENAME + CHARACTER(LEN=4) :: SYEAR, SNAME + CHARACTER(LEN=2) :: THISMONTHCHAR + REAL*8 :: NH3_SCALE(12) + + ! seasonal scalar for NH3 emission (lzh, amv, 12/11/2009) + ! Updated on May 13, 2012 by Wai-Ho Lo, since Agriculture Canada's + ! NH3 emission inventory is used, monthly scalars are not used + + NH3_SCALE = (/ + & 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /) + !& 0.426d0, 0.445d0, 0.526d0, 0.718d0, 1.179d0, 1.447d0, + !& 1.897d0, 1.884d0, 1.577d0, 0.886d0, 0.571d0, 0.445d0 /) + + !================================================================= + ! EMISS_CAC_ANTHRO begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_CAC_ANTHRO + FIRST = .FALSE. + ENDIF + + ! Get emissions year + IF ( FSCALYR < 0 ) THEN + THISYEAR = GET_YEAR() + ELSE + THISYEAR = FSCALYR + ENDIF + + THISMONTH = GET_MONTH() + + WRITE( THISMONTHCHAR, '(i2.2)' ) THISMONTH + THISMONTHCHAR = ADJUSTL( THISMONTHCHAR ) + + DO SPECIES = 1,4 + + IF ( SPECIES .eq. 1 ) THEN + SNAME = 'NOx' + SNo = 1 + ScNo = 71 + ELSEIF ( SPECIES .eq. 2 ) THEN + SNAME = 'CO' + SNo = 4 + ScNo = 72 + ELSEIF ( SPECIES .eq. 3 ) THEN + SNAME = 'SOx' + SNo = 26 + ScNo = 73 + ELSEIF ( SPECIES .eq. 4 ) THEN + SNAME = 'NH3' + SNo = 30 + ScNo = 0 + ENDIF + + IF ( ( THISYEAR .le. 2002 ) .OR. + & ( THISYEAR .ge. 2005 ) ) THEN + + ! TAU values for 2002/2005 + TAU = GET_TAU0( 1, 1, MIN( MAX( THISYEAR, 2002 ), 2005 ) ) + WRITE( SYEAR, '(i4)' ) MIN( MAX( THISYEAR, 2002 ), 2005 ) + + ! File name + IF (SPECIES .eq. 4 ) THEN + FILENAME = TRIM( DATA_DIR ) // 'CAC_200911/CAC' // + & '2008-' // TRIM( SNAME ) // '-' // + & TRIM( THISMONTHCHAR ) // + & '.geos.1t2x2t3' + ELSE + FILENAME = TRIM( DATA_DIR ) // 'CAC_200911/CAC' // + & SYEAR // '-' // TRIM( SNAME ) // + & '.geos.na.1t2x2t3' + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - EMISS_CAC_ANTHRO_05x0666: Reading ', a ) + + ! Read data + IF (SPECIES .eq. 4 ) THEN + ! Since currently the 2002 or 2005 data is read, a + ! monthly TAU value has to be read for 2008 for NH3 + ! emissions + TAU = GET_TAU0(THISMONTH, 1, 2008 ) + ENDIF + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, + & TAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 before regridding + GEOS_05x0666(:,:,1) = ARRAY(:,:,1) + + ! Apply annual scalar factor. Available for 1985-2006, + ! and NOx, CO and SO2 only. + IF ( ( THISYEAR .lt. 2002 ) .and. SPECIES .ne. 4 ) THEN + + CALL GET_ANNUAL_SCALAR_05x0666_NESTED( ScNo, 2002, + & THISYEAR, SC_05x0666 ) + + GEOS_05x0666(:,:,1) = GEOS_05x0666(:,:,1) + & * SC_05x0666(:,:) + + ELSE IF ((THISYEAR .gt. 2005) .and. SPECIES .ne. 4) THEN + + CALL GET_ANNUAL_SCALAR_05x0666_NESTED( ScNo, 2005, + & THISYEAR, SC_05x0666 ) + + GEOS_05x0666(:,:,1) = GEOS_05x0666(:,:,1) + & * SC_05x0666(:,:) + + ENDIF + + ELSE + + TAU2002 = GET_TAU0( 1, 1, 2002) + TAU2005 = GET_TAU0( 1, 1, 2005) + + ! File name for 2002 data + IF (SPECIES .eq. 4 ) THEN + FILENAME = TRIM( DATA_DIR ) // 'CAC_200911/CAC' // + & '2008-' // TRIM( SNAME ) // '-' // + & TRIM(THISMONTHCHAR ) // + & '.geos.1t2x2t3' + ELSE + FILENAME = TRIM( DATA_DIR ) // 'CAC_200911/CAC2002-' + & // TRIM(SNAME) // '.geos.na.1t2x2t3' + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read data + IF (SPECIES .eq. 4 ) THEN + ! Since currently the 2002 or 2005 data is read, a + ! monthly TAU value has to be read for 2008 for NH3 + ! emissions + TAU = GET_TAU0( THISMONTH, 1, 2008 ) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, + & TAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + ELSE + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, + & TAU2002, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + ENDIF + + ! Cast to REAL*8 before regridding + GEOS_05x0666_2002(:,:,1) = ARRAY(:,:,1) + + ! File name for 2005 data + IF (SPECIES .eq. 4 ) THEN + FILENAME = TRIM( DATA_DIR ) // 'CAC_200911/CAC' // + & '2008-' // TRIM( SNAME ) // '-' // + & TRIM(THISMONTHCHAR ) // + & '.geos.1t2x2t3' + ELSE + FILENAME = TRIM( DATA_DIR ) // 'CAC_200911/CAC2005-' + & // TRIM(SNAME) // '.geos.na.1t2x2t3' + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read data + IF (SPECIES .eq. 4 ) THEN + ! Since currently the 2002 or 2005 data is read, a + ! monthly TAU value has to be read for 2008 for NH3 + ! emissions + TAU = GET_TAU0( THISMONTH, 1, 2008 ) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, + & TAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + ELSE + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', SNo, + & TAU2005, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + ENDIF + + ! Cast to REAL*8 before regridding + GEOS_05x0666_2005(:,:,1) = ARRAY(:,:,1) + + ! Scale b/w 2002-2005 + GEOS_05x0666(:,:,1) = GEOS_05x0666_2002(:,:,1) + + & ( THISYEAR - 2002.) / 3. * + & ( GEOS_05x0666_2005(:,:,1) + & - GEOS_05x0666_2002(:,:,1) ) + + DO I = 1, IIPAR + DO J = 1, JJPAR + + IF ( GEOS_05x0666(I,J,1) .LT. 0D0 ) + & GEOS_05x0666(I,J,1) = 0d0 + + ENDDO + ENDDO + + ENDIF + + IF ( SPECIES .eq. 1 ) THEN + + NOx(:,:) = GEOS_05x0666(:,:,1) + + ELSEIF ( SPECIES .eq. 2 ) THEN + + CO(:,:) = GEOS_05x0666(:,:,1) + + ELSEIF ( SPECIES .eq. 3 ) THEN + + ! Convert SOx to SO2, where SOx is assumed to be 1.4% SO4 and + ! 98.6% SO2 over NA, based upon Chin et al, 2000, and as + ! utilized in sulfate_mod.f + SO2(:,:) = GEOS_05x0666(:,:,1) * 0.986 + + ELSEIF ( SPECIES .eq. 4 ) THEN + + ! Apply seasonality + !GEOS_05X0666(:,:,1) = NH3_SCALE(THISMONTH) + ! * GEOS_05X0666(:,:,1) + NH3(:,:) = GEOS_05x0666(:,:,1) + + ENDIF + + ENDDO + + !-------------------------- + ! Compute future emissions + !-------------------------- + IF ( LFUTURE ) THEN + CALL CAC_SCALE_FUTURE + ENDIF + + !-------------------------- + ! Print emission totals + !-------------------------- + CALL TOTAL_ANTHRO_Tg( THISYEAR ) + + END SUBROUTINE EMISS_CAC_ANTHRO_05x0666 +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: cac_scale_future +! +! !DESCRIPTION: Subroutine CAC\_SCALE\_FUTURE applies the IPCC future scale +! factors to the Criteria Air Contaminant anthropogenic emissions. +! (amv, phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: + + SUBROUTINE CAC_SCALE_FUTURE +! +! !USES: +! + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_COff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NH3an + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2ff + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + + !================================================================= + ! STREETS_SCALE_FUTURE begins here! + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Future NOx [kg NO2/yr] + NOx(I,J) = NOx(I,J) * GET_FUTURE_SCALE_NOxff( I, J ) + + ! Future CO [kg CO /yr] + CO(I,J) = CO(I,J) * GET_FUTURE_SCALE_COff( I, J ) + + ! Future SO2 [kg SO2/yr] + SO2(I,J) = SO2(I,J) * GET_FUTURE_SCALE_SO2ff( I, J ) + + ! Future NH3 [kg NH3/yr] + NH3(I,J) = NH3(I,J) * GET_FUTURE_SCALE_NH3an( I, J ) + + ENDDO + ENDDO +!$OMP END PARALLEL DO + + END SUBROUTINE CAC_SCALE_FUTURE +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: total_anthro_tg +! +! !DESCRIPTION: Subroutine TOTAL\_ANTHRO\_TG prints the totals for the +! anthropogenic emissions of NOx, CO, SO2 and NH3. (amv, phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE TOTAL_ANTHRO_TG( YEAR ) +! +! !USES: +! +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: YEAR ! Year of data to compute totals +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + REAL*8 :: T_NOX, T_CO, T_SO2, T_NH3 + CHARACTER(LEN=3) :: UNIT + + !================================================================= + ! TOTAL_ANTHRO_TG begins here! + !================================================================= + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 100 ) + 100 FORMAT( 'C. A. C. C A N A D I A N E M I S S I O N S', / ) + + + ! Total NOx [Tg N] + T_NOX = SUM( NOx ) * 1d-9 * ( 14d0 / 46d0 ) + + ! Total CO [Tg CO] + T_CO = SUM( CO ) * 1d-9 + + ! Total SO2 [Tg S] + T_SO2 = SUM( SO2 ) * 1d-9 * ( 32d0 / 64d0 ) + + ! Total NH3 [Tg NH3] + T_NH3 = SUM( NH3 ) * 1d-9 + + ! Print totals in [kg] + WRITE( 6, 110 ) 'NOx ', YEAR, T_NOx, '[Tg N ]' + WRITE( 6, 110 ) 'CO ', YEAR, T_CO, '[Tg CO ]' + WRITE( 6, 110 ) 'SO2 ', YEAR, T_SO2, '[Tg S ]' + WRITE( 6, 110 ) 'NH3 ', YEAR, T_NH3, '[Tg NH3]' + + ! Format statement + 110 FORMAT( 'C.A.C. Canadian anthro ', a5, + & 'for year ', i4, ': ', f11.4, 1x, a8 ) + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + END SUBROUTINE TOTAL_ANTHRO_Tg +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_canada_mask +! +! !DESCRIPTION: Subroutine READ\_CANADA\_MASK reads and regrids the Canadian +! geographic mask from disk. (amv, phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_CANADA_MASK +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE REGRID_1x1_MOD, ONLY : DO_REGRID_G2G_1x1, DO_REGRID_1x1 + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(I1x1,J1x1,1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + REAL*8 :: TAU2000 + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_CANADA_MASK begins here! + !================================================================= + + TAU2000 = GET_TAU0(1,1,2000) + + ! File name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'CAC_200801/CanadaMask.geos.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_CANADA_MASK: Reading ', a ) + + ! Read data [unitless] + CALL READ_BPCH2( FILENAME, 'LANDMAP', 2, + & TAU2000, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 before regridding + GEOS_1x1(:,:,1) = ARRAY(:,:,1) + + ! Save the 1x1 China mask for future use + MASK_CANADA_1x1(:,:) = GEOS_1x1(:,:,1) + + ! Regrid from GENERIC 1x1 GRID to GEOS 1x1 GRID +! CALL DO_REGRID_G2G_1x1( 'unitless', GEN_1x1, GEOS_1x1(:,:,1) ) + + ! Regrid from GEOS 1x1 GRID to current model resolution + CALL DO_REGRID_1x1( 'unitless', GEOS_1x1, MASK_CANADA ) + + END SUBROUTINE READ_CANADA_MASK +!EOC +!------------------------------------------------------------------------------ +! Dalhousie University Atmospheric Compositional Analysis Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_canada_mask_05x0666 +! +! !DESCRIPTION: Subroutine READ\_CANADA\_MASK\_05x0666 reads the Canadian +! geographic mask from disk. (amv, phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_CANADA_MASK_05x0666 +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE REGRID_1x1_MOD, ONLY : DO_REGRID_G2G_1x1, DO_REGRID_1x1 + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 11 Nov 2009 - A. van Donkelaar - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*8 :: GEOS_05x0666(IIPAR,JJPAR,1) + REAL*8 :: TAU2000 + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_CANADA_MASK begins here! + !================================================================= + + TAU2000 = GET_TAU0(1,1,2000) + + ! File name + FILENAME = TRIM( DATA_DIR ) // + & 'CAC_200911/CanadaMask.geos.na.1t2x2t3' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_CANADA_MASK_05x0666: Reading ', a ) + + ! Read data [unitless] + CALL READ_BPCH2( FILENAME, 'LANDMAP', 2, + & TAU2000, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 before regridding + MASK_CANADA(:,:) = ARRAY(:,:,1) + + END SUBROUTINE READ_CANADA_MASK_05x0666 +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: init_cac_anthro +! +! !DESCRIPTION: Subroutine INIT\_CAC\_ANTHRO allocates and zeroes all +! module arrays. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE INIT_CAC_ANTHRO +! +! !USES: +! + USE ERROR_MOD, ONLY : ALLOC_ERR + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE LOGICAL_MOD, ONLY : LCAC + +# include "CMN_SIZE" ! Size parameters +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: AS, J + + !================================================================= + ! INIT_CAC_ANTHRO begins here! + !================================================================= + + ! Return if LCAC is false + IF ( .not. LCAC ) RETURN + + !-------------------------------------------------- + ! Allocate and zero arrays for emissions + !-------------------------------------------------- + + ALLOCATE( NOx( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'NOx' ) + NOx = 0d0 + + ALLOCATE( CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'CO' ) + CO = 0d0 + + ALLOCATE( SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SO2' ) + SO2 = 0d0 + + ALLOCATE( NH3( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'NH3' ) + NH3 = 0d0 + + !--------------------------------------------------- + ! Pre-store array for grid box surface area in cm2 + !--------------------------------------------------- + + ! Allocate array + ALLOCATE( A_CM2( JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'A_CM2' ) + + ! Fill array + DO J = 1, JJPAR + A_CM2(J) = GET_AREA_CM2( J ) + ENDDO + + !--------------------------------------------------- + ! Read & Regrid masks for CAC emissions + !--------------------------------------------------- + + ALLOCATE( MASK_CANADA_1x1( I1x1, J1x1 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'MASK_CANADA_1x1' ) + MASK_CANADA_1x1 = 0 + + ALLOCATE( MASK_CANADA( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'MASK_CANADA' ) + MASK_CANADA = 0d0 + + ! Read China & SE Asia masks from disk + CALL READ_CANADA_MASK + + END SUBROUTINE INIT_CAC_ANTHRO +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: cleanup_cac_anthro +! +! !DESCRIPTION: Subroutine CLEANUP\_CAC\_ANTHRO deallocates all module +! arrays. (phs, 1/28/09) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE CLEANUP_CAC_ANTHRO +! +! !REVISION HISTORY: +! 28 Jan 2009 - P. Le Sager - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! CLEANUP_STREETS begins here! + !================================================================= + IF ( ALLOCATED( A_CM2 ) ) DEALLOCATE( A_CM2 ) + IF ( ALLOCATED( MASK_CANADA_1x1) ) DEALLOCATE( MASK_CANADA_1x1) + IF ( ALLOCATED( MASK_CANADA ) ) DEALLOCATE( MASK_CANADA ) + IF ( ALLOCATED( NOx ) ) DEALLOCATE( NOx ) + IF ( ALLOCATED( CO ) ) DEALLOCATE( CO ) + IF ( ALLOCATED( SO2 ) ) DEALLOCATE( SO2 ) + IF ( ALLOCATED( NH3 ) ) DEALLOCATE( NH3 ) + + END SUBROUTINE CLEANUP_CAC_ANTHRO +!EOC + END MODULE CAC_ANTHRO_MOD + diff --git a/code/ch3i_mod.f b/code/ch3i_mod.f new file mode 100644 index 0000000..a2b303d --- /dev/null +++ b/code/ch3i_mod.f @@ -0,0 +1,1180 @@ +! $Id: ch3i_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE CH3I_MOD +! +!****************************************************************************** +! Module CH3I_MOD contains emissions and chemistry routines for the CH3I +! (Methyl Iodide) simulation. (bmy, 1/23/02, 9/27/06) +! +! Module Routines: +! ============================================================================ +! (1 ) OPEN_CH3I_FILES : Opens CH3I emissions files and reads data +! (2 ) EMISSCH3I : Emits CH3I from various sources into the STT array +! (3 ) CHEMCH3I : Performs CH3I chemistry on the STT tracer array +! +! GEOS-CHEM modules referenced by ch3i_mod.f +! ============================================================================ +! (1 ) biofuel_mod.f : Module w/ routines to read biofuel emissions +! (2 ) biomass_mod.f : Module w/ routines to read biomass emissions +! (3 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (4 ) dao_mod.f : Module w/ arrays for DAO met fields +! (5 ) diag_mod.f : Module w/ GEOS-CHEM diagnostic arrays +! (6 ) diag_pl_mod.f : Module w/ routines for prod & logs diag's +! (7 ) error_mod.f : Module w/ NaN and other error check routines +! (8 ) file_mod.f : Module w/ file unit numbers and error checks +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! (10) transfer_mod.f : Module w/ routines to cast & resize arrays +! (11) uvalbedo_mod.f : Module w/ routines to read UV albedo data +! +! References +! ============================================================================ +! (1 ) Bell, N. et al, "Methyl Iodide: Atmospheric budget and use as a tracer +! of marine convection in global models", J. Geophys. Res, 107(D17), +! 4340, 2002. +! (2 ) Nightingale et al [2000a], J. Geophys. Res, 14, 373-387 +! (3 ) Nightingale et al [2000b], Geophys. Res. Lett, 27, 2117-2120 +! (4 ) Wanninkhof, R., "Relation between wind speed and gas exchange over +! the ocean", J. Geophys. Res, 97, 7373-7382, 1992. +! +! NOTES: +! (1 ) Removed obsolete code from 1/15/02 (bmy, 4/15/02) +! (2 ) Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Updated comments (bmy, 5/28/02) +! (3 ) Replaced all instances of IM with IIPAR and JM with JJPAR, in order +! to prevent namespace confusion for the new TPCORE (bmy, 6/25/02) +! (4 ) Now reference "file_mod.f" (bmy, 8/2/02) +! (5 ) Updated call to INPHOT (bmy, 8/23/02) +! (6 ) Now references BXHEIGHT from "dao_mod.f". Now also references F90 +! modules "error_mod.f" and "tracerid_mod.f". (bmy, 11/6/02) +! (7 ) Now references "grid_mod.f" and the new "time_mod.f" (bmy, 2/10/03) +! (8 ) Added modifications for SMVGEAR II. Removed reference to "file_mod.f". +! (bdf, bmy, 4/21/03) +! (9 ) Now references "directory_mod.f". Now references "diag_pl_mod.f". +! (bmy, 7/20/04) +! (10) Now can read data for both GEOS and GCAP grids. Now use Nightingale +! et al formulation for piston velocity Kw. (bmy, 8/16/05) +! (11) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (12) BIOMASS(:,:,IDBCO) from "biomass_mod.f" is now in units of +! [molec CO/cm2/s]. Adjust unit conversion accordingly. (bmy, 9/27/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE OPEN_CH3I_FILES( THISMONTH ) +! +!****************************************************************************** +! Subroutine OPEN_CH3I_FILES loads surface emission fields for CH3I +! (mgs, 3/15/99; bmy, hsu, 3/24/00,. bmy, 6/19/01, 10/3/05) +! +! As of 16 June 1999, scale factors are applied in emissch3i.f (mgs) +! and we use monthly RADSWG fields instead of NPP. +! +! This routine is called at the first emission time step and on the +! first of each month +! +! Arguments as Input: +! ============================================================================ +! (1 ) THISMONTH (INTEGER) : Current month (1-12) +! +! NOTES: +! (1 ) Shortwave radiation at the ground ... +! *** used to be: +! Ocean net primary productivity is used to estimate CH3I surface +! water concentration: parametrization derived from bilinear fit +! of ship cruise data with NPP from Rutgers University and RADSWG. +! (surface water concentration should not exceed 8 ng/L) +! (2 ) CH3I emissions from rice and wetlands use Fung's CH4 emission +! inventory scaled with a constant factor from BIBLE observations. +! (3 ) Added "CMN_SETUP" so that the proper path name to the /data/ctm +! directories can be supplied. (bmy, 3/18/99) +! (4 ) Trap I/O errors with subroutine IOERROR (bmy, 5/27/99) +! (5 ) OCDATA now holds the aqueous CH3I in [ng/L], as read from disk. +! No further unit conversion is necessary (hsu, bmy, 3/24/00) +! (7 ) Reference F90 module "bpch2_mod" which contains routine "read_bpch2" +! for reading data from binary punch files (bmy, 6/28/00) +! (7 ) Now use function GET_TAU0 (from "bpch2_mod.f") to return the TAU0 +! value used to index the binary punch file. (bmy, 7/20/00) +! (8 ) Convert all input files to binary punch file format -- now call +! READ_BPCH2 to read all binary punch files. Also use GET_RES_EXT() +! from BPCH2_MOD to get the proper extension string. (bmy, 8/8/00) +! (9 ) Now read all CH3I files from the DATA_DIR/CH3I subdirectory. +! Also updated comments & made cosmetic changes. Also removed +! reference to "CMN", which is not needed here. (bmy, 6/19/01) +! (10) Now use routine TRANSFER_2D from "transfer_mod.f" to cast from REAL*4 +! to REAL*8 and to copy 2-D data to an array of size (IIPAR,JJPAR). +! Also use 3 arguments (M/D/Y) in call to GET_TAU0.(bmy, 9/27/01) +! (11) Removed obsolete code from 9/01 (bmy, 10/24/01) +! (12) Now bundled into "ch3i_mod.f" Updated comments, cosmetic changes. +! (bmy, 1/23/02) +! (13) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +! (14) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +! (15) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +!****************************************************************************** +! + ! 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 + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: THISMONTH ! month of the year (1, 2, .., 12) + + ! Local common blocks (shared with OPEN_CH3I_FILES) + REAL*8 :: OCDATA(IIPAR,JJPAR) ! ocean field for emiss. flux + REAL*8 :: EFCH4R(IIPAR,JJPAR) ! emission flux from rice + REAL*8 :: EFCH4W(IIPAR,JJPAR) ! emission flux from wetlands + REAL*8 :: CH3ISUM(5) ! sum of emissions in kg/yr + COMMON /CH3IFLDS/ OCDATA, EFCH4R, EFCH4W, CH3ISUM + + ! Local variables + REAL*4 :: Q1(IGLOB,JGLOB,1) + REAL*8 :: XTAU + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! OPEN_CH3I_FILES begins here! + ! + ! Get the TAU0 value for this month (use "generic" year 1985) + !================================================================= + XTAU = GET_TAU0( THISMONTH, 1, 1985 ) + + !================================================================= + ! Read ocean field + !================================================================= + +! ! Uncomment this to read Ocean NPP +! FILENAME = TRIM( DATA_DIR ) // +! & 'CH3I/ocean_npp.geos.' // GET_RES_EXT() + + ! Uncomment this to read aqueous CH3I + FILENAME = TRIM( DATA_DIR ) // + & 'CH3I/ocean_ch3i.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + + ! Read Caq in [ng/L] from the binary punch file + CALL READ_BPCH2( TRIM( FILENAME ), 'IJ-AVG-$', 71, + & XTAU, IGLOB, JGLOB, + & 1, Q1, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( Q1(:,:,1), OCDATA ) + + !================================================================= + ! Read rice paddy emissions + !================================================================= + FILENAME = TRIM( DATA_DIR ) // + & 'CH3I/ch4_rice.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Read CH4 rice paddy emissions in [kg/m2/s] + CALL READ_BPCH2( TRIM( FILENAME ), 'CH4-SRCE', 1, + & XTAU, IGLOB, JGLOB, + & 1, Q1, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( Q1(:,:,1), EFCH4R ) + + !================================================================= + ! Read ocean DOC emissions and mixed-layer temp + !================================================================= +! FILENAME = TRIM( DATA_DIR ) // +! & 'CH3I/ocean_DOC.geos.' // GET_RES_EXT() +! +! ! Read Short-Lived DOC emissions in [ng/L] +! CALL READ_BPCH2( FILENAME, 'DOC-SRCE', 1, XTAU, +! & IGLOB, JGLOB, 1, Q1 ) +! +! ! extract window +! DOC_S(1:IIPAR,1:JJPAR) = Q1(1+I0:IIPAR+I0,1+J0:JJPAR+J0,1) +! +! ! Read Long-Lived DOC emissions in [ng/L] +! CALL READ_BPCH2( FILENAME, 'DOC-SRCE', 2, XTAU, +! & IGLOB, JGLOB, 1, Q1 ) +! +! ! extract window +! DOC_L(1:IIPAR,1:JJPAR) = Q1(1+I0:IIPAR+I0,1+J0:JJPAR+J0,1) +! +! ! Read Mixed-Layer temp [T] +! CALL READ_BPCH2( FILENAME, 'DOC-SRCE', 3, XTAU, +! & IGLOB, JGLOB, 1, Q1 ) +! +! ! extract window +! MLT(1:IIPAR,1:JJPAR) = Q1(1+I0:IIPAR+I0,1+J0:JJPAR+J0,1) + + !================================================================= + ! Read CH4 wetland emissions + !================================================================= + FILENAME = TRIM( DATA_DIR ) // + & 'CH3I/ch4_wetl.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Read CH4 rice paddy emissions in [kg/m2/s] + CALL READ_BPCH2( TRIM( FILENAME ), 'CH4-SRCE', 2, + & XTAU, IGLOB, JGLOB, + & 1, Q1, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( Q1(:,:,1), EFCH4W ) + + ! Return to calling program + END SUBROUTINE OPEN_CH3I_FILES + +!------------------------------------------------------------------------------ + + SUBROUTINE EMISSCH3I +! +!****************************************************************************** +! Subroutine EMISSCH3I (mgs, bmy, 11/23/98, 9/27/06) specifies methyl +! iodide (CH3I) emissions from the following sources: +! +! Ocean: use correlation of surface water CH3I with net ocean +! primary productivity and short wave radiation to get +! global fields of CH3I surface water concentrations. +! Then compute sea-air exchange according to Liss&Slater, 1974 +! Use ND36 to get detailed output of ocean emissions! +! (only shortwave radiation used, mgs, 06/21/99) +! +! Biomass burning: use CO emission database (J.A. Logan) and +! scale with 0.4x10-6 v/v [Ferek et al., 1998] +! +! Biofuel burning: same as biomass burning +! +! Rice paddies and wetlands: use CH4 emission inventory from +! Fung et al. [1991] and scale with 7.4x10-5 g/g +! (BIBLE data over Japan, Blake pers. com., 1999) +! +! Soil fumigation: CH3I could become the major replacement for +! CH3Br in the future. Right now, we have no soil emissions, +! but depending on availability, we might put the CH3Br +! inventory from Brasseur et al., 1998 into the model +! at some point. +! +! Emissions from rice paddies, wetlands and biofuels are rather +! speculative at this point. There appears to be another terrestrial +! source from higher plants. However, this is practically un-quantifiable. +! +! NOTES: +! (1 ) Starting point: cleaned version of EMISSRN (1.5 from bmy) +! (2 ) initial version: simply specify surface layer concentrations +! for all ocean grid boxes (mgs, 11/20/98) +! (3 ) As of 11/20/98, the following sources of CH3I are now used: +! (a) Tracer #1 : CH3I from oceans +! (b) Tracer #2 : CH3I from biomass burning (scaled from CO values) +! (c) Tracer #3 : CH3I from wood burning (scaled from CO values) +! (4 ) Added FIRSTEMISS as an argument...useful for later reference +! (bmy, 11/23/98) +! (5 ) Added ND29 diagnostics for CO woodburning and biomass burning +! (bmy, 11/23/98) +! (6 ) Add FRCLND as an argument (bmy, 1/11/99) +! (7 ) Replace constant surface concentrations for ocean source with +! flux parametrization and add rice and wetland tracers: (mgs, 03/12/99) +! (d) Tracer #4 : CH3I from rice paddies +! (e) Tracer #5 : CH3I from wetlands +! (8 ) DIAG36 is used for emission fluxes in ng/m2/s and surface water +! concentrations in ng/L and a log of the ocean atmosphere exchange +! coefficient in cm/h. DIAG29 traces biomass burning and woodburning +! CO emissions in ???. +! (9 ) Added LOGMONTH for logging CH3I monthly mean output (mgs, 3/24/99) +! (10) Now use F90 syntax for declarations. Also added the OUTLOG +! flag for sending monthly sums to a log file (bmy, 3/24/99) +! (11) Fixed bugs in the expressions for H and FLUX (mgs, bmy, 5/15/99) +! (12) Now uses bilinear correlation with NPP and RADSWG for ocean source +! (before only NPP) (mgs, 16 Jun 1999 +! (13) FRCLND removed as argument, because CMN_DEP now included +! (mgs, 06/16/99) +! (14) Ocean emissions now differetn parametrizations for 3 latitude regions. +! Emissions protocolled in more detail. +! (15) added LASTEMISS flag for final summary output (mgs, 06/28/99) +! (16) Replaced AIJ with AD36 allocatable array (bmy, 3/28/00) +! (17) Removed obsolete code (bmy, 4/14/00) +! (18) Now reference AIRVOL and TS from "dao_mod.f" instead of from +! common block header files (bmy, 6/23/00) +! (19) Eliminate obsolete code from 6/26/00 (bmy, 8/31/00) +! (20) Added references to F90 modules "biomass_mod.f" and "biofuel_mod.f". +! Also, TWOODIJ is now called BIOFUEL. Finally, BURNEMIS is now +! referenced with IREF = I + I0 and JREF = J + J0. (bmy, 9/11/00) +! (21) Removed obsolete code from 9/12/00 (bmy, 12/21/00) +! (22) Now use IDBFCO to reference the biofuel CO emissions. Also make +! sure that IDBCO and IDBFCO are not zero. (bmy, 3/20/01) +! (23) Eliminated obsolete commented-out code (bmy, 4/20/01) +! (24) Now prompt user to check IDBCO and IDBFCO in "tracer.dat" if +! these switches are turned off. Also now read all data files +! from the CH3I subdirctory of DATA_DIR. (bmy, 6/19/01) +! (25) BIOFUEL (N,IREF,JREF) is now BIOFUEL(N,I,J). BURNEMIS(N,IREF,JREF) +! is now BURNEMIS(N,I,J). (bmy, 9/28/01) +! (26) Removed obsolete code from 9/01 and 10/01 (bmy, 10/23/01) +! (27) Now bundled into "ch3i_mod.f". Updated comments, cosmetic +! changes. Removed LASTEMISS as an argument. (bmy, 1/23/02) +! (28) Now reference file units from "file_mod.f" (bmy, 8/2/02) +! (29) Now reference BXHEIGHT from "dao_mod.f". Also references IDBCO and +! IDBFCO from "tracerid_mod.f". Now make FIRSTEMISS a local SAVEd +! variable. (bmy, 11/15/02) +! (30) Now use GET_AREA_M2 from "grid_mod.f" to compute grid box surface +! areas. Removed references to DXYP. Now use functions GET_DAY, +! GET_GMT, GET_TS_EMIS from the new "time_mod.f". (bmy, 2/10/03) +! (31) Now reference STT & N_TRACERS from "tracer_mod.f". Now reference +! LEMIS from "logical_mod.f". (bmy, 7/20/04) +! (32) Now modified for new "biomass_mod.f" (bmy, 4/5/06) +! (33) BIOMASS(:,:,IDBCO) from "biomass_mod.f" is now in units of +! [molec CO/cm2/s]. Adjust unit conversion accordingly. (bmy, 9/27/06) +!****************************************************************************** +! + ! Reference to F90 modules + USE BIOFUEL_MOD, ONLY : BIOFUEL, BIOFUEL_BURN + USE BIOMASS_MOD, ONLY : BIOMASS, IDBCO + USE DAO_MOD, ONLY : AIRVOL, BXHEIGHT, TS + USE DIAG_MOD, ONLY : AD29, AD36 + USE GRID_MOD, ONLY : GET_AREA_M2 + USE ERROR_MOD, ONLY : ERROR_STOP + USE LOGICAL_MOD, ONLY : LEMIS + USE TIME_MOD, ONLY : GET_DAY, GET_GMT, + & GET_MONTH, GET_TS_EMIS + USE TRACER_MOD, ONLY : STT, N_TRACERS + USE TRACERID_MOD, ONLY : IDBFCO + + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DEP" ! RADIAT, FRCLND +# include "CMN_DIAG" ! Diagnostic switches + + ! Local common blocks (shared with OPEN_CH3I_FILES) + REAL*8 :: OCDATA(IIPAR,JJPAR) ! scaled ocean net primary prod. + REAL*8 :: EFCH4R(IIPAR,JJPAR) ! scaled emission flux from rice + REAL*8 :: EFCH4W(IIPAR,JJPAR) ! scaled emission flux from wetlands + REAL*8 :: CH3ISUM(5) ! sum of emissions in kg/yr + + COMMON /CH3IFLDS/ OCDATA, EFCH4R, EFCH4W, CH3ISUM + + ! Local variables: + LOGICAL, SAVE :: FIRSTEMISS = .TRUE. + INTEGER :: I, IJLOOP, J, L, N + + REAL*8 :: DTSRCE, BIO_CO, WOOD_CO + REAL*8 :: SCALE, MOLRAT, BXHEIGHT_CM, AREA_M2 + + ! local surface air temp. in K or degC + REAL*8 :: TK, TC + + ! Henry, Schmidt number and exchange coeff. + REAL*8 :: H, Sc, KW + + ! emission flux in kg m^-2 s^-1 + REAL*8 :: FLUX + + ! surface layer gas concentration (ocean) + REAL*8 :: CGAS + + ! For Nightingale sea-air transfer formulation + REAL*8 :: W10 + REAL*8, PARAMETER :: ScCO2 = 600.0d0 + + ! molar volume ratio CH3I/CH3Br for computation + ! of exchange coefficient ocean atmosphere = (62.9/52.9)**0.6 + REAL*8, PARAMETER :: MVR__ = 1.1094736d0 + + ! molar gas constant + REAL*8, PARAMETER :: R = 8.314d0 + + ! (molecules/mole)^-1 + REAL*8, PARAMETER :: XMOL = 1.d0 /6.0225d+23 + + ! molar weights (g/mole) + REAL*8, PARAMETER :: FMOL_CO = 28.0d0 + REAL*8, PARAMETER :: FMOL_CH3I = 141.939d0 + + ! month number used for logging of emissions + INTEGER :: LOGMONTH + + ! ECH3I: Emission ratio mole CH3I / mole CO for biomass burning + REAL*8, PARAMETER :: ECH3I = 4.0d-6 + + !---------------------------------------------------------------------- + ! Prior to 3/28/00: + ! We don't have to scale RADSWG anymore (bmy, 3/28/00) + ! scale factor for ocean npp (ng/L per NPP units) + ! REAL*8, PARAMETER :: SCNPP = 1.0d0 / 2.d5 + ! + !! scale factor for RADSWG (ng/L per W/m^2) + !! HL: high latitudes (> 50deg), ML: mid latitudes (20-50deg) + !REAL*8, PARAMETER :: SCRADHL = 5.445D-3 ! r=0.637 + !REAL*8, PARAMETER :: OFRADHL = -6.845D-2 + ! + !! mean slope refs 10&11 vs 12 + !REAL*8, PARAMETER :: SCRADML = 3.5D-3 + ! + !! mean offset + !REAL*8, PARAMETER :: OFRADML = 0.0D0 + ! + !! ** use the following for a maximum estimate + !REAL*8, PARAMETER :: SCRADML = 3.324D-3 ! refs 10&11 + !REAL*8, PARAMETER :: OFRADML = 3.355D-1 + ! + !! ** use the following for a minimum estimate + !REAL*8, PARAMETER :: SCRADML = 3.796D-3 ! ref 12 + !REAL*8, PARAMETER :: OFRADML = -3.6462D-1 + !---------------------------------------------------------------------- + + ! constant CH3I surface water conc. for tropical latitudes (0-20 deg + ! ** use mean of 0.721D0 for a maximum estimate, median is 0.480D0 + REAL*8, PARAMETER :: OCTROP = 0.480D0 ! median + + ! scale factor for rice paddy emissions ( g CH3I / g CH4 ) + REAL*8, PARAMETER :: SCCH4R = 7.4d-5 + + ! scale factor for wetland emissions + REAL*8, PARAMETER :: SCCH4W = SCCH4R + + ! External functions + REAL*8, EXTERNAL :: BOXVL ! grid box volume in cm^3 + REAL*8, EXTERNAL :: SFCWINDSQR ! square of surface wind speed (10m) + + ! output flag + LOGICAL, PARAMETER :: OUTLOG = .FALSE. + + !================================================================= + ! EMISSCH3I begins here! + ! + ! If this is the first emission step, do the following... + !================================================================= + IF ( FIRSTEMISS ) THEN + + ! Make sure that NTRACE = 5 since we have 5 CH3I tracers. + !IF ( NTRACE /= 5 ) NTRACE = 5 + IF ( N_TRACERS /= 5 ) N_TRACERS = 5 + + + ! Make sure that emissions are turned on. + ! CH3I simulation doesn't make sense w/o emissions + IF ( .not. LEMIS ) THEN + PRINT*,'**** LEMIS=.FALSE.! I turn emissions on now!' + LEMIS = .TRUE. + ENDIF + + ! Output of accumulated emissions + WRITE(97,*) ' CH3I emission log' + WRITE(97,*) ' Total emissions in kg' + WRITE(97,*) + + CH3ISUM = 0.0D0 + ENDIF + +!### Debug -- comment out for now (bmy, 2/10/03) +! !### Debug output in unit 97 ... set OUTLOG flag if wanted +! !### print the first 24 hours, then every 24 hours +! IF ( OUTLOG ) THEN +! IF ( TAU-TAUI < 24 .OR. MOD(FLOOR(TAU-TAUI),24) == 0 ) THEN +! write(97,*) 'before emiss, TAU=',tau +! DO N = 1, NTRACE +! write(97,'(A,I4,1p,E12.4)') ' N, SUM STT(N) = ', +! & N, SUM( STT(:,:,:,N) ) +! ENDDO +! ENDIF +! ENDIF + + ! DTSRCE = the number of seconds between emissions + DTSRCE = GET_TS_EMIS() * 60d0 + + !================================================================= + ! On the first of each month and at the first emission time step: + ! + ! (1) Read in the following fields + ! Aqueous CH3I concentrations (ocean_ch3i.geosX.4x5) + ! methane emissions from rice (ch4_rice.4x5.MM) + ! methane emissions from wetlands (ch4_wetl.4x5.MM) + ! + ! (2) Log global total of emissions and reset sums + !================================================================= + IF ( FIRSTEMISS .OR. + & ( GET_DAY() == 1 .and. GET_GMT() < 1d-3 ) ) THEN + + CALL OPEN_CH3I_FILES( GET_MONTH() ) + + ! apply scaling factors + EFCH4R = EFCH4R * SCCH4R + EFCH4W = EFCH4W * SCCH4W + + ! for surface water concentrations, use results from correlation + ! analysis with NPP and solar radiation (i.e. only RADSWG): + ! use latitude centers (YLMID) for different regions + DO J = 1, JJPAR + DO I = 1, IIPAR + + !--------------------------------------------------------------- + ! Prior to 3/24/00: + ! We don't need to do the latitudinal scaling since we + ! don't calculate the aqueous CH3I anymore -- we read it + ! from disk now, already in units of [ng/L] (hsu, bmy, 3/24/00) + ! + !IF ( ABS(YLMID(J-J0)).LT.20. ) THEN + ! OCDATA(I,J) = OCTROP + !ELSE IF ( ABS(YLMID(J-J0)).GT.50. ) THEN + ! OCDATA(I,J) = OCDATA(I,J) * SCRADHL + OFRADHL + !ELSE + ! OCDATA(I,J) = OCDATA(I,J) * SCRADML + OFRADML + !ENDIF + !--------------------------------------------------------------- + + ! set all values over land to zero + IF ( FRCLND(I,J) >= 0.8 ) OCDATA(I,J) = 0.0D0 + + ! make sure we have no negative concentrations + IF ( OCDATA(I,J) < 0. ) OCDATA(I,J) = 0.0D0 + ENDDO + ENDDO + + ENDIF + +!### Debug -- comment out for now (bmy, 2/10/03) +! !### Debug output to fort.97 +! IF ( JDATE == 1 .AND. TOFDAY < 1.D-3 ) THEN +! LOGMONTH = MONTH-1 +! IF ( LOGMONTH <= 0 ) LOGMONTH = 12 +! +! WRITE(97,*) +! WRITE(97,*) +! & ' ---------------------------------------------' +! WRITE(97,*) ' Accumulated global emissions for month ', +! & LOGMONTH,': ' +! WRITE(97,'(3X,A20,1p,E12.4)') +! & 'ocean : ',CH3ISUM(1) +! WRITE(97,'(3X,A20,1p,E12.4)') +! & 'biomass burning : ',CH3ISUM(2) +! WRITE(97,'(3X,A20,1p,E12.4)') +! & 'wood burning : ',CH3ISUM(3) +! WRITE(97,'(3X,A20,1p,E12.4)') +! & 'rice paddies: ',CH3ISUM(4) +! WRITE(97,'(3X,A20,1p,E12.4)') +! & 'wetlands : ',CH3ISUM(5) +! WRITE(97,*) +! & ' ---------------------------------------------' +! WRITE(97,*) +! +! ! flush the output buffer +! CALL FLUSH( 97 ) +! +! CH3ISUM = 0.0D0 +! ENDIF + + !================================================================= + ! -------------------------------------------- + ! Tracer #1: CH3I from Oceans + ! -------------------------------------------- + ! + ! OCDATA contains estimated surface water CH3I concentrations + ! derived from ocean net primary productivity (in ng/L). + ! The net emission flux is given by + ! F = KW ( Caq - Cg*H ) + ! + ! KW is exchange parameter (piston velocity) and given by + ! KW = 0.31 u^2 ( Sc/660 )^(-1/2) (cm/h) + ! [Wanninkhof et al., 1992] + ! NOTE: As of 8/16/05, we now use the Nightingale et al [2000b] + ! formulation for piston velocity which is: + ! Kw = ( 0.24 * u^2 + 0.061d0*u ) * SQRT( 600/Sc ) + ! + ! u^2 is square of surface wind speed (10m above ground) in m/s + ! + ! Sc is Schmidt number: + ! Sc = (62.9/52.9)^0.6* (2004.-93.5*T+1.39*T^2) + ! + ! with T in degC [Moore and Groszko, 1999] + ! 660.0 is Schmidt number for CO2 in seawater (normalization) + ! + ! Caq is the surface water concentration, + ! Cg is the gas-phase concentration, and + ! H is the (dimensionless!) Henry coefficient: + ! H^-1 = 0.14 exp(-4300 * (T-298)/(T*298)) * R * T / 101.325 + ! [R. Sander] + ! + ! here T is in K (!) + ! + ! To convert Cg from kg/gridbox into ng/L: * 1.d12*1.d-3/AIRVOL + ! + ! To convert cm/h*ng/L to kg/m^2/s : *1.d-11/3600. + ! + ! Since CH3I exhibits a pretty strong gradient near the surface, + ! we may have to adjust the "surface" gas-phase concentration in + ! the future?? + ! + ! Apply emission flux only for grid boxes that contain at least + ! 20% non-land (FRCLND) and where the surface temperature is above + ! -2 degC (a little arbitrary). + ! + ! NOTES: + ! (1 ) grid box surface area in m^2 is given by DXYP(JREF). + ! Attention: this is not window size! + ! (2 ) Fixed bug with Henry's definition. Old code erroneously + ! used two different definitions of H and did not correctly + ! convert from H in mol/atm to dimensionless H. + ! (mgs, 05/14/1999) + ! (3 ) Now we read in the aqueous CH3I (Caq) from disk into the + ! OCDATA array. OCDATA now has units of [ng/L]. + ! (hsu, bmy, 3/24/00) + ! (4 ) DXYP(JREF) is now replaced by GET_AREA_M2(J) (bmy, 2/4/03) + !================================================================= + N = 1 + L = 1 + DO J = 1, JJPAR + + ! Grid box surface area [m2] + AREA_M2 = GET_AREA_M2( J ) + + DO I = 1, IIPAR + IF ( TS(I,J) >= 271.15 .and. FRCLND(I,J) < 0.8 ) THEN + + ! surface air temp [K] + TK = TS(I,J) + + ! sea surface temp [C] + ! (use TS as surrogate for SST) + TC = TK - 273.15 + + ! Henry's law constant [unitless] + H = 0.14*exp(-4300.*(TK-298.)/(TK*298.) ) * R / 101.325 * TK + + ! Schmidt # [unitless] + Sc = MVR__ * ( 2004. - 93.5*TC + 1.39*TC**2 ) + + ! 10-m wind speed + W10 = SQRT( SFCWINDSQR(I,J) ) + + ! Piston velocity [cm/h], cf Nightingale et al [2000b] + ! (swu, bmy, 8/16/05) + Kw = ( 0.24d0*W10*W10 + 0.061d0*W10 ) * SQRT( ScCO2/Sc ) + + ! convert gas-phase tracer mass to concentration in ng/L + CGAS = STT(I,J,L,N) * 1.0D9 / AIRVOL(I,J,L) + + ! Emission of CH3I from the ocean + FLUX = KW * ( OCDATA(I,J) - CGAS*H ) + +!### !### debug output +!### WRITE(97,9777) 'I,J,H,Sc,KW,CGAS,OCDATA(I,J),FLUX:', +!### & I,J,H,Sc,KW,CGAS,OCDATA(I,J),FLUX +!### 9777 FORMAT(A,2I3,1p,6E12.3) + + !###! make sure, flux is positive (really ??) + !###IF (FLUX.LT.0.0D0) FLUX = 0.0D0 + + ! convert flux to kg/m^2/time step + FLUX = FLUX * ( 1.0D-11 / 3600.D0 ) * DTSRCE + + ! Add to diagnostic array + IF (ND36.GT.0) THEN + AD36(I,J,N) = AD36(I,J,N) + FLUX * 1.D+12 + AD36(I,J,6) = AD36(I,J,6) + KW * OCDATA(I,J) * DTSRCE + AD36(I,J,7) = AD36(I,J,7) + KW * CGAS * H * DTSRCE + !### debug output: store terms seperately !! + !###AD36(I,J,N) = AD36(I,J,N) + FLUX * 1.D+12 + !###AD36(I,J,6) = AD36(I,J,6) + OCDATA(I,J)*DTSRCE + !###AD36(I,J,7) = AD36(I,J,7) + KW*DTSRCE + ENDIF + +!### !### debug output +!### IF (I.eq.49 .AND. J.eq.26) THEN +!### WRITE(97,'(A,2I5,1p,4e12.4)') +!### & 'I,J, Caq, Cgas, KW, Ocean flux = ', +!### & I,J,OCDATA(I,J),CGAS,KW,FLUX +!### +!### WRITE(97,'(A,1p,3e12.4)') +!### & 'STT,AIRVOL(I,J,L), H = ', +!### & STT(I,J,L,N),AIRVOL(I,J,L),H +!### ENDIF + + ! convert flux to kg/gridbox/time step + FLUX = FLUX * AREA_M2 + + !### Debug + !###write(97,'(A,1p,E12.4)') 'rescaled flux = ',FLUX + + ! add to tracer mass and to global sum + STT(I,J,L,N) = STT(I,J,L,N) + FLUX + + !### make sure we get no negative concentrations + IF (STT(I,J,L,N).LT.0.) THEN + STT(I,J,L,N) = 0.0D0 + FLUX = 0.0D0 + ENDIF + + CH3ISUM(N) = CH3ISUM(N) + FLUX + + IF (ND36.GT.0) THEN + AD36(I,J,8) = AD36(I,J,8) + FLUX + ENDIF + ENDIF + ENDDO + ENDDO + + !================================================================= + ! -------------------------------------------- + ! Tracer #2: CH3I from Biomass burning + ! -------------------------------------------- + ! + ! Biomass burning CO is stored in BURNEMIS(IDBCO,:,:) + ! in [molec/cm3/s]. Convert to kg CH3I as follows: + ! + ! FLUXKG = flux * molar emission factor + ! * mole weight CH3I / molec/mole + ! * grid box volume + !================================================================= + + ! Convert biomass CO into biomass CH3I + N = 2 + L = 1 + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Grid box height [cm] + BXHEIGHT_CM = BXHEIGHT(I,J,L) * 100d0 + + !----------------------------------------------------------------- + ! Get emission flux in kg/cm3/time step + !FLUX = ECH3I * BIOMASS(I,J,IDBCO) + !----------------------------------------------------------------- + + ! Convert [molec/cm2/s] to [kg/cm3/timestep] + FLUX = ECH3I * BIOMASS(I,J,IDBCO) / BXHEIGHT_CM + FLUX = FLUX * 1.0D-3 * FMOL_CH3I * XMOL * DTSRCE + + ! Add to diagnostic array as kg/m2/time step + IF ( ND36 > 0 ) THEN + AD36(I,J,N) = AD36(I,J,N) + FLUX*BXHEIGHT_CM*1.0D4*1.0D+12 + ENDIF + + ! Convert to kg/grid box/time step + FLUX = FLUX * BOXVL(I,J,L) + + ! add to tracer mass and to global sum + STT(I,J,L,N) = STT(I,J,L,N) + FLUX + CH3ISUM(N) = CH3ISUM(N) + FLUX + ENDDO + ENDDO + + !================================================================= + ! -------------------------------------------- + ! Tracer #3: Wood burning + ! -------------------------------------------- + ! + ! Wood burning CO is stored in BIOFUEL(IDBFCO,:,:) + ! in [molec/cm^3/s]. Proceed as in biomass burning emissions + !================================================================= + + ! Make sure CO is a biofuel tracer + IF ( IDBFCO == 0 ) THEN + CALL ERROR_STOP( 'IDBFCO=0, check "tracer.dat"', 'EMISSCH3I' ) + ENDIF + + ! Now reference routine BIOFUEL_BURN from "biofuel_mod.f" (bmy, 9/12/00) + CALL BIOFUEL_BURN + + N = 3 + L = 1 + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Get flux as kg/cm3/time step + ! Now use IDBFCO to index biofuel burning CO (bmy, 3/20/01) + FLUX = ECH3I * BIOFUEL(IDBFCO,I,J) + FLUX = FLUX * 1.0D-3 * FMOL_CH3I * XMOL * DTSRCE + + ! Add to diagnostic array as kg/m2/time step + IF ( ND36 > 0 ) THEN + BXHEIGHT_CM = BXHEIGHT(I,J,L) * 100d0 + AD36(I,J,N) = AD36(I,J,N) + FLUX * BXHEIGHT_CM * + & 1.0D4 * 1.0D + 12 + ENDIF + + FLUX = FLUX * BOXVL(I,J,L) + + ! add to tracer mass and to global sum + STT(I,J,L,N) = STT(I,J,L,N) + FLUX + CH3ISUM(N) = CH3ISUM(N) + FLUX + ENDDO + ENDDO + + !================================================================= + ! -------------------------------------------- + ! Tracer #4: Rice paddy emissions + ! -------------------------------------------- + ! + ! EFCH4R contains emission flux in kg(CH3I)/m^2/s. + ! Simply convert to kg/grid box/time step and add to tracer mass + ! + ! NOTES: + ! (1) everything should be in window size except DXYP(J) + ! (2) DXYP(JREF) is now replaced by GET_AREA_M2(J). (bmy, 2/4/03) + !================================================================= + N = 4 + L = 1 + DO J = 1, JJPAR + + ! Grid box surface area [m2] + AREA_M2 = GET_AREA_M2( J ) + + DO I = 1, IIPAR + + ! First compute flux as kg/m2/time step + FLUX = EFCH4R(I,J) + FLUX = FLUX * DTSRCE + + ! Add to diagnostic array as kg/m2/time step + IF ( ND36 > 0 ) THEN + AD36(I,J,N) = AD36(I,J,N) + FLUX*1.0D+12 + ENDIF + + ! Now convert to kg/grid box/time step + FLUX = FLUX * AREA_M2 + + ! add to tracer mass and to global sum + STT(I,J,L,N) = STT(I,J,L,N) + FLUX + CH3ISUM(N) = CH3ISUM(N) + FLUX + ENDDO + ENDDO + + !================================================================= + ! -------------------------------------------- + ! Tracer #5: Wetland emissions + ! -------------------------------------------- + ! + ! EFCH4W contains emission flux in kg(CH3I)/m^2/s. + ! Simply convert to kg/grid box/time step and add to tracer mass + ! + ! NOTES: + ! (1) everything should be in window size except DXYP(J) + ! (2) DXYP(J) is now replaced by GET_AREA_M2(J) (bmy, 2/4/03) + !================================================================= + N = 5 + L = 1 + DO J = 1, JJPAR + + ! Grid box surface area [m2] + AREA_M2 = GET_AREA_M2( J ) + + DO I = 1, IIPAR + + ! First compute flux as kg/m2/time step + FLUX = EFCH4W(I,J) + FLUX = FLUX * DTSRCE + + ! Add to diagnostic array as kg/m2/time step + IF ( ND36 > 0 ) THEN + AD36(I,J,N) = AD36(I,J,N) + FLUX*1.0D+12 + ENDIF + + ! Now convert to kg/grid box/time step + FLUX = FLUX * AREA_M2 + + ! add to tracer mass and to global sum + STT(I,J,L,N) = STT(I,J,L,N) + FLUX + CH3ISUM(N) = CH3ISUM(N) + FLUX + ENDDO + ENDDO + + !================================================================= + ! ** Future : + ! (1) add soil fumigation (CH3I as replacement for CH3Br) + ! [may require change in ND36!] + !================================================================= + +!### Debug -- comment out for now +! !### Debug output in unit 97 ... set OUTLOG flag if wanted +! !### print the first 24 hours +! IF ( OUTLOG ) THEN +! IF ( TAU-TAUI < 24 .OR. MOD(FLOOR(TAU-TAUI),24) == 0 ) THEN +! WRITE( 97, * ) 'after emiss' +! +! DO N = 1, NTRACE +! WRITE( 97, '(''N, SUM STT(N) = '',i4,es12.4)' ) +! & N, SUM( STT(:,:,:,N) ) +! ENDDO +! ENDIF +! +! WRITE( 97, * ) +! ENDIF + + ! Make sure the next time is not the first emission time step ;-) + FIRSTEMISS = .FALSE. + + ! Return to calling program + END SUBROUTINE EMISSCH3I + +!------------------------------------------------------------------------------ + + SUBROUTINE CHEMCH3I +! +!****************************************************************************** +! Subroutine CHEMCH3I performs loss chemistry for methyl iodide (CH3I). +! (mgs, bey, bmy, 11/20/98, 8/16/05) +! +! If the LFASTJ C-preprocessor switch is set, then CHEMCH3I will invokes +! the FAST-J subroutines to compute local photolysis rates, which in +! turn determine local CH3I loss rates. Otherwise, a constant loss rate +! of 1/4 day is applied. +! +! NOTES: +! (1 ) Based on subroutine CHEMRN.F (bey, bmy, 1998) +! (2 ) Edited comments and changed constant lifetime from 3 to 4 days. +! (mgs, 3/12/99) +! (3 ) Now call INPHOT directly, rather than via FJ_INIT. (bmy, 10/4/99) +! (4 ) Make sure fast-J files "ratj.d" and "jv_spec.dat" include +! the information for CH3I branching ratios & quantum yields. +! (5 ) CHEMCH3I calls READER.F and CHEMSET.F to read in the "m.dat" and +! "chem.dat" files for CH3I. These is necessary to ensure that the +! J-Value mapping from Harvard indices to UCI indices will be done +! correctly. +! (6 ) CH3I loss will be computed from the surface to layer NSKIPL-1, +! which is specified in "input.ctm". +! (7 ) CH3I loss is now computed only for places where it is daylight +! (i.e. where SUNCOS > 0). This will prevent computing the +! exponential where the J-Values would be zero. (bmy, 11/23/98) +! (8 ) Add J-Value diagnostic for ND22 (bmy, 11/23/98) +! (9 ) Now use F90 syntax for declarations (bmy, 3/24/99) +! (10) Now "comsol.h" only contains variables relevant to SLOW-J, so +! we don't have to #include it here. +! (11) AD22 is now declared allocatable in "diag_mod.f". (bmy, 11/29/99) +! (12) LTJV is now declared allocatable in "diag_mod.f". +! Also made cosmetic changes, and updated comments. (bmy, 3/17/00) +! (13) Added ND65 diagnostic for CH3I loss (nad, bmy, 3/27/01) +! (14) Now reference the UVALBEDO array directly from "uvalbedo_mod.f". +! Remove ALBD from the argument list. Updated comments, cosmetic +! changes. (bmy, 1/15/02) +! (15) Now bundled into "ch3i_mod.f". (bmy, 1/23/02) +! (16) Removed obsolete code from 1/15/02 (bmy, 4/15/02) +! (17) Replaced all instances of IM with IIPAR and JM with JJPAR, in order +! to prevent namespace confusion for the new TPCORE (bmy, 6/25/02) +! (18) Now reference file unit IU_CTMCHEM from "file_mod.f" (bmy, 8/2/02) +! (19) Now reference SUNCOS, OPTD from "dao_mod.f". Now make FIRSTCHEM +! a local SAVEd variable. (bmy, 11/15/02) +! (20) Now use function GET_TS_CHEM from "time_mod.f" (bmy, 2/11/03) +! (21) Replace call to CHEMSET with call to READCHEM for SMVGEAR II. Replace +! NAMESPEC array with NAMEGAS array. Removed reference to "file_mod.f" +! since now the "smv2.log" file is opened in READER. (bdf, bmy, 4/21/03) +! (22) Now reference STT and N_TRACERS from "ch3i_mod.f". Also replace +! NSKIPL-1 with LLTROP for now. Now references AD65 from +! "diag_pl_mod.f". (bmy, 7/20/04) +! (23) FAST-J is now the default, so we don't need the LFASTJ C-preprocessor +! switch any more (bmy, 6/23/05) +! (24) Now use Nightingale et al [2000b] formulation for piston velocity +! (swu, bmy, 8/16/05) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : OPTD, SUNCOS + USE DIAG_MOD, ONLY : AD22, LTJV + USE DIAG_PL_MOD, ONLY : AD65 + USE UVALBEDO_MOD, ONLY : UVALBEDO + USE TIME_MOD, ONLY : GET_TS_CHEM + USE TRACER_MOD, ONLY : STT, N_TRACERS + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! ND36 +# include "comode.h" ! SPECNAME + + ! Local variables + LOGICAL, SAVE :: FIRSTCHEM = .TRUE. + REAL*8 :: DTCHEM, RLRAD, RDLOSS, T1L + REAL*8 :: TCHEMA, JVALUE + + ! Hardwired flag for CH3I species name + CHARACTER (LEN=4) :: SPECNAME + + ! Local loop and index variables + INTEGER :: I, IFNC, IBRCH, J, L, LN22, N, NK, NR + + ! Hardwired Logical flag for FAST-J + LOGICAL, PARAMETER :: DO_FASTJ = .TRUE. + + ! External functions + REAL*8, EXTERNAL :: FJFUNC + + !================================================================= + ! CHEMCH3I begins here! + !================================================================= + + ! convert DTCHEM from mn to sec. + DTCHEM = GET_TS_CHEM() * 60d0 + +!----------------------------------------------------------------------------- +!### Debug output in unit 97 ...comment out if necessary (bmy, 11/23/98) +!### print the first 24 hours +! IF (TAU-TAUI.LT.24) THEN +! write(97,*) 'before chem' +! DO N = 1, NTRACE +! write(97,'(A,I4,1p,E12.4)') ' N, SUM STT(N) = ', +! & N, SUM( STT(:,:,:,N) ) +! ENDDO +! ENDIF +!----------------------------------------------------------------------------- + + !============================================================== + ! If LFASTJ is defined in "define.h", then invoke FAST-J + ! subroutines to compute photolysis rates. The loss rate + ! of CH3I is dependent on the local photolysis rates. + ! + ! Initialize FAST-J quantities on the first timestep + !============================================================== + IF ( FIRSTCHEM ) THEN + + ! Call READER and READCHEM to read "mglob.dat" and + ! "globchem.dat" (these are needed for the J-value mapping). + CALL READER( FIRSTCHEM ) + CALL READCHEM + + ! Call INPHOT to initialize the fast-J variables. + CALL INPHOT( LLTROP, NPHOT ) + + ! Echo output + WRITE( 6,'(a)' ) 'Using U.C.I Fast-J Photolysis' + + ! Reset FIRSTCHEM + FIRSTCHEM = .FALSE. + ENDIF + + !============================================================== + ! For each chemistry time step, compute J-values and store + ! them in an internal array. SUNCOS, OPTD, and UVALBEDO are + ! needed for FAST-J. + !============================================================== + CALL FAST_J( SUNCOS, OPTD, UVALBEDO ) + + !============================================================== + ! NR is the loop over the number of reactions (NR=1 for now!) + ! Compute the proper branch number for each reaction, using + ! the same algorithm from CALCRATE.F. + ! + ! For each photo reaction, loop over the grid boxes (I-J-L) + ! and test whether the grid box is in sunlight or not. If the + ! grid box is a daytime box, then extract the proper photo + ! rate for that box. + ! + ! The photo rate for each grid box is in (s^-1) so multiply + ! this by the number of seconds in the chemistry interval and + ! use that as the loss rate (i.e. the arg of the exponential). + ! + ! You must specify NTRACE in "input.ctm". The number of CH3I + ! tracers from different sources ranges from N=1 to N=NTRACE: + ! N = 1: CH3I from oceans + ! N = 2: CH3I from biomass burning + ! N = 3: CH3I from wood burning + ! N = 4: CH3I from rice paddies + ! N = 5: CH3I from wetlands + ! + ! Also redefine RDLOSS so that it is just the exponential term, + ! which can then be multiplied by the tracer STT in one step + ! (bmy, 1/11/99) + !============================================================== + DO NR = 1, NPHOT + NK = NRATES(NCS) + NR + IFNC = DEFPRAT(NK,NCS) + 0.01D0 + IBRCH = 10.D0*(DEFPRAT(NK,NCS)-IFNC) + 0.5D0 + SPECNAME = NAMEGAS(IRM(1,NK,NCS)) + + ! Maybe later can replace this w/ the ann mean tropopause... + DO L = 1, LLTROP + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! SUNCOS > 0 means daytime! + IF ( SUNCOS( (J-1)*IGLOB + I ) > 0 ) THEN + JVALUE = FJFUNC( I, J, L, NR, IBRCH, SPECNAME ) + RLRAD = JVALUE * DTCHEM + RDLOSS = EXP( -RLRAD ) + + ! Loop over all individual CH3I tracers + ! (which have the same loss rate) + DO N = 1, N_TRACERS + STT(I,J,L,N) = STT(I,J,L,N) * RDLOSS + ENDDO + + ! ND22: J-value diagnostic + IF ( ND22 > 0 ) THEN + IF ( LTJV(I,J) > 0 .and. L <= LD22 ) THEN + AD22(I,J,L,1) = AD22(I,J,L,1) + JVALUE + ENDIF + ENDIF + + ! ND65: Loss rates for each tracer + IF ( ND65 > 0 ) THEN + IF ( L <= LD65 ) THEN + DO N = 1, N_TRACERS + AD65(I,J,L,N) = AD65(I,J,L,N) + + & ( STT(I,J,L,N) * JVALUE * DTCHEM ) + ENDDO + ENDIF + ENDIF + ENDIF + ENDDO + ENDDO + ENDDO + ENDDO + +!------------------------------------------------------------------------------ +! Prior to 6/22/03: +! Leave this commented here for now (bmy, 6/22/03) +!#else +! +! !============================================================== +! ! If LFASTJ is not set in "define.h", then treat the decay of +! ! CH3I as if it were radioactive decay. This is useful for +! ! testing. +! ! +! ! TCHEMA: first order loss rate in 1/s +! ! CH3I, lifetime 4 days : TCHEMA = 2.8935E-6 +! ! (old : CH3I, lifetime 3 days : TCHEMA = 3.85E-6) +! ! +! ! NOTE: If you modify CHEMCH3I so that it will handle more +! ! than one species, you must specify TCHEMA as an array, loop +! ! over N, and then compute RLRAD as: +! ! +! ! RLRAD = DTCHEM*TCHEMA(N) +! ! +! ! Also redefine RDLOSS so that it is just the exponential term, +! ! which can then be multiplied by the tracer STT in one step +! ! (bmy, 1/11/99) +! !============================================================== +! SPECNAME = 'CH3I' +! TCHEMA = 2.8935D-6 +! RLRAD = DTCHEM * TCHEMA +! RDLOSS = EXP( -RLRAD ) +! +! DO N = 1, N_TRACERS +! DO L = 1, LLTROP +! DO J = 1, JJPAR +! DO I = 1, IIPAR +! STT(I,J,L,N) = STT(I,J,L,N) * RDLOSS +! ENDDO +! ENDDO +! ENDDO +! ENDDO +! +!#endif +!------------------------------------------------------------------------------ + +!----------------------------------------------------------------------------- +!### Debug output in unit 97 ...comment out if necessary (bmy, 11/23/98) +!### print the first 24 hours +! IF (TAU-TAUI.LT.24) THEN +! write(97,*) 'after chem' +! DO N = 1, NTRACE +! write(97,'(A,I4,1p,E12.4)') ' N, SUM STT(N) = ', +! & N, SUM( STT(:,:,:,N) ) +! ENDDO +! ENDIF +!----------------------------------------------------------------------------- + + ! Return to calling program + END SUBROUTINE CHEMCH3I + +!------------------------------------------------------------------------------ + + END MODULE CH3I_MOD diff --git a/code/charpak_mod.f b/code/charpak_mod.f new file mode 100644 index 0000000..2e6288e --- /dev/null +++ b/code/charpak_mod.f @@ -0,0 +1,596 @@ +! $Id: charpak_mod.f,v 1.1 2009/06/09 21:51:50 daven Exp $ + MODULE CHARPAK_MOD +! +!****************************************************************************** +! Module CHARPAK_MOD contains routines from the CHARPAK string and character +! manipulation package used by GEOS-CHEM (bmy, 10/15/01, 7/20/04) +! +! CHARPAK routines by Robert D. Stewart, 1992. Subsequent modifications +! made for GEOS-CHEM by Bob Yantosca (1998, 2002, 2004). +! +! Module Routines: +! ============================================================================ +! (1 ) CNTMAT : Counts # of chars in STR1 that match a char in STR2 +! (2 ) COPYTXT : Writes chars from STR1 into STR2 +! (3 ) CSTRIP : Strip blanks and null characters from a string +! (4 ) ISDIGIT : Returns TRUE if a character is a numeric digit +! (5 ) STRREPL : Replaces characters w/in a string with replacement text +! (6 ) STRSPLIT : Convenience wrapper for TXTEXT +! (7 ) STRSQUEEZE : Squeezes text by removing white space from both ends +! (8 ) TRANLC : Translates text to LOWERCASE +! (9 ) TRANUC : Translates text to UPPERCASE +! (10) TXT2INUM : Converts a string of characters into an integer number +! (11) TXTEXT : Extracts a sequence of characters from a string +! +! GEOS-CHEM modules referenced by charpak_mod.f +! ============================================================================ +! none +! +! NOTES: +! (1 ) Moved "cntmat.f", "copytxt.f", "cstrip.f", "fillstr.f", "txt2inum.f", +! "txtext.f", into this F90 module for easier bookkeeping +! (bmy, 10/15/01) +! (2 ) Moved "tranuc.f" into this F90 module (bmy, 11/15/01) +! (3 ) Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Updated comments (bmy, 5/28/02) +! (4 ) Wrote a new file "strrepl.f", which replaces a character pattern +! within a string with replacement text. Moved "tranlc.f" into +! this module. Replaced calls to function LENTRIM with F90 +! intrinsic function LEN_TRIM. Removed function FILLSTR and +! replaced it w/ F90 intrinsic REPEAT. (bmy, 6/25/02) +! (5 ) Added routine STRSPLIT as a wrapper for TXTEXT. Also added +! routines STRREPL and STRSQUEEZE. (bmy, 7/30/02) +! (6 ) Added function ISDIGIT. Also replace LEN_TRIM with LEN in routine +! STRREPL, to allow us to replace tabs w/ spaces. (bmy, 7/20/04) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE CntMat(str1,str2,imat) +C +C Count the number of characters in str1 that match +C a character in str2. +C +C CODE DEPENDENCIES: +C Routine Name File +C LENTRIM CharPak +C +C DATE: JAN. 6, 1995 +C AUTHOR: R.D. STEWART +C COMMENTS: Revised slightly (2-5-1996) so that trailing +C blanks in str1 are ignored. Revised again +C on 3-6-1996. +C + CHARACTER*(*) str1,str2 + INTEGER imat + INTEGER L1,L2,i,j + LOGICAL again + + L1 = MAX(1,LEN_TRIM(str1)) + L2 = LEN(str2) + imat = 0 + DO i=1,L1 + again = .true. + j = 1 + DO WHILE (again) + IF (str2(j:j).EQ.str1(i:i)) THEN + imat = imat+1 + again = .false. + ELSEIF (j.LT.L2) THEN + j=j+1 + ELSE + again = .false. + ENDIF + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE CntMat + +!------------------------------------------------------------------------------ + + SUBROUTINE CopyTxt(col,str1,str2) +C +c PURPOSE: Write all of the characters in str1 into variable +C str2 beginning at column, col. If the length of str1 +C + col is longer than the number of characters str2 +C can store, some characters will not be transfered to +C str2. Any characters already existing in str2 will +C will be overwritten. +C +C CODE DEPENDENCIES: +C Routine Name File +C N/A +C +C DATE: DEC. 24, 1993 +C AUTHOR: R.D. STEWART +C + CHARACTER*(*) str2,str1 + INTEGER col,ilt1,i1,i,j,ic + + i1 = LEN(str2) + IF (i1.GT.0) THEN + ilt1 = LEN(str1) + IF (ilt1.GT.0) THEN + ic = MAX0(col,1) + i = 1 + j = ic + DO WHILE ((i.LE.ilt1).and.(j.LE.i1)) + str2(j:j) = str1(i:i) + i = i + 1 + j = ic + (i-1) + ENDDO + ENDIF + ENDIF + + ! Return to calling program + END SUBROUTINE CopyTxt + +!------------------------------------------------------------------------------ + + SUBROUTINE CSTRIP(text) +C +C PURPOSE: Strip blanks and null characters for the variable TEXT. +C +C COMMENTS: The original "text" is destroyed upon exit. +C +C CODE DEPENDENCIES: +C Routine Name File +C N/A +C +C AUTHOR: Robert D. Stewart +C DATE: May 19, 1992 +C + CHARACTER*(*) TEXT + INTEGER ilen,iasc,icnt,i + CHARACTER*1 ch + + ilen = LEN(text) + IF (ilen.GT.1) THEN + icnt = 1 + DO i=1,ilen + iasc = ICHAR(text(i:i)) + IF ((iasc.GT.32).AND.(iasc.LT.255)) THEN +C Keep character + ch = text(i:i) + text(icnt:icnt) = ch + icnt = icnt + 1 + ENDIF + ENDDO +C Fill remainder of text with blanks + DO i=icnt,ilen + text(i:i) = ' ' + ENDDO + ENDIF + + ! Return to calling program + END SUBROUTINE CSTRIP + +!------------------------------------------------------------------------------ + + FUNCTION ISDIGIT( ch ) RESULT( LNUM ) +C +C Returned as true if ch is a numeric character (i.e., one of +C the numbers from 0 to 9). +C +C CODE DEPENDENCIES: +C Routine Name File +C N/A +C +C DATE: NOV. 11, 1993 +C AUTHOR: R.D. STEWART +C +C NOTE: Changed name from ISNUM to ISDIGIT (bmy, 7/15/04) +C + CHARACTER*1 ch + INTEGER iasc + LOGICAL lnum + + iasc = ICHAR(ch) + lnum = .FALSE. + IF ((iasc.GE.48).AND.(iasc.LE.57)) THEN + lnum = .TRUE. + ENDIF + + ! Return to calling program + END FUNCTION ISDIGIT + +!------------------------------------------------------------------------------ + + SUBROUTINE StrRepl( STR, PATTERN, REPLTXT ) + + !================================================================= + ! Subroutine STRREPL replaces all instances of PATTERN within + ! a string STR with replacement text REPLTXT. + ! (bmy, 6/25/02, 7/20/04) + ! + ! Arguments as Input: + ! ---------------------------------------------------------------- + ! (1 ) STR : String to be searched + ! (2 ) PATTERN : Pattern of characters to replace w/in STR + ! (3 ) REPLTXT : Replacement text for PATTERN + ! + ! Arguments as Output: + ! ---------------------------------------------------------------- + ! (1 ) STR : String with new replacement text + ! + ! NOTES + ! (1 ) REPLTXT must have the same # of characters as PATTERN. + ! (2 ) Replace LEN_TRIM with LEN (bmy, 7/20/04) + !================================================================= + + ! Arguments + CHARACTER(LEN=*), INTENT(INOUT) :: STR + CHARACTER(LEN=*), INTENT(IN) :: PATTERN, REPLTXT + + ! Local variables + INTEGER :: I1, I2 + + !================================================================= + ! STRREPL begins here! + !================================================================= + + ! Error check: make sure PATTERN and REPLTXT have the same # of chars + IF ( LEN( PATTERN ) /= LEN( REPLTXT ) ) THEN + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a)' ) + & 'STRREPL: PATTERN and REPLTXT must have same # of characters!' + WRITE( 6, '(a)' ) 'STOP in STRREPL (charpak_mod.f)' + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + STOP + ENDIF + + ! Loop over all instances of PATTERN in STR + DO + + ! I1 is the starting location of PATTERN w/in STR + I1 = INDEX( STR, PATTERN ) + + ! If pattern is not found, then return to calling program + IF ( I1 < 1 ) RETURN + + ! I2 is the ending location of PATTERN w/in STR + I2 = I1 + LEN_TRIM( PATTERN ) - 1 + + ! Replace text + STR(I1:I2) = REPLTXT + + ENDDO + + ! Return to calling program + END SUBROUTINE StrRepl + +!------------------------------------------------------------------------------ + + SUBROUTINE StrSplit( STR, SEP, RESULT, N_SUBSTRS ) +! +!****************************************************************************** +! Subroutine STRSPLIT returns substrings in a string, separated by a +! separator character (similar to IDL's StrSplit function). This is mainly +! a convenience wrapper for CHARPAK routine TxtExt. (bmy, 7/11/02) +! +! Arguments as Input: +! ============================================================================ +! (1 ) STR (CHARACTER*(*)) : String to be searched (variable length) +! (2 ) SEP (CHARACTER*1 ) : Separator character +! +! Arguments as Output: +! ============================================================================ +! (3 ) RESULT (CHARACTER*255) : Array containing substrings (255 elements) +! (4 ) N_SUBSTRS (INTEGER ) : Number of substrings returned (optional) +! +! NOTES: +!****************************************************************************** +! + ! Arguments + CHARACTER(LEN=*), INTENT(IN) :: STR + CHARACTER(LEN=1), INTENT(IN) :: SEP + CHARACTER(LEN=*), INTENT(OUT) :: RESULT(255) + INTEGER, INTENT(OUT), OPTIONAL :: N_SUBSTRS + + ! Local variables + INTEGER :: I, IFLAG, COL + CHARACTER (LEN=255) :: WORD + + !================================================================= + ! STRSPLIT begins here! + !================================================================= + + ! Initialize + I = 0 + COL = 1 + IFLAG = 0 + RESULT(:) = '' + + ! Loop until all matches found, or end of string + DO WHILE ( IFLAG == 0 ) + + ! Look for strings beteeen separator string + CALL TXTEXT ( SEP, TRIM( STR ), COL, WORD, IFLAG ) + + ! Store substrings in RESULT array + I = I + 1 + RESULT(I) = TRIM( WORD ) + + ENDDO + + ! Optional argument: return # of substrings found + IF ( PRESENT( N_SUBSTRS ) ) N_SUBSTRS = I + + ! Return to calling program + END SUBROUTINE StrSplit + +!------------------------------------------------------------------------------ + + SUBROUTINE StrSqueeze( STR ) +! +!****************************************************************************** +! Subroutine STRSQUEEZE strips white space from both ends of a string. +! White space in the middle of the string (i.e. between characters) will +! be preserved as-is. Somewhat similar (though not exactly) to IDL's +! STRCOMPRESS function. (bmy, 7/11/02) +! +! Arguments as Input/Output: +! ============================================================================ +! (1 ) STR (CHAR*(*)) : String to be squeezed (will be overwritten in place!) +! +! NOTES: +!****************************************************************************** +! + ! Arguments + CHARACTER(LEN=*), INTENT(INOUT) :: STR + + !================================================================= + ! STRSQUEEZE begins here! + !================================================================= + STR = ADJUSTR( TRIM( STR ) ) + STR = ADJUSTL( TRIM( STR ) ) + + ! Return to calling program + END SUBROUTINE StrSqueeze + +!------------------------------------------------------------------------------ + + SUBROUTINE TRANLC(text) +C +C PURPOSE: Tranlate a character variable to all lowercase letters. +C Non-alphabetic characters are not affected. +C +C COMMENTS: The original "text" is destroyed. +C +C CODE DEPENDENCIES: +C Routine Name File +C N/A +C +C AUTHOR: Robert D. Stewart +C DATE: May 19, 1992 +C + CHARACTER*(*) text + INTEGER iasc,i,ilen + + ilen = LEN(text) + DO I=1,ilen + iasc = ICHAR(text(i:i)) + IF ((iasc.GT.64).AND.(iasc.LT.91)) THEN + text(i:i) = CHAR(iasc+32) + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE TRANLC + +!------------------------------------------------------------------------------ + + SUBROUTINE TRANUC(text) +C +C PURPOSE: Tranlate a character variable to all upper case letters. +C Non-alphabetic characters are not affected. +C +C COMMENTS: The original "text" is destroyed. +C +C CODE DEPENDENCIES: +C Routine Name File +C N/A +C +C AUTHOR: Robert D. Stewart +C DATE: May 19, 1992 +C + CHARACTER*(*) text + INTEGER iasc,i,ilen + + ilen = LEN(text) + DO i=1,ilen + iasc = ICHAR(text(i:i)) + IF ((iasc.GT.96).AND.(iasc.LT.123)) THEN + text(i:i) = CHAR(iasc-32) + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE TRANUC + +!------------------------------------------------------------------------------ + + SUBROUTINE Txt2Inum(fmat,txt,Inum,iflg) +C +C attempts to convert the string of characters +C in txt into a integer number. fmat is the +C VALID format specifier to use in the internal read +C statement. iflg is returned as a status flag indicating +C the success or failure of the operation. iflg <=0 if the +C operation was successful, and > 0 if it failed. +C +C COMMENTS: Generally, the Fxx.0 format should be used to convert +C string of characters to a number. +C +C AUTHOR: Robert D. Stewart +C DATE: DEC 24, 1992 +C +C CODE DEPENDENCIES: +C Routine Name File +C N/A +C + CHARACTER*(*) txt,fmat + INTEGER inum + INTEGER iflg + + READ(txt,fmt=fmat,iostat=iflg) inum + + ! Return to calling program + END SUBROUTINE Txt2Inum + +!------------------------------------------------------------------------------ + + SUBROUTINE TxtExt(ch,text,col,word,iflg) +C +C PURPOSE: TxtExt extracts a sequence of characters from +C text and transfers them to word. The extraction +C procedure uses a set of character "delimiters" +C to denote the desired sequence of characters. +C For example if ch=' ', the first character sequence +C bracketed by blank spaces will be returned in word. +C The extraction procedure begins in column, col, +C of TEXT. If text(col:col) = ch (any character in +C the character string), the text is returned beginning +C with col+1 in text (i.e., the first match with ch +C is ignored). +C +C After completing the extraction, col is incremented to +C the location of the first character following the +C end of the extracted text. +C +C A status flag is also returned with the following +C meaning(s) +C +C IF iflg = -1, found a text block, but no more characters +C are available in TEXT +C iflg = 0, task completed sucessfully (normal term) +C iflg = 1, ran out of text before finding a block of +C text. +C +C COMMENTS: TxtExt is short for Text Extraction. This routine +C provides a set of powerful line-by-line +C text search and extraction capabilities in +C standard FORTRAN. +C +C CODE DEPENDENCIES: +C Routine Name File +C CntMat CHARPAK.FOR +C TxtExt CHARPAK.FOR +C FillStr CHARPAK.FOR +C CopyTxt CHARPAK.FOR +C +C other routines are indirectly called. +C AUTHOR: Robert D. Stewart +C DATE: Jan. 1st, 1995 +C +C REVISIONS: FEB 22, 1996. Slight bug fix (introduced by a +C (recent = FLIB 1.04) change in the CntMat routine) +C so that TxtExt correctlyhandles groups of characters +C delimited by blanks). +C +C MODIFICATIONS by Bob Yantosca (6/25/02) +C (1) Replace call to FILLSTR with F90 intrinsic REPEAT +C + CHARACTER*(*) ch,text,word + INTEGER col,iflg + INTEGER Tmax,T1,T2,imat + LOGICAL again,prev + +C Length of text + Tmax = LEN(text) + +C Fill Word with blanks + WORD = REPEAT( ' ', LEN( WORD ) ) + + IF (col.GT.Tmax) THEN +C Text does not contain any characters past Tmax. +C Reset col to one and return flag = {error condition} + iflg = 1 + col = 1 + ELSEIF (col.EQ.Tmax) THEN +C End of TEXT reached + CALL CntMat(ch,text(Tmax:Tmax),imat) + IF (imat.EQ.0) THEN +C Copy character into Word and set col=1 + CALL CopyTxt(1,Text(Tmax:Tmax),Word) + col = 1 + iflg = -1 + ELSE +C Same error condition as if col.GT.Tmax + iflg = 1 + ENDIF + ELSE +C Make sure column is not less than 1 + IF (col.LT.1) col=1 + CALL CntMat(ch,text(col:col),imat) + IF (imat.GT.0) THEN + prev=.true. + ELSE + prev=.false. + ENDIF + T1=col + T2 = T1 + + again = .true. + DO WHILE (again) +C Check for a match with a character in ch + CALL CntMat(ch,text(T2:T2),imat) + IF (imat.GT.0) THEN +C Current character in TEXT matches one (or more) of the +C characters in ch. + IF (prev) THEN + IF (T2.LT.Tmax) THEN +C Keep searching for a block of text + T2=T2+1 + T1=T2 + ELSE +C Did not find any text blocks before running +C out of characters in TEXT. + again=.false. + iflg=1 + ENDIF + ELSE +C Previous character did not match ch, so terminate. +C NOTE: This is "NORMAL" termination of the loop + again=.false. + T2=T2-1 + iflg = 0 + ENDIF + ELSEIF (T2.LT.Tmax) THEN +C Add a letter to the current block of text + prev = .false. + T2=T2+1 + ELSE +C Reached the end of the characters in TEXT before reaching +C another delimiting character. A text block was identified +C however. + again=.false. + iflg=-1 + ENDIF + ENDDO + + IF (iflg.EQ.0) THEN +C Copy characters into WORD and set col for return + CALL CopyTxt(1,Text(T1:T2),Word) + col = T2+1 + ELSE +C Copy characters into WORD and set col for return + CALL CopyTxt(1,Text(T1:T2),Word) + col = 1 + ENDIF + ENDIF + + ! Return to calling program + END SUBROUTINE TxtExt + +!------------------------------------------------------------------------------ + + END MODULE CHARPAK_MOD diff --git a/code/cleanup.f b/code/cleanup.f new file mode 100644 index 0000000..ea74276 --- /dev/null +++ b/code/cleanup.f @@ -0,0 +1,246 @@ +! $Id: cleanup.f,v 1.2 2009/07/14 23:51:27 daven Exp $ + SUBROUTINE CLEANUP +! +!****************************************************************************** +! Subroutine CLEANUP deallocates the memory assigned to dynamic allocatable +! arrays just before exiting the GEOS-CHEM model. (bmy, 11/29/99, 10/2/07) +! +! NOTES: +! (1 ) CLEANUP is written in Fixed-Format F90. +! (2 ) Now calls CLEANUP_WETSCAV, which deallocates arrays from +! "wetscav_mod.f". (bmy, 3/9/00) +! (3 ) Add call to CLEANUP_SULFATE, which deallocates arrays from +! "sulfate_mod.f". Also now deallocate ND32 arrays. (bmy, 6/6/00) +! (4 ) Add call to CLEANUP_DAO, which deallocates arrays from "dao_mod.f". +! (bmy, 6/26/00) +! (5 ) Add call to CLEANUP_TAGGED_CO and CLEANUP_COMODE, which deallocates +! arrays from and "comode_mod.f". (bmy, 7/19/00) +! (6 ) Add call to CLEANUP_GLOBAL_OH and CLEANUP_COMODE, which deallocates +! arrays from "global_oh_mod.f". (bmy, 7/28/00) +! (7 ) Add calls to CLEANUP_BIOMASS and CLEANUP_BIOFUEL, which deallocates +! arrays from "biomass_mod.f" and "biofuel_mod.f". Also deallocate +! the AD32_bf array for the biofuel NOx diagnostic. (bmy, 9/12/00) +! (8 ) Add call to CLEANUP_DIAG51, to deallocate module arrays from +! "diag51_mod.f" (bmy, 11/29/00) +! (9 ) Removed obsolete code from 11/29/00 (bmy, 12/21/00) +! (10) Add call to CLEANUP_CH4, to deallocate module arrays from +! "global_ch4_mod.f" (bmy, 1/16/01) +! (11) Now deallocate the AD34 array. Also updated comments and +! made some cosmetic changes. (bmy, 3/15/01) +! (12) Now deallocate the AD12 array (bdf, bmy, 6/15/01) +! (13) Add call to CLEANUP_ACETONE, to deallocate module arrays from +! "acetone_mod.f" Also deallocate AD11 array. Also deallocate +! variables from dao_mod.f last, to try to avoid bus error on +! SGI (bmy, 8/3/01) +! (14) Added call to CLEANUP_UVALBEDO from "uvalbedo_mod.f". Also removed +! obsolete code from 9/01. Also only include references to CLEANUP_* +! subroutines in other modules for clarity. (bmy, 1/15/02) +! (15) Added call to CLEANUP_C2H6 from "c2h6_mod.f" (bmy, 1/25/02) +! (16) Added call to CLEANUP_AIRCRAFT_NOX from "aircraft_nox_mod.f" +! (bmy, 2/14/02) +! (17) Now deallocate CTNO2, CTHO2, LTNO2, LTHO2 arrays (rvm, bmy, 2/27/02) +! (18) Now reference CLEANUP_PLANEFLIGHT from "planeflight_mod.f". +! Now also deallocate AD01 and AD02 arrays. (mje, bmy, 8/7/02) +! (19) Now reference cleanup routines from "global_nox_mod.f", +! "global_hno3_mod.f", "global_no3_mod.f", "drydep_mod.f", and +! "rpmares_mod.f". (bmy, 12/16/02) +! (20) Now reference cleanup routine from "transport_mod.f" (bmy, 2/10/03) +! (21) Now reference cleanup routine from "pjc_pfix_mod.f" and +! "tpcore_fvdas_mod.f90". (bmy, 5/9/03) +! (22) Now reference cleanup routine from "toms_mod.f" (bmy, 7/14/03) +! (23) Now reference cleanup routine from "carbon_mod.f", "dust_mod.f", and +! "dust_dead_mod.f". (bmy, 7/14/03) +! (23) Now references cleanup routine from "lightning__nox_mod.f" +! (bmy, 4/14/04) +! (24) Now references cleanup routine from "seasalt_mod.f" (bmy, 4/26/04) +! (25) Now references cleanup routines from new modules (bmy, 7/20/04) +! (26) Now calls cleanup routine from "epa_nei_mod.f" (bmy, 11/5/04) +! (27) Now call CLEANUP_MERCURY from "mercury_mod.f" (eck, bmy, 12/7/04) +! (28) Now call CLEANUP_OCEAN_MERCURY from "ocean_mercury_mod.f". Also +! reordered the calling sequence. (sas, bmy, 1/21/05) +! (29) Now call CLEANUP_PBL_MIX from "pbl_mix_mod.f". Now call CLEANUP_DIAG41 +! from "diag41_mod.f". (bmy, 2/17/05) +! (30) Now calls CLEANUP_HCN_CH3CN from "hcn_ch3cn_mod.f (bmy, 6/23/05) +! (31) Now calls CLEANUP_DIAG04, CLEANUP_CO2, and CLEANUP_TROPOPAUSE +! (bmy, 8/15/05) +! (32) Now calls CLEANUP_LAI from "lai_mod.f", CLEANUP_MEGAN from +! "megan_mod.f" and CLEANUP_REGRID_1x1 from "regrid_1x1_mod.f" +! (tmf, bdf, bmy, 10/24/05) +! (33) Now calls CLEANUP_EMEP from "emep_mod.f" (bdf, bmy, 11/1/05) +! (34) Now calls CLEANUP_GC_BIOMASS and CLEANUP_GFED2_BIOMASS (bmy, 4/5/06) +! (35) Now calls CLEANUP_DIAG56 from "diag56_mod.f" and +! CLEANUP_LIGHTNING_NOX_NL from "lightning_nox_nl_mod.f" +! (ltm, bmy, 5/5/06) +! (36) Now references CLEANUP_BRAVO from "bravo_mod.f" and CLEANUP_EDGAR +! from "edgar_mod.f" (bmy, 7/6/06) +! (37) Now calls CLEANUP_H2_HD from "h2_hd_mod.f" and CLEANUP_GLOBAL_O1D +! from "global_o1d_mod.f". Remove call to CLEANUP_LIGHTNING_NOx_NL +! from "lightning_nox_nl_mod.f (hup, phs, bmy, 10/2/07) +! (38) Now calls GEOS5_EXIT_TPCORE_WINDOW to finalize the TPCORE for +! GEOS-5 nested window simulations (yxw, dan, bmy, 11/6/08) +! (39) Now references CLEANUP_CAC_ANTHRO (amv, phs, 3/10/08) +! (40) Now references CLEANUP_ARCTAS_SHIP (phs, 3/10/08) +! (41) Now references CLEANUP_VISTAS_ANTHRO (phs, 3/10/08) +! 07 Sep 2011 - P. Kasibhatla - Add modifications for GFED3 +!****************************************************************************** +! + ! References to F90 modules + USE ACETONE_MOD, ONLY : CLEANUP_ACETONE + USE AEROSOL_MOD, ONLY : CLEANUP_AEROSOL + USE AIRCRAFT_NOX_MOD, ONLY : CLEANUP_AIRCRAFT_NOX + USE ARCTAS_SHIP_EMISS_MOD, ONLY : CLEANUP_ARCTAS_SHIP + USE BIOMASS_MOD, ONLY : CLEANUP_BIOMASS + USE BIOFUEL_MOD, ONLY : CLEANUP_BIOFUEL + USE BRAVO_MOD, ONLY : CLEANUP_BRAVO + USE C2H6_MOD, ONLY : CLEANUP_C2H6 + USE CAC_ANTHRO_MOD, ONLY : CLEANUP_CAC_ANTHRO + USE CARBON_MOD, ONLY : CLEANUP_CARBON + USE CO2_MOD, ONLY : CLEANUP_CO2 + USE COMODE_MOD, ONLY : CLEANUP_COMODE + USE DAO_MOD, ONLY : CLEANUP_DAO + USE DIAG_MOD, ONLY : CLEANUP_DIAG + USE DIAG03_MOD, ONLY : CLEANUP_DIAG03 + USE DIAG04_MOD, ONLY : CLEANUP_DIAG04 + USE DIAG41_MOD, ONLY : CLEANUP_DIAG41 + USE DIAG50_MOD, ONLY : CLEANUP_DIAG50 + USE DIAG51_MOD, ONLY : CLEANUP_DIAG51 + USE DIAG51b_MOD, ONLY : CLEANUP_DIAG51b + USE DIAG51c_MOD, ONLY : CLEANUP_DIAG51c + USE DIAG51d_MOD, ONLY : CLEANUP_DIAG51d + USE DIAG_OH_MOD, ONLY : CLEANUP_DIAG_OH + USE DIAG_PL_MOD, ONLY : CLEANUP_DIAG_PL + USE DRYDEP_MOD, ONLY : CLEANUP_DRYDEP + USE DUST_MOD, ONLY : CLEANUP_DUST + USE DUST_DEAD_MOD, ONLY : CLEANUP_DUST_DEAD + USE EDGAR_MOD, ONLY : CLEANUP_EDGAR + USE EMEP_MOD, ONLY : CLEANUP_EMEP + USE EPA_NEI_MOD, ONLY : CLEANUP_EPA_NEI + USE ERROR_MOD, ONLY : DEBUG_MSG + USE GC_BIOMASS_MOD, ONLY : CLEANUP_GC_BIOMASS + USE GFED2_BIOMASS_MOD, ONLY : CLEANUP_GFED2_BIOMASS + USE GFED3_BIOMASS_MOD, ONLY : CLEANUP_GFED3_BIOMASS + USE GLOBAL_CH4_MOD, ONLY : CLEANUP_GLOBAL_CH4 + USE GLOBAL_HNO3_MOD, ONLY : CLEANUP_GLOBAL_HNO3 + USE GLOBAL_NO3_MOD, ONLY : CLEANUP_GLOBAL_NO3 + USE GLOBAL_NOX_MOD, ONLY : CLEANUP_GLOBAL_NOX + USE GLOBAL_O1D_MOD, ONLY : CLEANUP_GLOBAL_O1D + USE GLOBAL_OH_MOD, ONLY : CLEANUP_GLOBAL_OH + USE H2_HD_MOD, ONLY : CLEANUP_H2_HD + USE HCN_CH3CN_MOD, ONLY : CLEANUP_HCN_CH3CN + USE LAI_MOD, ONLY : CLEANUP_LAI + USE LIGHTNING_NOX_MOD, ONLY : CLEANUP_LIGHTNING_NOX + USE MEGAN_MOD, ONLY : CLEANUP_MEGAN + USE MERCURY_MOD, ONLY : CLEANUP_MERCURY + USE OCEAN_MERCURY_MOD, ONLY : CLEANUP_OCEAN_MERCURY + USE PBL_MIX_MOD, ONLY : CLEANUP_PBL_MIX + USE PJC_PFIX_MOD, ONLY : CLEANUP_PJC_PFIX + USE PLANEFLIGHT_MOD, ONLY : CLEANUP_PLANEFLIGHT + USE PRESSURE_MOD, ONLY : CLEANUP_PRESSURE + USE REGRID_1x1_MOD, ONLY : CLEANUP_REGRID_1x1 + USE SEASALT_MOD, ONLY : CLEANUP_SEASALT + USE SULFATE_MOD, ONLY : CLEANUP_SULFATE + USE TAGGED_CO_MOD, ONLY : CLEANUP_TAGGED_CO + USE TOMS_MOD, ONLY : CLEANUP_TOMS + USE TPCORE_FVDAS_MOD, ONLY : EXIT_TPCORE + USE TPCORE_GEOS5_WINDOW_MOD, ONLY : EXIT_GEOS5_TPCORE_WINDOW + USE TPCORE_GEOSFP_WINDOW_MOD,ONLY : EXIT_GEOSFP_TPCORE_WINDOW ! (lzh,02/01/2015) + USE TRACER_MOD, ONLY : CLEANUP_TRACER + USE TRANSPORT_MOD, ONLY : CLEANUP_TRANSPORT + USE TROPOPAUSE_MOD, ONLY : CLEANUP_TROPOPAUSE + USE UVALBEDO_MOD, ONLY : CLEANUP_UVALBEDO + USE VISTAS_ANTHRO_MOD, ONLY : CLEANUP_VISTAS_ANTHRO + USE WETSCAV_MOD, ONLY : CLEANUP_WETSCAV + USE ICOADS_SHIP_MOD, ONLY : CLEANUP_ICOADS_SHIP !(cklee,7/09/09) + USE RETRO_MOD, ONLY : CLEANUP_RETRO + USE RCP_MOD, ONLY : CLEANUP_RCP + + + IMPLICIT NONE + +# include "define.h" + + !================================================================= + ! CLEANUP begins here! + !================================================================= + + ! Echo info + WRITE( 6, 100 ) + 100 FORMAT( ' - CLEANUP: deallocating arrays now...' ) + + ! Call cleanup routines from individual F90 modules + CALL CLEANUP_ACETONE + CALL CLEANUP_AEROSOL + CALL CLEANUP_AIRCRAFT_NOX + CALL CLEANUP_ARCTAS_SHIP + CALL CLEANUP_BIOMASS + CALL CLEANUP_BIOFUEL + CALL CLEANUP_BRAVO + CALL CLEANUP_C2H6 + CALL CLEANUP_CAC_ANTHRO + CALL CLEANUP_CARBON + CALL CLEANUP_CO2 + CALL CLEANUP_COMODE + CALL CLEANUP_DAO + CALL CLEANUP_DIAG + CALL CLEANUP_DIAG03 + CALL CLEANUP_DIAG04 + CALL CLEANUP_DIAG41 + CALL CLEANUP_DIAG50 + CALL CLEANUP_DIAG51 + CALL CLEANUP_DIAG51b + CALL CLEANUP_DIAG51c + CALL CLEANUP_DIAG51d + CALL CLEANUP_DIAG_OH + CALL CLEANUP_DIAG_PL + CALL CLEANUP_DRYDEP + CALL CLEANUP_DUST_DEAD + CALL CLEANUP_DUST + CALL CLEANUP_EDGAR + CALL CLEANUP_EMEP + CALL CLEANUP_EPA_NEI + CALL CLEANUP_GC_BIOMASS + CALL CLEANUP_GFED2_BIOMASS + CALL CLEANUP_GFED3_BIOMASS + CALL CLEANUP_GLOBAL_CH4 + CALL CLEANUP_GLOBAL_HNO3 + CALL CLEANUP_GLOBAL_NO3 + CALL CLEANUP_GLOBAL_NOX + CALL CLEANUP_GLOBAL_NO3 + CALL CLEANUP_GLOBAL_O1D + CALL CLEANUP_GLOBAL_OH + CALL CLEANUP_H2_HD + CALL CLEANUP_HCN_CH3CN + CALL CLEANUP_LAI + CALL CLEANUP_LIGHTNING_NOX + CALL CLEANUP_MEGAN + CALL CLEANUP_MERCURY + CALL CLEANUP_OCEAN_MERCURY + CALL CLEANUP_PBL_MIX + CALL CLEANUP_PJC_PFIX + CALL CLEANUP_PLANEFLIGHT + CALL CLEANUP_PRESSURE + CALL CLEANUP_REGRID_1x1 + CALL CLEANUP_SEASALT + CALL CLEANUP_SULFATE + CALL CLEANUP_TAGGED_CO + CALL CLEANUP_TRANSPORT + CALL CLEANUP_TOMS + CALL CLEANUP_TRACER + CALL CLEANUP_TROPOPAUSE + CALL CLEANUP_UVALBEDO + CALL CLEANUP_VISTAS_ANTHRO + CALL CLEANUP_WETSCAV + CALL CLEANUP_ICOADS_SHIP !(cklee,7/09/09) + CALL CLEANUP_RETRO + CALL CLEANUP_RCP + +#if defined( GEOS_5 ) && defined( GRID05x0666 ) + CALL EXIT_GEOS5_TPCORE_WINDOW +#elif defined( GEOS_FP ) && defined( GRID025x03125 ) + CALL EXIT_GEOSFP_TPCORE_WINDOW ! (lzh, 02/01/2015) +#else + CALL EXIT_TPCORE +#endif + + ! Return to calling program + END SUBROUTINE CLEANUP diff --git a/code/cmn_fj.h b/code/cmn_fj.h new file mode 100644 index 0000000..4438790 --- /dev/null +++ b/code/cmn_fj.h @@ -0,0 +1,57 @@ +! $Id: cmn_fj.h,v 1.1 2009/06/09 21:51:52 daven Exp $ +! +!****************************************************************************** +! CMN_FJ.H -- Header file containing parameters and common +! blocks used to interface between Harvard chemistry and UC-Irvine +! Fast-J photolysis programs. +! +! Based on code from Oliver Wild (9 Jul 1999) +! +! NOTES: +! (1 ) Uses Fortran 90 declarations for parameters and variables +! (2 ) Pass CTM size parameters and preprocessor switches via CMN_SIZE. +! (3 ) Update JPMAX for new chemistry mechanism (amf, bmy, 4/20/00) +! (4 ) Return JPMAX to original setting (bmy, 9/25/00) +! (5 ) Return JPMAX to 55 for peroxy recycling (again) (bmy, 12/20/00) +! (6 ) Now need to use the window parameters IIPAR,JJPAR,LLPAR (bmy, 9/25/01) +! (7 ) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation. (bmy, 6/25/02) +! (8 ) Replaced ESIG array with ETAA and ETAB arrays for the hybrid +! pressure formulation. Also deleted PREST, since we don't need that +! anymore. (bmy, 8/23/02) +! (9 ) Removed ETAA and ETAB arrays. We now compute PJ directly from the +! GET_PEDGE routine. (bmy, 10/30/07) +! (10) Increase photolysis rxns JPMAX = 79 (tmf, 1/7/09) +! +! - Bob Yantosca [bmy@io.as.harvard.edu], 30 Oct 2007 +!****************************************************************************** +! +# include "CMN_SIZE" + + ! Global array sizes in longitude, latitude, altitude + INTEGER, PARAMETER :: IPAR = IIPAR + INTEGER, PARAMETER :: JPAR = JJPAR + INTEGER, PARAMETER :: LPAR = LLPAR + + ! max # of photolysis rxns = 4 + IPHOT (see comode.h) + INTEGER, PARAMETER :: JPMAX = 79 + + ! Variables for number of layers and number of photolysis rxns + INTEGER :: JPNL, JPPJ + COMMON /FJ_INTEG/ JPNL, JPPJ + + ! Branches for photolysis species + INTEGER :: BRANCH + COMMON /FJ_BRANCH/ BRANCH(JPMAX) + + ! Names of photolysis species + CHARACTER (LEN=4) :: RNAMES + COMMON /FJ_NAME/ RNAMES(JPMAX) + + ! Mapping array from Harvard species names to UCI species names + INTEGER :: RINDEX + COMMON /FJ_INDX/ RINDEX(JPMAX) + + ! Output J-values + REAL*8 :: ZPJ + COMMON /FJ_VALUE/ ZPJ(LPAR,JPMAX,IPAR,JPAR) diff --git a/code/commsoil.h b/code/commsoil.h new file mode 100644 index 0000000..16bbc85 --- /dev/null +++ b/code/commsoil.h @@ -0,0 +1,149 @@ +! $Id: commsoil.h,v 1.2 2012/03/01 22:00:26 daven Exp $ +! +!********************************************************************** +! * +! HARVARD ATMOSPHERIC CHEMISTRY MODELING GROUP * +! MODULE FOR SOIL NOx EMISSIONS * +! by Yuhang Wang, Gerry Gardner and Prof. Daniel Jacob * +! (Release V2.1) * +! * +! Contact person: Bob Yantosca (bmy@io.harvard.edu) * +! * +!********************************************************************** +! NOTES: +! (1 ) Be sure to force double precision with the DBLE function +! and the "D" exponent, wherever necessary (bmy, 10/6/99) +! (2 ) Changed RCS ID tag comment character from "C" to "!" to allow +! freeform compilation. Also added & continuation characters in +! column 73 to allow header files to be included in F90 freeform +! files. Updated comments, cosmetic changes. (bmy, 6/25/02) +! (3 ) Now use cpp switches to define 1x1 parameters. Also added +! space in the #ifdef block for the 1x125 grid (bmy, 12/1/04) +! (4 ) Bug fix: 2681 should be 2861 in NLAND (bmy, 9/22/06) +! (5 ) Set # of land boxes for GEOS-5 nested grids (yxw, dan, bmy, 11/6/08) +!********************************************************************** +! +! header file for soil NOx emissions + + ! The defined soil types + INTEGER, PARAMETER :: NSOIL = 11 + + ! Number of soil pulsing types + INTEGER, PARAMETER :: NPULSE = 3 + +#if defined( GRID4x5 ) + + ! There are 1118 land boxes for the 4 x 5 GLOBAL GRID + INTEGER, PARAMETER :: NLAND = 1118 + +#elif defined( GRID2x25 ) + + ! There are 3920 land boxes for the 2 x 2.5 GLOBAL GRID + INTEGER, PARAMETER :: NLAND = 3920 + +#elif defined( GRID1x125 ) + + !%%% NOTE: still to be determined + INTEGER, PARAMETER :: NLAND = 9999 + +#elif defined( GRID1x1 ) && defined( NESTED_CH ) + + ! There are 2861 land points for the 1x1 CHINA nested grid + INTEGER, PARAMETER :: NLAND = 2861 + +#elif defined( GRID1x1 ) && defined( NESTED_NA ) + + ! There are 2118 land points for the 1x1 N. AMERICA nested grid + INTEGER, PARAMETER :: NLAND = 2118 + +#elif defined( GRID1x1 ) + + ! There are 17174 land points for the 1x1 GLOBAL grid + INTEGER, PARAMETER :: NLAND=17174 + +#elif defined( GRID05x0666 ) && defined( NESTED_CH ) && !defined( NESTED_SD ) + + ! There are 8261 land points for the 0.5 x 0.666 CHINA nested grid + INTEGER, PARAMETER :: NLAND = 8261 + +#elif defined( GRID05x0666 ) && defined( NESTED_NA ) && !defined( NESTED_SD ) + + INTEGER, PARAMETER :: NLAND = 8568 + +#elif defined( GRID05x0666 ) && (defined( NESTED_NA ) || defined( NESTED_CH )) && defined( NESTED_SD ) + + ! Parameters for smaller domain + INTEGER, PARAMETER :: NLAND = 5153 + +#elif defined( GRID025x03125 ) && defined( NESTED_CH ) + + !%%% NOTE: still to be determined, use fudge factor for now + !%%% need to check (lzh, 02/01/2015) + INTEGER, PARAMETER :: NLAND =24261 + +#elif defined( GRID025x03125 ) && defined( NESTED_NA ) + + !%%% NOTE: still to be determined, use fudge factor for now + INTEGER, PARAMETER :: NLAND =24261 + +#elif defined( GRID025x03125 ) && defined( SEAC4RS ) + + !%%% NOTE: still to be determined, use fudge factor for now + INTEGER, PARAMETER :: NLAND = 5536 + +#endif + + +! water/desert/ice//Trop. Rain. Forst.//conifers//dry deciduous// +! other deciduous//woodland//grassland//agriculture (other than rice) +! rice paddies//wetland/tundra + INTEGER INDEXSOIL(2,NLAND) !i,j of the grid + REAL*8 SOILPULS(NPULSE+1,NLAND) + !tracking of wet/dry & three types of pulsing (Y&L, 94) + REAL*8 SOILPREP(2,NLAND) !two month observed precip + REAL*8 SOILFERT(NLAND) !ferterlizers + REAL*8 PULSFACT(NPULSE) !pulsing factors + REAL*8 PULSDECAY(NPULSE) !pulsing decay per timestep + REAL*8 SOILNOX(IGLOB,JGLOB) !stores output + + INTEGER NCONSOIL(NVEGTYPE) !olson->soil type,nvegtype in commbio.h + REAL*8 CANOPYNOX(MAXIJ,NTYPE) !track NOx within canopy dry dep. + REAL*8 SOILTA(NSOIL),SOILTB(NSOIL),SOILAW(NSOIL),SOILAD(NSOIL) + REAL*8 SOILEXC(NSOIL) !canopy wind extinction coeff. + + COMMON /SOIL/ SOILNOX, INDEXSOIL, NCONSOIL, SOILPULS, & + & SOILPREP, SOILFERT, CANOPYNOX + + ! The correct sequence of PULSFACT is 5, 10, 15 + DATA PULSFACT / 5.D0, 10.D0, 15.D0 / + + ! PULSDECAY now contains the correct decay factors from Yienger & Levy + DATA PULSDECAY / 0.805D0, 0.384D0, 0.208D0 / + + ! SOILTA = Coefficient used to convert from surface temperture to + ! soil temperature + DATA SOILTA /0.D0, 0.84D0, 0.84D0, 0.84D0, 0.84D0, & + & 0.66D0, 0.66D0, 1.03D0, 1.03D0, 0.92D0, & + & 0.66D0/ + + ! SOILTB = Coefficient used to convert from surface temperture to + ! soil temperature + DATA SOILTB /0.D0, 3.6D0, 3.6D0, 3.6D0, 3.6D0, & + & 8.8D0, 8.8D0, 2.9D0, 2.9D0, 4.4D0, & + & 8.8D0/ + + ! SOILAW = Wet biome coefficient + DATA SOILAW /0.D0, 2.6D0, 0.03D0, 0.06D0, 0.03D0, & + & 0.17D0, 0.36D0, 0.36D0, 0.36D0, 0.003D0, & + & 0.05D0/ + + ! SOILAD = Dry biome coefficient + DATA SOILAD /0.D0, 8.6D0, 0.22D0, 0.40D0, 0.22D0, & + & 1.44D0, 2.65D0, 2.65D0, 2.65D0, 0.003D0, & + & 0.37D0/ + + ! SOILEXC = Canopy wind extinction coeff. + DATA SOILEXC /0.1D0, 4.D0, 4.D0, 4.D0, 4.D0, & + & 2.D0, 1.D0, 2.D0, 2.D0, 0.5D0, & + & 0.1D0/ + diff --git a/code/comode.h b/code/comode.h new file mode 100644 index 0000000..9c2c2f7 --- /dev/null +++ b/code/comode.h @@ -0,0 +1,768 @@ +! $Id: comode.h,v 1.1 2009/06/09 21:51:50 daven Exp $ +! +!****************************************************************************** +! Header file COMODE contains common blocks and variables for SMVGEAR II. +! (M. Jacobson 1997; bdf, bmy, 4/23/03, 6/1/06) +! +! NOTES: +! (1 ) Removed many commented-out common blocks not needed for GEOS-CHEM. +! Also updated comments. Also make sure that MAXGL3 is dimensioned +! for at least NNPAR tracers. Add NNADDG and NKSPECG for DMS+OH+O2 +! rxn. COEF12 and QRM2 are now obsolete for SMVGEAR II. (bmy, 4/23/03) +! (2 ) Added ICH4 to the /SPECIE2/ common block for interannual-varying +! CH4 concentration. Added variables for latitude distribution of +! CH4 to the /SPECIE3/ common block. (bmy, 7/1/03) +! (3 ) Added ITS_NOT_A_ND65_FAMILY to the /LPL/ common block for the ND65 +! production/loss diagnostic. Comment out counter variables, you can +! get the same info w/ a profiling run. Updated comments, cosmetic +! changes. (bmy, 7/9/03) +! (4 ) Removed the following variables from common blocks which are not needed +! for GEOS-CHEM: COLENG, AERSURF, VHMET1, VHMET, VMET3, CINIT, RHO3, +! GRIDVH, CSUMA1, XELRAT, T1BEG, T2BEG, T1FIN, T2FIN, DECLIN, RAGSUT, +! SINDEC, COSDEC, SIGMAL, PRESSL, RHOA, DSIG_SMV, TEMPL, VMET, SIGDIF, +! TMORN, PRESSC, XLAT, XLON, DMERIDUT, GRIDAREA, DSX, XLONUT, DSY, +! SINXLAT, COSXLAT, HMETT, HMET1, HMET2, RSET, RRIS, TZDIF, ZENRAT0, +! ZENRAT1, MLOPJ, REORDER_SAVE, RHO3K, GRIDVH3K, FIELDXY, FIELDYZ, +! FIELDXZ, RATMIX, GQSCHEM, C, QPRODA, QPRODB, QPRODC, QPRODD, QPROD, +! CINP, NUMSDT, NKSDT, PRATE. MONTHP, KYEAR, LDMONTH, ININT, ICLO, +! JCLO, FIELD1, MZLO, MZLO2, MZHI0, MZHI1, KZLO1, KZLO2, KZHI0, KZHI1, +! IHIZ1, IHIZ2, IHIZ3, PRESS5KM, KGRP, IABOVK, MROTAT1, MINROT1, +! NUMSUBS, LSPECEMIS, MROTAT2, MINROT2, MAXPOS, NOGAINR, NOLOSSR, +! MAXSTEPS, YLOW, HMAXDAY, KPHT, KRDD, KMIX, KINS, KGCO, ABHSUMK, DX0, +! DY0, XU0, DTOUT, CONPSUR, DXLONG, DYLAT, SWLONDC, CONSTIM, SWLATDC, +! UTSECY, TOTSEC, FINHOUR, FINMIN, FINSEC, TFROMID, ZENFIXED, ZENITH, +! DENCONS, HALFDAY, GRAVC, FOURPI, TWOPI, REARTH, RPRIMB, AVOG1, +! HALF, THIRD, THRPI2, PID180, PID2, SCTWOPI, AMRGAS, TWPISC. +! This should free up more memory for runs. (bmy, 7/16/03) +! (5 ) Split off NOCC into the /CHEM3B/ common block, since it doesn't need +! to be held THREADPRIVATE. Removed /DKBLOOP/ and /DKBLOOP5/, since +! these contain variables which are used locally within either +! "calcrate.f" or "smvgear.f". Cosmetic changes. (bmy, 7/28/03) +! (6 ) Add NKN2O5 to /CHEM4/ common block to flag N2O5 hydrolysis rxn. +! (mje, bmy, 8/7/03) +! (7 ) Eliminated SMALLCHEM cpp switch (bmy, 12/2/03) +! (8 ) Now set MAXGL3 = NNPAR for new # of tracers (bmy, 4/6/04) +! (9 ) Remove obsolete LGEOSCO and FULLCHEM Cpp switches (bmy, 6/24/05) +! (10) For COMPAQ, put IRMA, IRMB in /INMTRATE2/ common block. For COMPAQ, +! also declare /INMTRATE2/ THREADPRIVATE. (Q. Liang, bmy, 10/17/05) +! (11) Now remove AVG, BOLTG, RGAS, SCDAY, BK, EIGHTDPI, RSTARG, WTAIR, +! ONEPI, CONSVAP, SMAL1, SMAL2, SMAL3 from common blocks and declare +! these as parameters. (bec, bmy, 3/29/06) +! (12) Added ILISOPOH, the index of ISOP lost to OH (dkh, bmy, 6/1/06) +! (13) Added NKHO2 to /CHEM4/ common block to flag HO2 aerosol uptake +! (jaegle 02/26/09) +! (14) Add NNADDF and NNADDH to /CHEM4/ for HOC2H4O rxns +! Add NKHOROI and NKHOROJ to /CHEM4/ for HOC2H4O rxns in EP photolysis +! (tmf, 3/6/09) +! (15) Added NKSPECF, NKSPECH to /IDICS/ for C2H4 chemistry (tmf, 3/6/09) +! (16) Increase IGAS, MAXGL, MAXGL2, NMRATE, IPHOT (tmf, 3/6/09) +!****************************************************************************** +! +C CCCCCCC OOOOOOO M M OOOOOOO DDDDDD EEEEEEE +C C O O M M M M O O D D E +C C O O M M M O O D D EEEEEEE +C C O O M M O O D D E +C CCCCCCC OOOOOOO M M OOOOOOO DDDDDD EEEEEEE +C +C ********************************************************************* +C * THIS IS THE COMMON BLOCK FOR "SMVGEAR" AND "MIE," TWO ORDINARY * +C * DIFFERENTIAL EQUATION SOLVERS. THE REFERENCE FOR THE CODES IS * +C * * +C * JACOBSON M. Z. AND TURCO R. P. (1993) SMVGEAER: A SPARSE- * +C * MATRIX, VECTORIZED GEAR CODE FOR ATMOSPHERIC MODELS. * +C * SUBMITTED TO ATMOSPHERIC ENVIRONMENT, PART A. MAY 20, 1993 * +C * * +C * COMODE.H SETS PARAMETER VALUES AND SERVES AS A COMMON BLOCK FOR * +C * ALL DIMENSIONED AND NON-DIMENSIONED VARIABLES. COMODE.H ALSO * +C * DEFINES EACH PARAMETER, BUT DATA FILE DEFINE.DAT EXPLAINS NON- * +C * DIMENSIONED VARIABLES. INDIVIDUAL SUBROUTINES DEFINE DIMENSIONED * +C * VARIABLES. * +C ********************************************************************* +C +C ********************************************************************* +C * SET PARAMETERS * +C ********************************************************************* +C +C ****************** COORDINATE-SYSTEM PARAMETERS ********************* +C +C ILAT = MAXIMUM NUMBER OF LATITUDE(ILAT) GRID POINTS +C ILONG = MAXIMUM NUMBER OF LONGITUDE(ILONG) GRID POINTS +C IMLOOP = ILAT * ILONG - USED FOR MORE EFFICIENT ARRAYS +C IVERT = MAXIMUM NUMBER OF LAYERS +C ILAYER = MAXIMUM OF LAYER BOUNDARIES +C KBLOOP = MAXIMUM NUMBER OF GRID POINTS IN A VECTORIZED BLOCK +C SHOULD RANGE FROM 512 (BELOW WHICH VECTORIZATION DECREASES) +C TO 1024 (ABOVE WHICH, ARRAY SPACE IS LIMITED) +C MXBLOCK = MAXIMUM NUMBER OF GRID POINT BLOCKS +C MAXDAYS = MAXIMUM NUMBER OF DAYS FOR THE MODEL TO RUN +C + + INTEGER ILAT,ILONG,IVERT,IPLUME,IPVERT,ITLOOP,KBLOOP,MXBLOCK + INTEGER IMLOOP,ILAYER,ILTLOOP,MAXDAYS + PARAMETER (ILAT = JJPAR ) + PARAMETER (ILONG = IIPAR ) + + ! LLTROP is the max number of tropospheric levels + PARAMETER (IVERT = LLTROP ) + + ! GEOS-CHEM does not use plumes...set IPLUME=0 + PARAMETER (IPLUME = 0 ) + PARAMETER (IPVERT = IVERT + IPLUME ) + PARAMETER (ITLOOP = ILAT * ILONG * IPVERT ) + + ! Regular + !PARAMETER (KBLOOP = 64 ) + PARAMETER (KBLOOP = 24 ) + PARAMETER (IMLOOP = ILAT * ILONG ) + PARAMETER (ILAYER = IVERT + 1 ) + PARAMETER (ILTLOOP = IMLOOP * ILAYER ) + PARAMETER (MAXDAYS = 1000 ) +C Debug +C PARAMETER (KBLOOP = 1 ) + PARAMETER (MXBLOCK = 16 + ITLOOP/KBLOOP ) +C +C ************************* TRACER PARAMETERS **************************** +C IDEMS = EMISSION ID NUMBER (WHICH SPECIES) + INTEGER IDEMS + ! NEMPARA = max no. of anthropogenic emissions + ! NEMPARB = max no. of biogenic emissions + COMMON /JTRCID/ IDEMS(NEMPARA+NEMPARB) +C +C ************************* GAS-PHASE PARAMETERS ********************** +C +C IGAS = MAXIMUM NUMBER OF GASES, ACTIVE + INACTIVE +C IAERTY = MAXIMUM NUMBER OF AQUEOUS CHEMISTRY SPECIES (SET = 1 +C HERE SINCE NO AQUEOUS CHEMISTRY IS INCLUDED) +C NMRATE = MAXIMUM NUMBER OF RATES CONSTANTS (MAX # REACTIONS) +C IPHOT = MAXIMUM NUMBER OF PHOTO RATES +C NMTRATE = MAXIMUM NUMBER OF KINETIC + PHOTO REACTIONS +C NMQRATE = MAXIMUM NUMBER OF AQUEOUS CHEMICAL REACTIONS PLUS PHOTO +C PROCESSES (SET = 1 HERE SINCE NO AQUEOUS CHEMISTRY INCLUDED) +C NMRPROD = MAXIMUM NUMBER OF SPECIES IN A REACTION RATE +C NMDEAD = MAXIMUM NUMBER OF DEAD SPECIES +C MAXGL = MAXIMUM NUMBER OF GAINS / LOSSES FOR EACH CHEMICAL SPECIES. +C MAXGL2 = AN ARRAY DIMENSION SMALLER THAN MAXGL +C MAXGL3 = AN ARRAY DIMENSION SMALLER THAN MAXGL2 +C ICS = NUMBER OF TYPES OF CHEMISTRY: up to 3 for gas phase +C ICP = TYPES OF CHEMISTRY * 2 (ONE FOR DAY, ONE FOR NIGHT) +C MORDER = MAXIMUM ORDER FOR GEAR PARAMETERS FOR DIMENSION PURPOSES +C + INTEGER IGAS,IAERTY,NMRATE,IPHOT,NMTRATE,NMQRATE,NMRPROD,NMDEAD + INTEGER MAXGL,MAXGL2,MAXGL3,MAXGL4,ICS,ICP,MORDER,IPHOT8,IMISC + INTEGER IMASBAL,IALTS,MXCOF + + ! Updated for SMVGEAR II (bdf, bmy, 4/1/03) + PARAMETER ( IGAS = 200, IAERTY = 1 ) + PARAMETER ( NMRATE = 510, IPHOT = 85 ) + PARAMETER ( NMTRATE = NMRATE + IPHOT, NMQRATE = 1 ) + PARAMETER ( NMRPROD = 25, NMDEAD = 100 ) + PARAMETER ( MAXGL = 750, MAXGL2 = 90 ) + PARAMETER ( MAXGL3 = NNPAR, MAXGL4 = 10 ) + PARAMETER ( ICS = 3, ICP = 2*ICS ) + PARAMETER ( MORDER = 7 ) + PARAMETER ( IPHOT8 = IPHOT + 8, IMISC = 100 ) + PARAMETER ( IMASBAL = 9, IALTS = 22 ) + PARAMETER ( MXCOF = 5 ) +C +C ****************** PARAMETERS TO MINIMIZE ARRAY SPACE *************** +C +C MXGSAER = LARGER OF IGAS, IAERTY +C MXRATE = LARGER OF NMTRATE, NMQRATE +C MXCC2 = LARGER OF MXGSAER, MXARRAY +C MXCOUNT1.. = ARRAYS SIZES USED TO MINIMIZE MATRIX SPACE +C MXARRAY = MAXIMUM ONE-DIMENSIONAL ARRAY-LENGTH OF SPARSE MATRIX +C + INTEGER MXGSAER,MXRATE,MXARRAY,MXCC2,MXCOUNT1,MXCOUNT2,MXCOUNT3, + 1 MXCOUNT4,MXHOLD + PARAMETER( MXGSAER = IGAS) + PARAMETER( MXRATE = NMTRATE) + PARAMETER( MXARRAY = 3000) + PARAMETER( MXCC2 = MXARRAY) + PARAMETER( MXCOUNT1 = MXGSAER * MAXGL3 * 3) + PARAMETER( MXCOUNT2 = MXGSAER * MAXGL3 * 7) + PARAMETER( MXCOUNT3 = MXGSAER * 50) + PARAMETER( MXCOUNT4 = MXGSAER * 20) + PARAMETER( MXHOLD = 250) +C +C +C ********************************************************************* +C * SET CHARACTER LENGTHS * +C ********************************************************************* +C + CHARACTER*14 NAMESPEC, NAMD, + 1 APGASA, APGASB, APGASC, APGASD, APGASE, + 2 APGASF, APGASG, APGASH, IFSORM, + 3 XINP, RINP + CHARACTER*14 NAMEGAS, NAMEMB, + 1 JST, NAMENCS, ACORNER, SINP, NAMEPHOT, CHEMTYP + CHARACTER*4 DINP, DINPLAST + CHARACTER*2 SPECIAL, SPECL +C + CHARACTER*80 HEADING, COMMENT +C +C ********************************************************************* +C * SET CHARACTER DIMENSIONS * +C ********************************************************************* +C + COMMON / CHARAC / + 1 APGASA, APGASB, APGASC, APGASD, APGASE, + 2 APGASF, APGASG, APGASH, IFSORM, + 3 DINP, HEADING, COMMENT, + 4 JST, ACORNER, SPECIAL, DINPLAST + + COMMON / CHAR2 / + 1 XINP( IMISC), RINP( IMISC), SINP( IMISC), + 2 NAMEMB( IMASBAL), CHEMTYP( ICS), NAMD( NMDEAD), + 3 SPECL( MXCOF) + + COMMON / CHAR3 / + 1 NAMESPEC(0:IGAS,ICS), NAMEGAS(0:IGAS), NAMENCS(0:MXGSAER,ICS) + + COMMON / CHAR4 / + 2 NAMEPHOT(NMRPROD,IPHOT) +C +C ********************************************************************* +C * SET REAL AND INTEGER NON-ARRAY VARIABLES * +C ********************************************************************* +C + !--------------------------------------------------------------- + ! Physical constants + ! (now make these PARAMETERS instead of COMMON block variables) + !--------------------------------------------------------------- + + ! Avogadro's # + REAL*8, PARAMETER :: AVG = 6.02252d+23 + + ! Boltzmann's constant [erg/K] + REAL*8, PARAMETER :: BK = 1.38054d-16 + REAL*8, PARAMETER :: BOLTG = 1.38054d-16 + + ! Condensation vapor pressure ?????? + REAL*8, PARAMETER :: CONSVAP = 6.1078d+03 / BOLTG + + ! PI (same value as in CMN_GCTM) and related quantities + REAL*8, PARAMETER :: ONEPI = 3.14159265358979323d0 + REAL*8, PARAMETER :: EIGHTDPI = 8.d0 / ONEPI + + ! Gas constant [erg/K/mole] + REAL*8, PARAMETER :: RGAS = BOLTG * AVG + + ! Universal gas constant [g/cm2/s2/mole/K] + REAL*8, PARAMETER :: RSTARG = 8.31450d+07 + + ! Seconds per day + REAL*8, PARAMETER :: SCDAY = 86400.0d0 + + ! Molecular weight of air + REAL*8, PARAMETER :: WTAIR = 28.966d0 + + !--------------------------------------------------------------- + ! Small number tolerances + ! (now make these PARAMETERS instead of COMMON block variables) + !--------------------------------------------------------------- + + REAL*8, PARAMETER :: SMAL1 = 1d-06 + REAL*8, PARAMETER :: SMAL2 = 1.0d-99 + REAL*8, PARAMETER :: SMAL3 = 1d-50 + + + INTEGER :: NLAT, NLONG, NLAYER, NVERT + INTEGER :: NLOOP, NTLOOP, KULOOP, NTSPECGAS + INTEGER :: NMASBAL, KSLOOP, NTLOOPUSE, NPVERT + INTEGER :: NTTLOOP, NIJLOOP + COMMON /CTLLOOP/ NLAT, NLONG, NLAYER, NVERT, + & NLOOP, NTLOOP, KULOOP, NTSPECGAS, + & NMASBAL, KSLOOP, NTLOOPUSE, NPVERT, + & NTTLOOP, NIJLOOP + + ! /CTLLOOP2/ needs to be declared THREADPRIVATE (bmy, 7/16/03) + INTEGER :: KTLOOP, JLOOPLO, IFSUN + COMMON /CTLLOOP2/ KTLOOP, JLOOPLO, IFSUN + + INTEGER :: ICOORD, IFPRAT, INCVMIX, IFSOLVE + INTEGER :: IFURBAN, IFTROP, IFSTRAT, ISL + INTEGER :: IGLOBCHEM, ITESTGEAR, IFSIN, IFBOX + COMMON /CTLPROC/ ICOORD, IFPRAT, INCVMIX, IFSOLVE, + & IFURBAN, IFTROP, IFSTRAT, ISL, + & IGLOBCHEM, ITESTGEAR, IFSIN, IFBOX + + INTEGER :: IPRGASA, IPRGASB, IPRGASC, IPRGASD + INTEGER :: IPRGASE, IPRGASF, IPRGASG, IPRGASH + INTEGER :: IPRGASLO, IPRGASHI, NUMPRG, IPGMTOT + INTEGER :: IOXSEC, IOSPEC, IOREAC, IPRTEMP + INTEGER :: IPRMANY, IPREADER, IPRMET, IPMASBUD + INTEGER :: IFPR1, IPONEND, IPRATES, IPRPRESS + INTEGER :: IUSRDUM, IGRIDZ, IPGASES, INCXY + INTEGER :: INCXZ, INCYZ, IGRIDX, IGRIDY + INTEGER :: LXOUT, LYOUT, LLOOP, LLOOP2 + INTEGER :: LZOUT + COMMON /CTLPRNT/ IPRGASA, IPRGASB, IPRGASC, IPRGASD, + & IPRGASE, IPRGASF, IPRGASG, IPRGASH, + & IPRGASLO, IPRGASHI, NUMPRG, IPGMTOT, + & IOXSEC, IOSPEC, IOREAC, IPRTEMP, + & IPRMANY, IPREADER, IPRMET, IPMASBUD, + & IFPR1, IPONEND, IPRATES, IPRPRESS, + & IUSRDUM, IGRIDZ, IPGASES, INCXY, + & INCXZ, INCYZ, IGRIDX, IGRIDY, + & LXOUT, LYOUT, LLOOP, LLOOP2, + & LZOUT + + REAL*8 :: TINTERVAL, CHEMINTV, TIME, OXYCONS + REAL*8 :: HMAXNIT, FRACDEC + COMMON /XYGRID/ TINTERVAL, CHEMINTV, TIME, OXYCONS, + & HMAXNIT, FRACDEC +C + INTEGER :: IHOUR, NCS, NBLOCKS, IRCHEM + INTEGER :: NCSGAS, NCSURBAN, NCSTROP, NCSSTRAT + INTEGER :: NPHOTALL, IFDID, IFNEVER, IFNONE + INTEGER :: NCSALL, NCSTRST + COMMON /IXYGD/ IHOUR, NCS, NBLOCKS, IRCHEM, + & NCSGAS, NCSURBAN, NCSTROP, NCSSTRAT, + & NPHOTALL, IFDID, IFNEVER, IFNONE, + & NCSALL, NCSTRST + + ! /IXYGD2/ needs to be held THREADPRIVATE. Also remove NSTEPS + ! since this can be declared local w/in "smvgear.f" (bmy, 7/16/03) + INTEGER :: NCSP, KBLK + COMMON /IXYGD2/ NCSP, KBLK + + REAL*8 :: HMIN, PLOURB, PLOTROP, TSPMIDC + COMMON /DGEAR/ HMIN, PLOURB, PLOTROP, TSPMIDC + + ! /DGEAR2/ needs to be held THREADPRIVATE (hamid, bmy, 7/16/03) + REAL*8 :: HMAX, R1DELT, DELT, TIMREMAIN + REAL*8 :: XELAPS, TOLD, RDELT, XELAPLAST + REAL*8 :: RMSERR + COMMON /DGEAR2/ HMAX, R1DELT, DELT, TIMREMAIN, + & XELAPS, TOLD, RDELT, XELAPLAST, + & RMSERR + + ! /DGEAR3/ doesn't need to be held THREADPRIVATE (hamid, bmy, 7/16/03) + REAL*8 :: SUMAVGE, SUMAVHI, SUMRMSE, SUMRMHI + REAL*8 :: TOTSTEP, TOTIT, TELAPS + COMMON /DGEAR3/ SUMAVGE, SUMAVHI, SUMRMSE, SUMRMHI, + & TOTSTEP, TOTIT, TELAPS + + INTEGER :: NSFTOT, NPDTOT, NSTTOT, ISREORD + INTEGER :: IFREORD, IFAILTOT, LFAILTOT, NFAILTOT + COMMON /IGEAR/ NSFTOT, NPDTOT, NSTTOT, ISREORD, + & IFREORD, IFAILTOT, LFAILTOT, NFAILTOT + + ! /IGEAR2/ has to be declared THREADPRIVATE (bmy, 7/16/03) + INTEGER :: NQQ, NSUBFUN, NPDERIV + INTEGER :: NFAIL, IFAIL, LFAIL + COMMON /IGEAR2/ NQQ, NSUBFUN, NPDERIV, + & NFAIL, IFAIL, LFAIL + + INTEGER :: NPHOT, NPRODLO, NPRODHI, MSTEP + INTEGER :: MAXORD, MBETWEEN, IC3H8, IC2H6 + COMMON /CHEM2/ NPHOT, NPRODLO, NPRODHI, MSTEP, + & MAXORD, MBETWEEN, IC3H8, IC2H6 + + ! /CHEM2A/ has to be held THREADPRIVATE (bmy, 7/16/03) + INTEGER :: ISCHAN, NFDH3, NFDL2, NFDH2 + INTEGER :: NFDL1, NFDH1, NFDREP, NFDREP1 + INTEGER :: NFDL0, NALLR + COMMON /CHEM2A/ ISCHAN, NFDH3, NFDL2, NFDH2, + & NFDL1, NFDH1, NFDREP, NFDREP1, + & NFDL0, NALLR + + ! Split off from /CHEM2A/ (bmy, 7/28/03) + INTEGER :: NOCC + COMMON /CHEM2B/ NOCC + + INTEGER :: NGAS, NMREAC + COMMON /CHEM3/ NGAS, NMREAC + + ! Added NNADDG to /CHEM4/ for DMS+OH+O2 rxn (bdf, bmy, 4/18/03) + ! Add NKN2O5 to /CHEM4/ to flag N2O5 hydrolysis rxn (mje, bmy, 8/7/03) + ! Add NKHO2 to /CHEM4/ to flag HO2 aerosol uptake (jaegle 02/26/09) + ! Add NNADDF, NNADDH, NKHOROI and NKHOROJ to /CHEM4/ for HOC2H4O rxns + ! (tmf, 3/6/09) + !Added NNRO2HO2(jmao, 11/17/2012) + INTEGER :: NNADD1, NNADDA, NNADDB + INTEGER :: NNADDC, NNADDD, NNADDK + INTEGER :: NNADDV, NNADDZ, NKO3PHOT + INTEGER :: NNADDG, NEMIS, NDRYDEP + INTEGER :: NKHNO4, NKN2O5, NKHO2 + INTEGER :: NNADDF, NNADDH + INTEGER :: NKHOROI, NKHOROJ + INTEGER :: NNRO2HO2 + COMMON /CHEM4/ NNADD1, NNADDA(ICS), NNADDB( ICS), + & NNADDC(ICS), NNADDD(ICS), NNADDK( ICS), + & NNADDV(ICS), NNADDZ, NKO3PHOT(ICS), + & NNADDG(ICS), NEMIS( ICS), NDRYDEP( ICS), + & NNADDF(ICS), NNADDH(ICS), + & NKHOROI(ICS),NKHOROJ(ICS), + & NKHNO4(ICS), NKN2O5, NKHO2,NNRO2HO2(ICS) + + INTEGER :: IH2O, IOXYGEN, MB1, MB2 + COMMON /SPECIES/ IH2O, IOXYGEN, MB1, MB2 + + ! Added for interannually-varying Methane (bnd, bmy, 7/1/03) + INTEGER :: ICH4 + COMMON /SPECIE2/ ICH4 + + ! Added for interannually-varying Methane (bnd, bmy, 7/1/03) + REAL*8 :: C3090S, C0030S, C0030N, C3090N + COMMON /SPECIE3/ C3090S, C0030S, C0030N, C3090N + + ! Added for tracking oxidation of ISOP by OH (dkh, bmy, 6/1/06) + INTEGER :: ILISOPOH + COMMON /SPECIE4/ ILISOPOH + + INTEGER :: IOUT, KGLC, KCPD, IO93 + COMMON /FILES/ IOUT, KGLC, KCPD, IO93 +C +C ********************************************************************* +C * SET REAL AND INTEGER ARRAY VARIABLES * +C ********************************************************************* +C + INTEGER :: JLOWVAR, KTLPVAR + INTEGER :: JLOFIXED, JHIFIXED + COMMON /IMXBLOCK/ JLOWVAR( MXBLOCK), KTLPVAR( MXBLOCK), + & JLOFIXED(MXBLOCK), JHIFIXED(MXBLOCK) + + INTEGER :: JREORDER, LREORDER + INTEGER :: ITWO, NCSLOOP + COMMON /IITLOOP/ JREORDER(ITLOOP), LREORDER(ITLOOP), + & ITWO( ITLOOP), NCSLOOP( ITLOOP,ICS) + + ! Add NKSPECG for DMS+OH+O2 rxn (bdf, bmy, 4/18/03) + ! Added NKSPECF, NKSPECH to /IDICS/ for C2H4 chemistry (tmf, 3/6/09) + ! Added NKSPECRO2HO2 for RO2+HO2 (jmao, 11/17/2012) + INTEGER NMOTH,NTSPEC,JPHOTRAT,ISGAINR,ISPORL,NOGAINE,NOUSE + INTEGER NSPEC,NTRATES,ISGAINE,NTLOOPNCS,NSPCSOLV,ISCHANG,NRATES + INTEGER NM3BOD,ITWOR,ITHRR,INOREP,NRATCUR,NSURFACE,NPRESM,NMAIR + INTEGER NMO2,NMN2,NNEQ,NARR,NABR,NACR,NABC,NKSPECW,NKSPECX + INTEGER NKSPECY,NKSPECZ,NKSPECV,ISLOSSR,NKSPECA,NKSPECB,NKSPECC + INTEGER NKSPECD,NKSPECK,NKSPECG + INTEGER NKSPECF, NKSPECH + INTEGER NKSPECRO2HO2 + + COMMON /IDICS/ + 1 NMOTH( ICS), NTSPEC( ICS), JPHOTRAT(ICS), + 3 ISGAINR( ICS), ISPORL( ICS), NOGAINE( ICS), NOUSE( ICS), + 4 NSPEC( ICS), NTRATES(ICS), ISGAINE( ICS), NTLOOPNCS(ICS), + 5 NSPCSOLV(ICS), ISCHANG(ICS), NRATES( ICS), NM3BOD( ICS), + 7 ITWOR( ICS), ITHRR( ICS), INOREP( ICS), NRATCUR( ICS), + 8 NSURFACE(ICS), NPRESM( ICS), NMAIR( ICS), NMO2( ICS), + 9 NMN2( ICS), NNEQ( ICS), NARR( ICS), NABR( ICS), + 1 NACR( ICS), NABC( ICS), NKSPECW( ICS), NKSPECX( ICS), + 2 NKSPECY( ICS), NKSPECZ(ICS), NKSPECV(MAXGL2,ICS),ISLOSSR(ICS), + 3 NKSPECA( MAXGL3,ICS), NKSPECB( MAXGL3,ICS), + 4 NKSPECC(MAXGL3,ICS),NKSPECD(MAXGL3,ICS),NKSPECK(MAXGL3,ICS), + 5 NKSPECG(MAXGL2,ICS),NKSPECRO2HO2(MAXGL3,ICS), + 6 NKSPECF(MAXGL3,ICS), NKSPECH(MAXGL3,ICS) + + ! re-define some nkspec* arrays for harvard chem mechanism (bdf) + INTEGER :: NOLOSP, NGNFRAC, NOLOSRAT + INTEGER :: IARRAY, NALLRAT, KZTLO + INTEGER :: KZTHI, IONER, NPLLO + INTEGER :: NPLHI, NFRLO, NFRHI + INTEGER :: NPDLO, NPDHI, IZLO + INTEGER :: JZLO, JLLO, JGLO + INTEGER :: IRMCT + COMMON /IICP/ NOLOSP(ICP), NGNFRAC(ICP), NOLOSRAT(ICP), + & IARRAY(ICP), NALLRAT(ICP), KZTLO( ICP), + & KZTHI( ICP), IONER( ICP), NPLLO( ICP), + & NPLHI( ICP), NFRLO( ICP), NFRHI( ICP), + & NPDLO( ICP), NPDHI( ICP), IZLO ( ICP), + & JZLO ( ICP), JLLO( ICP), JGLO( ICP), + & IRMCT( ICP) + + REAL*8 :: ABTOL, ABST2 + REAL*8 :: ERRMAX, HMAXUSE, TIMEINTV + COMMON /DICS/ ABTOL(6,ICS), ABST2(ICS), + & ERRMAX(ICS), HMAXUSE(ICP), TIMEINTV(ICS) + + REAL*8 :: WTGAS, GQSUMINI + REAL*8 :: BSUMCHEM, GQSUM, QBKGAS + COMMON /DIGAS/ WTGAS(IGAS), GQSUMINI(IGAS), + & BSUMCHEM(IGAS), GQSUM( IGAS), QBKGAS(IGAS) + + REAL*8 :: CPREV, CMODEL, APORL + COMMON /DMXGAER1/ CPREV(MXGSAER), CMODEL(MXGSAER), APORL(MXGSAER) + + INTEGER :: IFPRGAS, LGNUM, NGMIX + COMMON /IIGAS/ IFPRGAS(IGAS), LGNUM(IGAS), NGMIX(IGAS) + + REAL*8 :: DEFPRAT + COMMON /DIPHOT/ DEFPRAT(MXRATE,ICS) + + REAL*8 :: ARRT, BRRT + REAL*8 :: FCVT, FCT1T, FCT2T + COMMON /DMXCOF/ ARRT(MXCOF), BRRT( MXCOF), + & FCVT(MXCOF), FCT1T(MXCOF), FCT2T(MXCOF) + + INTEGER :: KCRRT + COMMON /IMXCOF/ KCRRT(MXCOF) + + INTEGER NKARR,NKABR,NKACR,NKABC,IRORD + COMMON /INMRAT2/ + 1 NKARR(NMTRATE,ICS), NKABR(NMTRATE,ICS), NKACR(NMTRATE,ICS), + 2 NKABC(NMTRATE,ICS), IRORD(NMTRATE,ICS) + + REAL*8 ARR,BRR,FCV,FCTEMP1,FCTEMP2 + COMMON /DNMTRATE/ + 1 ARR( NMTRATE, ICS), BRR( NMTRATE, ICS), + 2 FCV( NMTRATE, ICS), FCTEMP1(NMTRATE, ICS), + 3 FCTEMP2(NMTRATE, ICS) + + INTEGER IAPROD,NOLOSRN,NRUSE,NRREP,NPRODUC,IALLOSN,NCEQUAT + INTEGER NEWFOLD,NKONER,NKTWOR,NKTHRR,IRMA,IRMB,KCRR,LSKIP,IRMC + INTEGER JPHOTNK,IUSED,NOLDFNEW + COMMON /INMTRATE/ + 2 IAPROD( NMTRATE, ICS), NOLOSRN( NMTRATE, ICS), + 3 NRUSE( NMTRATE, ICS), NRREP( NMTRATE, ICS), + 4 NPRODUC(NMTRATE, ICS), IALLOSN( MXRATE, ICS), + 5 NCEQUAT(NMTRATE, ICS), NOLDFNEW(NMTRATE, ICS), + 6 NEWFOLD(NMTRATE*2,ICS), NKONER( NMTRATE, ICS), + 7 NKTWOR( NMTRATE, ICS), NKTHRR( NMTRATE, ICS), + 9 KCRR( NMTRATE, ICS), LSKIP( MXRATE, ICS), + 1 IRMC( NMTRATE ), JPHOTNK( NMTRATE, ICS), + 2 IUSED( MXRATE, ICS) + + ! For COMPAQ, put IRMA, IRMB in /INMTRATE2/ (Q. Liang, bmy, 10/17/05) + COMMON /INMTRATE2/ + & IRMA( NMTRATE ), IRMB( NMTRATE ) + + INTEGER :: NEWNK + COMMON /IMAXGL3/ NEWNK(MAXGL) + + REAL*8 :: FRACP + COMMON /DMAXGL2/ FRACP(MAXGL, ICS) + + INTEGER NREACOTH,LGASBINO,NKNLOSP,LOSINACP,IGNFRAC,NKGNFRAC + INTEGER NREACAIR,NREAC3B,NREACEQ,NREQOTH,NREACN2,NREACO2,NREACPM + INTEGER LGAS3BOD,NKSURF,NCOATG + COMMON /IMAXGL2/ + 1 NREACOTH(MAXGL2,ICS), LGASBINO(MAXGL2,ICS), + 2 NKNLOSP( MAXGL3,ICS), LOSINACP(MAXGL3,ICS), + 3 IGNFRAC( MAXGL, ICS), NKGNFRAC(MAXGL, ICS), + 4 NREACAIR(MAXGL3,ICS), NREAC3B( MAXGL3,ICS), + 5 NREACEQ( MAXGL3,ICS), NREQOTH( MAXGL3,ICS), + 6 NREACN2( MAXGL3,ICS), NREACO2( MAXGL3,ICS), + 7 NREACPM( MAXGL3,ICS), LGAS3BOD(MAXGL3,ICS), + 8 NKSURF( MAXGL4 ), NCOATG( MAXGL4 ) + + INTEGER :: MBCOMP, MBTRACE + COMMON /IIMASBAL/ MBCOMP(IMASBAL,2), MBTRACE(IMASBAL) + + ! /DKBLOOP2/ needs to be declared THREADPRIVATE + REAL*8 CNEW,CEST,GLOSS,CHOLD,VDIAG,CBLK,DTLOS,EXPLIC,CONC + REAL*8 RRATE,URATE,TRATE,CORIG + !***************ADJ_GROUP**************** + REAL*8 RRATE_FOR_KPP + !******************************************** + COMMON /DKBLOOP2/ + 2 CNEW( KBLOOP, MXGSAER), + 3 CEST( KBLOOP, MXGSAER), + 4 GLOSS( KBLOOP, MXGSAER), + 5 CHOLD( KBLOOP, MXGSAER), + 6 VDIAG( KBLOOP, MXGSAER), CBLK( KBLOOP,MXGSAER), + 7 DTLOS( KBLOOP, MXGSAER), EXPLIC(KBLOOP,MXGSAER), + 1 CONC( KBLOOP,MXGSAER*7), + 2 RRATE( KBLOOP, NMTRATE), + !***************ADJ_GROUP******************** + 2 RRATE_FOR_KPP( KBLOOP, NMTRATE), + !******************************************** + 3 URATE( KBLOOP,NMTRATE,3), + 4 TRATE( KBLOOP,NMTRATE*2), + 7 CORIG( KBLOOP, MXGSAER) + + ! /DKBLOOP0/ needs to be held THREADPRIVATE + REAL*8 :: CC2 + COMMON /DKBLOOP0/ CC2(KBLOOP,0:MXARRAY) + + INTEGER :: MLOP, JLOP_SMV + COMMON /IILAT2/ MLOP(ILAT,ILONG), JLOP_SMV(ILAT,ILONG,ILAYER) + + INTEGER NKPHOTRAT,NPPHOTRAT,NKNPHOTRT + COMMON /DIPHOT2/ + 1 NKPHOTRAT(IPHOT,ICS), NPPHOTRAT(IPHOT,ICS), + 2 NKNPHOTRT(IPHOT,ICS) + + REAL*8 :: FRACGAIN, QBKCHEM + COMMON /DIMXGS2/ FRACGAIN(MXGSAER,ICS), QBKCHEM( MXGSAER,ICS) + + INTEGER NUMLOST,NUMGFRT,NUMLOSS,JPORL,NUMGAINT,NGAINE,NUMGAIN + INTEGER IGAINR,IPORL,IGAINE,ISOLVSPC,INEWOLD,MAPPL,ISAPORL,NUMPORL + INTEGER ISPARDER,JLOSST + COMMON /IIMXGS2/ + 1 NUMLOST( MXGSAER, ICS), NUMGFRT( MXGSAER, ICS), + 2 NUMLOSS( MXGSAER, ICP), JPORL( MXGSAER,MAXGL, ICS), + 3 NUMGAINT(MXGSAER, ICS), NGAINE( MXGSAER, ICS), + 4 NUMGAIN( MXGSAER, ICP), IGAINR( MXGSAER, ICS), + 9 IPORL( MXGSAER, ICS), IGAINE( MXGSAER, ICS), + 2 ISOLVSPC(MXGSAER, ICS), INEWOLD( MXGSAER, ICS), + 3 MAPPL( MXGSAER, ICS), ISAPORL( MXGSAER ), + 7 NUMPORL( MXGSAER, ICP), ISPARDER(MXGSAER,MXGSAER ), + 8 JLOSST( MXGSAER,MAXGL,ICS) + + INTEGER JZILCH,KZILCH,MZILCH + COMMON /IGMXGLS/ + & JZILCH(MXGSAER), KZILCH(MXGSAER), MZILCH(MXGSAER) + + INTEGER LZERO,JARRAYPT,IZILCH,JARRDIAG,JLOZ1,JHIZ1,IJTLO + INTEGER IJTHI,IMZTOT,IFREPRO,IZLO1,IZLO2,IZHI0,IZHI1 + COMMON /IGMXGS2/ + 1 LZERO( MXGSAER,MXGSAER), JARRAYPT(MXGSAER,MXGSAER), + 2 IZILCH( MXGSAER,MXGSAER), JARRDIAG(MXGSAER, ICP), + 3 JLOZ1( MXGSAER, ICP), JHIZ1( MXGSAER, ICP), + 4 IJTLO( MXGSAER, ICP), IJTHI( MXGSAER, ICP), + 5 IMZTOT( MXGSAER, ICP), IFREPRO( MXGSAER,MXRATE, ICS), + 6 IZLO1( MXGSAER,ICP), + 7 IZLO2( MXGSAER,ICP), IZHI0( MXGSAER,ICP), IZHI1( MXGSAER,ICP) + + REAL*8 :: FRACNFR, FRACPL + COMMON /DMXCOUN/ FRACNFR(MXCOUNT4), FRACPL(MXCOUNT2) + + INTEGER JZERO,KZERO,MZERO,IZEROK,JZEROA,IKDECA,KJDECA,LOSSRA + INTEGER IKDECB,KJDECB,LOSSRB,IKDECC,KJDECC,LOSSRC,IKDECD,KJDECD + INTEGER LOSSRD,IKDECE,KJDECE,LOSSRE,KZEROA,MZEROA,KZEROB,MZEROB + INTEGER KZEROC,MZEROC,KZEROD,MZEROD,KZEROE,MZEROE,IPOSPD,IIALPD + INTEGER NKPDTERM,IJVAL,IKZTOT,JSPNPL,NKNFR,JSPCNFR + COMMON /IMXCOUN/ + 1 JZERO( MXCOUNT3), KZERO( MXCOUNT3), MZERO( MXCOUNT3), + 2 IZEROK(MXCOUNT2), JZEROA( MXCOUNT3), + 3 IKDECA(MXCOUNT3), KJDECA( MXCOUNT3), LOSSRA( MXCOUNT4), + 4 IKDECB(MXCOUNT3), KJDECB( MXCOUNT3), LOSSRB( MXCOUNT4), + 5 IKDECC(MXCOUNT3), KJDECC( MXCOUNT3), LOSSRC( MXCOUNT4), + 6 IKDECD(MXCOUNT3), KJDECD( MXCOUNT3), LOSSRD( MXCOUNT4), + 7 IKDECE(MXCOUNT3), KJDECE( MXCOUNT3), LOSSRE( MXCOUNT4), + 8 KZEROA(MXCOUNT4), MZEROA( MXCOUNT4), + 9 KZEROB(MXCOUNT4), MZEROB( MXCOUNT4), + 1 KZEROC(MXCOUNT4), MZEROC( MXCOUNT4), + 2 KZEROD(MXCOUNT4), MZEROD( MXCOUNT4), + 3 KZEROE(MXCOUNT4), MZEROE( MXCOUNT4), + 4 IPOSPD(MXCOUNT2), IIALPD( MXCOUNT2), NKPDTERM(MXCOUNT2), + 5 IJVAL( MXCOUNT3), IKZTOT( MXCOUNT4), JSPNPL( MXCOUNT4), + 7 NKNFR( MXCOUNT4), JSPCNFR(MXCOUNT4) + + INTEGER IDH5,IDH4,IDH3,IDH2,IDH1,IDL5,IDL4,IDL3,IDL2,IDL1,KBH5 + INTEGER KBH4,KBH3,KBH2,KBH1,KBL5,KBL4,KBL3,KBL2,KBL1,MBH5,MBH4 + INTEGER MBH3,MBH2,MBH1,MBL5,MBL4,MBL3,MBL2,MBL1,NPH5,NPH4,NPH3 + INTEGER NPH2,NPH1,NPL5,NPL4,NPL3,NPL2,NPL1 + COMMON /IMXCOU2/ + 1 IDH5( MXCOUNT3), IDH4( MXCOUNT3), IDH3( MXCOUNT3), + 2 IDH2( MXCOUNT3), IDH1( MXCOUNT3), IDL5( MXCOUNT3), + 3 IDL4( MXCOUNT3), IDL3( MXCOUNT3), IDL2( MXCOUNT3), + 4 IDL1( MXCOUNT3), + 5 KBH5( MXCOUNT4), KBH4( MXCOUNT4), KBH3( MXCOUNT4), + 6 KBH2( MXCOUNT4), KBH1( MXCOUNT4), KBL5( MXCOUNT4), + 7 KBL4( MXCOUNT4), KBL3( MXCOUNT4), KBL2( MXCOUNT4), + 8 KBL1( MXCOUNT4), + 9 MBH5( MXCOUNT4), MBH4( MXCOUNT4), MBH3( MXCOUNT4), + 1 MBH2( MXCOUNT4), MBH1( MXCOUNT4), MBL5( MXCOUNT4), + 2 MBL4( MXCOUNT4), MBL3( MXCOUNT4), MBL2( MXCOUNT4), + 3 MBL1( MXCOUNT4), + 4 NPH5( MXCOUNT4), NPH4( MXCOUNT4), NPH3( MXCOUNT4), + 5 NPH2( MXCOUNT4), NPH1( MXCOUNT4), NPL5( MXCOUNT4), + 6 NPL4( MXCOUNT4), NPL3( MXCOUNT4), NPL2( MXCOUNT4), + 7 NPL1( MXCOUNT4) + + REAL*8 :: GEARCONC + COMMON /DIMXG2/ GEARCONC(MXGSAER,0:MXHOLD,ICS) + + REAL*8 :: WTMB + COMMON /DIMASBAL2/ WTMB(IMASBAL,MXGSAER,2) + + INTEGER :: JMBCOMP + COMMON /IIMASBAL2/ JMBCOMP(IMASBAL,MXGSAER,2) + + REAL*8 :: FKOEF + REAL*8 :: FK2 + COMMON /DNMRPROD2/ FKOEF(NMRPROD,NMTRATE,ICS), + & FK2( NMRPROD,NMTRATE,ICS) + + INTEGER :: IRM + INTEGER :: IRM2 + COMMON /INMRPROD2/ IRM( NMRPROD,NMTRATE,ICS), + & IRM2(NMRPROD,NMTRATE,ICS) + + REAL*8 :: ASET, PINP, CVAR, O3DOBS + COMMON /DMISC/ ASET(10,8), PINP(20), CVAR(15), O3DOBS(12) + + REAL*8 :: ENQQ2, ENQQ3, CONPST + REAL*8 :: ENQQ1, CONP15 + COMMON /IORDR/ ENQQ2(MORDER), ENQQ3( MORDER), CONPST(MORDER), + & ENQQ1(MORDER), CONP15(MORDER) + + REAL*8 :: PERTS2, PERTST + COMMON /DMORD/ PERTS2(MORDER,3), PERTST(MORDER,3) + + INTEGER :: JLLOW, KLHI + COMMON /IMXBLOCK/ JLLOW(MXBLOCK), KLHI(MXBLOCK) + + REAL*8 :: XGDFCF, ASTKCF, RUARSL, RH100 + COMMON /XARSOL/ XGDFCF, ASTKCF, RUARSL, RH100 + + INTEGER :: IARSFA, MWARSL, MNTHARS + COMMON /IARSOL/ IARSFA, MWARSL, MNTHARS + + INTEGER :: NKEMIS, NTEMIS + INTEGER :: NKDRY, NTDEP + COMMON /IMAXGL4/ NKEMIS(MAXGL3,ICS), NTEMIS(MAXGL3,ICS), + & NKDRY (MAXGL3,ICS), NTDEP( MAXGL3) + +C BDF COULD BE SOME MISSING STUFF FROM HERE. +C INTEGER KZERO,IZEROA,IZEROB,IZEROC,IZEROD,IZER2A,IZER2B, +C 1 IZER2C,IZER2D,JZEROA,JZEROB,IRMSEC,IRMTHD,NKARRY, +C 2 LOSSRA,JPRODA,LOSSRB,LOSSRC,LOSSRD,JPRODB,JPRODC, +C 3 JPRODD +C COMMON /IMXCOUN/ +C 1 KZERO( MXARRAY,ICP), IZEROA( MXARRAY ), +C 7 IZEROB( MXARRAY), IZEROC( MXARRAY ), IZEROD( MXARRAY), +C 8 IZER2A( MXARRAY), IZER2B( MXARRAY ), +C 9 IZER2C( MXARRAY), IZER2D( MXARRAY ), +C 1 JZEROA( MXARRAY), JZEROB( MXARRAY ), +C 3 IRMSEC(MXCOUNT3), IRMTHD(MXCOUNT3 ), NKARRY(MXCOUNT3), +C 2 LOSSRA(MXCOUNT4), JPRODA(MXCOUNT4 ), +C 4 LOSSRB(MXCOUNT4), LOSSRC(MXCOUNT4 ), LOSSRD(MXCOUNT4), +C 5 JPRODB(MXCOUNT4), JPRODC(MXCOUNT4 ), +C 6 JPRODD(MXCOUNT4), JPRODT( MXGSAER,MAXGL,ICS), +C 5 NKSINGL( MXGSAER,ICS, 2), NKNUMSL( MXGSAER,MAXGL,ICS), +C 6 NKDOUBL( MXGSAER,ICS ), NKNUMDL( MXGSAER,MAXGL,ICS), +C 7 NKTRIPL( MXGSAER,ICS ), NKNUMTL( MXGSAER,MAXGL,ICS), +C 8 LOSSLEFT(MXGSAER,ICS ), LOSSREM( MXGSAER,MAXGL,ICS), +C 9 ILOSSR( MXGSAER,ICS ), NLOSSR( MXGSAER, ICS), +C 1 NGAINR( MXGSAER,ICS ), ICHANSPC(MXGSAER, ICS), +C 4 NUML1( MXGSAER,ICP ), NUML2( MXGSAER, ICP), +C 5 NUMP1( MXGSAER,ICP ), NUMP2( MXGSAER, ICP), +C 6 JHIZ2( MXGSAER, ICP) + + !================================================================= + ! Common blocks for ND65 diagnostic (ljm, bmy, 7/8/03) + !================================================================= + INTEGER :: IFAM, NFAMILIES + COMMON /IPL/ IFAM(MAXFAM), NFAMILIES + + CHARACTER*4 :: PORL + COMMON /CPL/ PORL(MAXFAM) + + LOGICAL :: LFAMILY, ITS_NOT_A_ND65_FAMILY + COMMON /LPL/ LFAMILY, ITS_NOT_A_ND65_FAMILY(IGAS) + + !================================================================= + ! Declare some common blocks THREADPRIVATE for the OpenMP + ! parallelization (bdf, bmy, 4/1/03) + !================================================================= +!$OMP THREADPRIVATE( /CHEM2A/ ) +!$OMP THREADPRIVATE( /CTLLOOP2/ ) +!$OMP THREADPRIVATE( /DGEAR2/ ) +!$OMP THREADPRIVATE( /DKBLOOP0/ ) +!$OMP THREADPRIVATE( /DKBLOOP2/ ) +!$OMP THREADPRIVATE( /IGEAR2/ ) +!$OMP THREADPRIVATE( /IXYGD2/ ) + +#if defined( COMPAQ ) +! For COMPAQ, declare /INMTRATE2/ threadprivate (Q. Liang, bmy, 10/17/05) +!$OMP THREADPRIVATE( /INMTRATE2/ ) +#endif + +C +C ********************************************************************* +C ****************** END OF COMMON BLOCK COMODE.H ********************* +C ********************************************************************* +C diff --git a/code/critical_load_mod.f b/code/critical_load_mod.f new file mode 100644 index 0000000..9ee5c59 --- /dev/null +++ b/code/critical_load_mod.f @@ -0,0 +1,338 @@ +! + MODULE CRITICAL_LOAD_MOD + +!module critical_load contains variable and routines to read acidity/N deposition critical loads over the US (SD) and generate map of exceedence + + + IMPLICIT NONE + + ! Make everything private + PRIVATE + + + !except + PUBLIC :: GET_CL_EXCEEDENCE + PUBLIC :: CL_FILENAME + PUBLIC :: GC_FILENAME + + CHARACTER*255 :: CL_FILENAME + CHARACTER*255 :: GC_FILENAME + + !very large value used to generate critical load files + !to make sure no exceedence is found in regions where CL is not defined + INTEGER, PARAMETER :: MISSING_VALUE = 9D6 + + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_CRITICAL_LOAD(CRIT_L) +! Subroutine read_critical_load is used to read annual critical/load acidification files. +! Files are in netcdf format (spatial resolution is reduced nested domain over the US) + + USE TRANSFER_MOD, ONLY : TRANSFER_2D + USE NETCDF_UTIL_MOD + +# include "CMN_SIZE" + + REAL*8, INTENT(OUT) :: CRIT_L(IIPAR,JJPAR) + REAL*4 :: ARRAY(IIPAR,JJPAR) + INTEGER :: I,J + INTEGER :: fileID, varID + CHARACTER*255 :: FILENAME + + WRITE(6,*) '==========================' + WRITE(6,*) '=== Read Critical load ===' + WRITE(6,*) '==========================' + + + call ncdf_open_for_read( fileID, TRIM(CL_FILENAME) ) + varID = ncdf_get_varid( fileID, 'ecoreg' ) + + call ncdf_get_var( fileID, varID, array, + & start=(/ 1, 1 /), + & count=(/ iipar, jjpar /) ) + + ! real*4->real*8 + CALL TRANSFER_2D( ARRAY, CRIT_L ) + + WRITE(*,*) 'Min Critical Load: ',MINVAL( CRIT_L ) + WRITE(*,*) 'Max Critical Load: ',MAXVAL( CRIT_L, + & MASK = CRIT_L < MISSING_VALUE ) + + END SUBROUTINE READ_CRITICAL_LOAD + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_GC_LOAD(GC_L) +! Subroutine read_annual deposition. Read GC calculated deposition from 3yr nested simulation (lzh) + + USE TRANSFER_MOD, ONLY : TRANSFER_2D + USE NETCDF_UTIL_MOD + + USE TRACERID_MOD, ONLY : IDTNH3, IDTNH4, IDTNIT, IDTNITs + USE TRACERID_MOD, ONLY : IDTHNO3, IDTR4N2, IDTPMN, IDTPPN + USE TRACERID_MOD, ONLY : IDTPAN, IDTNOX, IDTN2O5 + USE TRACERID_MOD, ONLY : IDTSO2, IDTSO4, IDTSO4s + USE TRACER_MOD, ONLY : TRACER_MW_KG, TRACER_NAME + USE LOGICAL_ADJ_MOD, ONLY : LADJ_CL_ACID, LADJ_CL_NDEP + USE GRID_MOD, ONLY : GET_AREA_M2 + USE LOGICAL_MOD, ONLY : LPRT + +# include "CMN_SIZE" + + REAL*8, INTENT(OUT) :: GC_L(IIPAR,JJPAR) + REAL*4 :: ARRAY(IIPAR,JJPAR) + REAL*8 :: ARRAY8(IIPAR,JJPAR) + REAL*8 :: SWET(IIPAR,JJPAR) + INTEGER :: N, NMAX + INTEGER :: fileID, varID + INTEGER :: I,J + REAL*8 :: TRACER(18) + REAL*8 :: DRY(IIPAR,JJPAR) + REAL*8 :: TEMP(IIPAR,JJPAR) + + + WRITE(6,*) '====================' + WRITE(6,*) '=== Read GC load ===' + WRITE(6,*) '====================' + + TRACER( 1 ) = IDTHNO3 + TRACER( 2 ) = IDTR4N2 + TRACER( 3 ) = IDTPMN + TRACER( 4 ) = IDTPPN + TRACER( 5 ) = IDTPAN + TRACER( 6 ) = IDTNOX + TRACER( 7 ) = IDTN2O5 + TRACER( 8 ) = IDTN2O5 !repeat N2O5 as it contains two N + TRACER( 9 ) = IDTNH3 + TRACER(10 ) = IDTNH4 + TRACER(11 ) = IDTNIT + TRACER(12 ) = IDTNITs + + !repeat S tracers since they contain two equivalents + TRACER(13) = IDTSO2 + TRACER(14) = IDTSO4 + TRACER(15) = IDTSO4s + TRACER(16) = IDTSO2 + TRACER(17) = IDTSO4 + TRACER(18) = IDTSO4s + + GC_L(:,:) = 0d0 + SWET(:,:) = 0d0 + DRY(:,:) = 0d0 + + + IF ( LADJ_CL_ACID ) THEN + NMAX = 18 + ELSEIF (LADJ_CL_NDEP) THEN + NMAX = 12 + ENDIF + +! open netcdf file + call ncdf_open_for_read( fileID, TRIM(GC_FILENAME) ) + + DO N = 1,NMAX + + ! read dry deposition + IF (LPRT) THEN + WRITE(6,100) TRIM(TRACER_NAME(TRACER(N))) + ENDIF + + IF ( TRACER(N) .EQ. IDTNOx) THEN + + varID = ncdf_get_varid( fileID, + & 'DRY_NO2' ) + + ELSE + + varID = ncdf_get_varid( fileID, + & 'DRY_' // TRIM(TRACER_NAME(TRACER(N))) ) + + ENDIF + + call ncdf_get_var( fileID, varID, array, + & start=(/ 1, 1 /), + & count=(/ iipar, jjpar /) ) + + ! real*4->real*8 + CALL TRANSFER_2D( ARRAY, ARRAY8 ) + + IF ( LADJ_CL_NDEP ) THEN + + ! convert from molec/cm2/s to kgN/ha/yr + GC_L(:,:) = GC_L(:,:) + + & 14D-3 / 6.022D23 * + & 1D8 * + & 86400D0 * 365D0 * + & ARRAY8(:,:) + + !for diagnostics (kgN/cm2/yr) + DRY(:,:) = DRY(:,:) + + & 14D-3 / 6.022D23 * + & 86400D0 * 365D0 * + & ARRAY8(:,:) + + DO J = 1, JJPAR + + TEMP(:,J) = 14D-3 / 6.022D23 * + & 86400D0 * 365D0 * + & ARRAY8(:,J) * GET_AREA_M2(J) * + & 1D4 + + ENDDO + + ELSEIF ( LADJ_CL_ACID ) THEN + + ! convert from molec/cm2/s to equiv/ha/yr + GC_L(:,:) = GC_L(:,:) + + & 1D0 / 6.022D23 * + & 1D8 * + & 86400D0 * 365D0 * + & ARRAY8(:,:) + + ! for diagnostics equiv/cm2/yr + DRY(:,:) = DRY(:,:) + + & 1D0 / 6.022D23 * + & 86400D0 * 365D0 * + & ARRAY8(:,:) + + ENDIF + + ! read wet deposition + IF ( LPRT ) THEN + WRITE(6,101) TRIM( TRACER_NAME(TRACER(N)) ) + ENDIF + + ! no wet deposition for NOx so no need to read NOx + IF ( IDTNOx .NE. TRACER(N) ) THEN + + varID = ncdf_get_varid( fileID, + & 'WET_' // TRIM( TRACER_NAME( TRACER(N))) ) + + call ncdf_get_var( fileID, varID, array, + & start=(/ 1, 1 /), + & count=(/ iipar, jjpar /) ) + + ! real*4->real*8 + CALL TRANSFER_2D( ARRAY, ARRAY8 ) + + IF ( LADJ_CL_NDEP ) THEN + + ! convert from kg/s to kgN/yr + SWET(:,:) = SWET(:,:) + + & 14D-3 / TRACER_MW_KG( TRACER(N) ) * + & 86400D0 * 365D0 * + & ARRAY8(:,:) + + ELSEIF ( LADJ_CL_ACID ) THEN + + ! convert from kg/s to equiv/yr + SWET(:,:) = SWET(:,:) + + & 1D0 / TRACER_MW_KG( TRACER(N) ) * + & 86400D0 * 365D0 * + & ARRAY8(:,:) + + ENDIF + + ENDIF + + ENDDO + + !for diagnostics + DO J = 1,JJPAR + + DRY(:,J) = DRY(:,J) * + & GET_AREA_M2(J) * 1D4 + + ENDDO + + + WRITE(*,*) 'GC deposition (wet): ',SUM( SWET ) + WRITE(*,*) 'GC deposition (dry): ',SUM( DRY ) + + + !convert SWET from equiv/yr to equiv/yr/ha + !add to critical load + + DO J = 1, JJPAR + + GC_L(:,J) = GC_L(:,J) + + & SWET(:,J) / GET_AREA_M2(J) * 1D4 + + ENDDO + + WRITE(*,*) 'Min GC Load: ', MINVAL( GC_L(:,:) ) + WRITE(*,*) 'Max GC Load: ', MAXVAL( GC_L(:,:) ) + + + 100 FORMAT('Dry deposition :',a) + 101 FORMAT('Wet deposition :',a) + + END SUBROUTINE READ_GC_LOAD + +!------------------------------------------------------------------------------ +! + SUBROUTINE GET_CL_EXCEEDENCE( EXCEEDENCE ) +! generate maks for criticial load exceedence +! + USE BPCH2_MOD + USE LOGICAL_MOD, ONLY : LPRT + USE FILE_MOD, ONLY : IU_DEBUG + +# include "CMN_SIZE" + + REAL*8, INTENT(OUT) :: EXCEEDENCE(IIPAR,JJPAR) + REAL*8 :: CRIT_L(IIPAR,JJPAR) + REAL*8 :: GC_L(IIPAR,JJPAR) + INTEGER :: I,J,NE,DEFINED + + EXCEEDENCE(:,:) = 0d0 + NE = 0 + DEFINED = 0 + + ! read GC load from deposition + CALL READ_GC_LOAD(GC_L) + + ! read critical load (deposition) + CALL READ_CRITICAL_LOAD(CRIT_L) + + DO I = 1, IIPAR + DO J = 1, JJPAR + + IF ( GC_L(I,J) .GT. CRIT_L(I,J) ) THEN + EXCEEDENCE(I,J) = 1D0 + NE = NE + 1 + ENDIF + + ! count the number of grid cells where a critical load is defined + IF ( CRIT_L(I,J) .LT. MISSING_VALUE ) THEN + DEFINED = DEFINED + 1 + ENDIF + + ENDDO + ENDDO + + WRITE(6,*) 'Number of exceedences: ', NE + WRITE(6,*) 'Fraction of grid cells with exceedence', + & REAL(NE)/REAL(DEFINED) + + + ! write out exceedence to bpch file + OPEN( IU_DEBUG, FILE='critical_load.log', STATUS='UNKNOWN' ) + + DO I = 1, IIPAR + DO J = 1, JJPAR + WRITE( IU_DEBUG, '(F10.3,X)', advance='no' ) EXCEEDENCE(I,J) + ENDDO + WRITE( IU_DEBUG,* ) + END DO + + CLOSE( IU_DEBUG ) + + + END SUBROUTINE GET_CL_EXCEEDENCE + +!------------------------------------------------------------------------------ + + END MODULE CRITICAL_LOAD_MOD diff --git a/code/decomp.f b/code/decomp.f new file mode 100644 index 0000000..20bc108 --- /dev/null +++ b/code/decomp.f @@ -0,0 +1,207 @@ +! $Id: decomp.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + SUBROUTINE DECOMP +! +!****************************************************************************** +! Subroutine DECOMP decomposes the sparse matrix for the SMVGEAR II solver. +! (M. Jacobson, 1997; bdf, bmy, 4/18/03) +! +! NOTES: +! (1 ) Now use & as F90 continuation character. Now also force double +! precision with the "D" exponent. (bmy, 4/18/03) +! (2 ) Comment out counter variable NUM_BACKSUB, you can get the same info +! w/ a profiling run. (bmy, 7/9/03) +!****************************************************************************** +! + IMPLICIT NONE + +# include "CMN_SIZE" +# include "comode.h" +C +C ********************************************************************* +C ************ WRITTEN BY MARK JACOBSON (1993) ************ +C *** (C) COPYRIGHT, 1993 BY MARK Z. JACOBSON *** +C *** U.S. COPYRIGHT OFFICE REGISTRATION NO. TXu 670-279 *** +C *** (650) 723-6836 *** +C ********************************************************************* +C +C DDDDDDD EEEEEEE CCCCCCC OOOOOOO M M PPPPPPP +C D D E C O O MM MM P P +C D D EEEEEEE C O O M M M M PPPPPPP +C D D E C O O M M M P +C DDDDDDD EEEEEEE CCCCCCC OOOOOOO M M P +C +C ********************************************************************* +C ************** DECOMPOSE THE SPARSE MATRIX ************************** +C ********************************************************************* +C +C ********************************************************************* +C * THIS SUBROUTINE DECOMPOSES THE MATRIX "P" INTO THE MATRIX "A" IN * +C * ORDER TO SOLVE THE LINEAR SET OF EQUATIONS Ax = B FOR x, WHICH IS * +C * A CORRECTION VECTOR. Ax = B IS SOLVED IN SUBROUTINE BACKSUB.F * +C * ABOVE, THE ORIGINAL MATRIX "P" IS * +C * * +C * P = I - H x Bo x J, * +C * * +C * WHERE I = IDENTITY MATRIX, H = TIME-STEP, Bo = A COEFFICIENT THAT * +C * DEPENDS ON THE ORDER OF THE INTEGRATION METHOD, AND J IS THE * +C * MATRIX OF PARTIAL DERIVATIVES. SEE PRESS ET AL. (1992) NUMERICAL * +C * RECIPES CAMBRIDGE UNIVERSITY PRESS, FOR A BETTER DESCRIPTION OF * +C * THE L-U DECOMPOSTION PROCESS * +C * * +C * THIS L-U DECOMPOSTION PROCESS USES SPARSE-MATRIX TECHNIQUES, * +C * VECTORIZES AROUND THE GRID-CELL DIMENSION, AND USES NO PARTIAL * +C * PIVOTING. TESTS BY SHERMAN & HINDMARSH (1980) LAWRENCE LIVERMORE * +C * REP. UCRL-84102 AND BY US HAVE CONFIRMED THAT THE REMOVAL OF * +C * PARTIAL PIVOTING HAS LITTLE EFFECT ON RESULTS. * +C * * +C * HOW TO CALL SUBROUTINE: * +C * ---------------------- * +C * CALL DECOMP.F FROM SMVGEAR.F WITH * +C * NCS = 1..NCSGAS FOR GAS CHEMISTRY * +C * NCSP = NCS FOR DAYTIME GAS CHEM * +C * NCSP = NCS +ICS FOR NIGHTTIME GAS CHEM * +C ********************************************************************* +C +C KTLOOP = NUMBER OF GRID-CELLS IN A GRID-BLOCK +C ISCHAN = ORIGINAL ORDER OF MATRIX +C CC2 = ARRAY OF IARRAY UNITS HOLDING VALUES OF EACH MATRIX +C POSITION ACTUALLY USED. ORIGINALLY, +C CC2 = P = I - DELT * ASET(NQQ,1) * PARTIAL DERIVATIVES. +C HOWEVER, CC2 IS DECOMPOSED HERE +C +C ********************************************************************* +C *** FIRST LOOP OF L-U DECOMPOSTION *** +C ********************************************************************* +C SUM 1,2,3,4, OR 5 TERMS AT A TIME TO IMPROVE VECTORIZATION +C + INTEGER J,IJT,IJ,IL5,IH5,IL4,IH4,IL3,IH3,IL2,IH2,IL1,IH1 + INTEGER IC,IK0,IK1,IK2,IK3,IK4,KJ0,KJ1,KJ2,KJ3,KJ4,K,IAR + INTEGER JL,JH,JC,IJA + + DO 510 J = 1, ISCHAN + DO 310 IJT = IJTLO(J,NCSP), IJTHI(J,NCSP) + IJ = IJVAL(IJT) + IL5 = IDL5( IJT) + IH5 = IDH5( IJT) + IL4 = IDL4( IJT) + IH4 = IDH4( IJT) + IL3 = IDL3( IJT) + IH3 = IDH3( IJT) + IL2 = IDL2( IJT) + IH2 = IDH2( IJT) + IL1 = IDL1( IJT) + IH1 = IDH1( IJT) + +C ********************* SUM 5 TERMS AT A TIME ************************* +C + DO 105 IC = IL5, IH5 + IK0 = IKDECA(IC) + IK1 = IKDECB(IC) + IK2 = IKDECC(IC) + IK3 = IKDECD(IC) + IK4 = IKDECE(IC) + KJ0 = KJDECA(IC) + KJ1 = KJDECB(IC) + KJ2 = KJDECC(IC) + KJ3 = KJDECD(IC) + KJ4 = KJDECE(IC) + DO 100 K = 1, KTLOOP + CC2(K,IJ) = CC2(K,IJ) - CC2(K,IK0) * CC2(K,KJ0) + & - CC2(K,IK1) * CC2(K,KJ1) + & - CC2(K,IK2) * CC2(K,KJ2) + & - CC2(K,IK3) * CC2(K,KJ3) + & - CC2(K,IK4) * CC2(K,KJ4) + 100 CONTINUE + 105 CONTINUE +C +C ********************* SUM 4 TERMS AT A TIME ************************* +C + DO 155 IC = IL4, IH4 + IK0 = IKDECA(IC) + IK1 = IKDECB(IC) + IK2 = IKDECC(IC) + IK3 = IKDECD(IC) + KJ0 = KJDECA(IC) + KJ1 = KJDECB(IC) + KJ2 = KJDECC(IC) + KJ3 = KJDECD(IC) + DO 150 K = 1, KTLOOP + CC2(K,IJ) = CC2(K,IJ) - CC2(K,IK0) * CC2(K,KJ0) + & - CC2(K,IK1) * CC2(K,KJ1) + & - CC2(K,IK2) * CC2(K,KJ2) + & - CC2(K,IK3) * CC2(K,KJ3) + 150 CONTINUE + 155 CONTINUE +C +C ********************* SUM 3 TERMS AT A TIME ************************* +C + DO 205 IC = IL3, IH3 + IK0 = IKDECA(IC) + IK1 = IKDECB(IC) + IK2 = IKDECC(IC) + KJ0 = KJDECA(IC) + KJ1 = KJDECB(IC) + KJ2 = KJDECC(IC) + DO 200 K = 1, KTLOOP + CC2(K,IJ) = CC2(K,IJ) - CC2(K,IK0) * CC2(K,KJ0) + & - CC2(K,IK1) * CC2(K,KJ1) + & - CC2(K,IK2) * CC2(K,KJ2) + 200 CONTINUE + 205 CONTINUE +C +C ********************* SUM 2 TERMS AT A TIME ************************* +C + DO 255 IC = IL2, IH2 + IK0 = IKDECA(IC) + IK1 = IKDECB(IC) + KJ0 = KJDECA(IC) + KJ1 = KJDECB(IC) + DO 250 K = 1, KTLOOP + CC2(K,IJ) = CC2(K,IJ) - CC2(K,IK0) * CC2(K,KJ0) + & - CC2(K,IK1) * CC2(K,KJ1) + 250 CONTINUE + 255 CONTINUE +C +C ********************* SUM 1 TERM AT A TIME ************************* +C + DO 305 IC = IL1, IH1 + IK0 = IKDECA(IC) + KJ0 = KJDECA(IC) + DO 300 K = 1, KTLOOP + CC2(K,IJ) = CC2(K,IJ) - CC2(K,IK0) * CC2(K,KJ0) + 300 CONTINUE + 305 CONTINUE +C + 310 CONTINUE +C +C ********************************************************************* +C * VDIAG = 1 / CURRENT DIAGONAL TERM OF THE DECOMPOSED MATRIX * +C ********************************************************************* +C + IAR = JARRDIAG(J,NCSP) + DO 400 K = 1, KTLOOP + VDIAG(K,J) = 1.0d0 / CC2(K,IAR) + 400 CONTINUE +C +C ********************************************************************* +C *** SECOND LOOP OF DECOMPOSTION *** +C ********************************************************************* +C JZEROA = IDENTIFIES THE ARRAY POSITION OF EACH JLOZ1..JHIZ1 TERM +C + JL = JLOZ1(J,NCSP) + JH = JHIZ1(J,NCSP) + DO 505 JC = JL, JH + IJA = JZEROA(JC) + DO 500 K = 1, KTLOOP + CC2(K,IJA) = CC2(K,IJA) * VDIAG(K,J) + 500 CONTINUE + 505 CONTINUE +C + 510 CONTINUE +C +C ********************************************************************* +C ********************* END OF SUBROUTINE DECOMP ********************* +C ********************************************************************* +C + RETURN + END SUBROUTINE DECOMP diff --git a/code/define.h b/code/define.h new file mode 100644 index 0000000..504bce0 --- /dev/null +++ b/code/define.h @@ -0,0 +1,184 @@ + +! $Id: define.h,v 1.6 2012/03/01 22:00:26 daven Exp $ +! +!****************************************************************************** +! Include file "define.h" specifies C-preprocessor "switches" that are +! used to include or exclude certain sections of code. +! (bmy, bdf, 1/30/98, 11/6/08) +! +! List of "Switches" +! =========================================================================== +! (1 ) GCAP : Enables code for GCAP met fields & chemistry +! (2 ) GEOS_3 : Enables code for GEOS-3 met fields & chemistry +! (3 ) GEOS_4 : Enables code for GEOS-4 met fields & chemistry +! (4 ) GEOS_5 : Enables code for GEOS-5 met fields & chemistry +! (5 ) GRIDREDUCED : Enables code for reduced stratosphere grids +! (6 ) GRID1x1 : Enables code for 1 x 1 GLOBAL GRID +! (7 ) NESTED_CH : Enables code for 1 x 1 CHINA NESTED GRID +! (8 ) NESTED_NA : Enables code for 1 x 1 N. AM. NESTED GRID +! (9 ) GRID1x125 : Enables code for 1 x 1.25 GLOBAL GRID +! (10) GRID2x25 : Enables code for 2 x 2.5 GLOBAL GRID +! (11) GRID4x5 : Enables code for 4 x 5 GLOBAL GRID +! (12) COMPAQ : Enables code for Alpha w/ COMPAQ/HP Alpha compiler +! (13) IBM_AIX : Enables code for IBM/AIX compiler +! (14) LINUX_PGI : Enables code for Linux w/ PGI compiler +! (15) LINUX_IFORT : Enables code for Linux v8 or v9 "IFORT" compiler +! (16) SGI_MIPS : Enables code for SGI Origin w/ MIPS compiler +! (17) SPARC : Enables code for Sun w/ SPARC or Sun Studio compiler +! +! NOTES: +! (1 ) "define.h" is #include'd at the top of CMN_SIZE. All subroutines +! that normally reference CMN_SIZE will also reference "define.h". +! (2 ) Only define the "switches" that are *absolutely* needed for a +! given implementation, as the criteria for code inclusion/exclusion +! is the #if defined() statement. Undefined "switches" are "off". +! (3 ) To turn off a switch, comment that line of code out. +! (4 ) As of 11/30/99, DO_MASSFLUX is obsolete, since the mass flux +! arrays are now declared allocatable in "diag_mod.f". +! (5 ) Eliminate DO_MASSB switch -- ND63 diagnostic is now obsolete. +! (bmy, 4/12/00) +! (6 ) Add GEOS_3 and GRID1x1 switches for future use (bmy, 7/7/00) +! (7 ) Make sure that one of FULLCHEM, SMALLCHEM, or LGEOSCO is turned on. +! Also cosmetic changes. (bmy, 10/3/00) +! (8 ) Added new switches "DEC_COMPAQ" and "SGI" (bmy, 3/9/01) +! (9 ) Added new "LINUX" switch (bmy, 7/16/01) +! (10) Added new "GEOS_4" switch for GEOS-4/fvDAS met fields (bmy, 11/21/01) +! (11) Now enclose switch names in ' ', since the PGI compiler chokes +! on barewords (bmy, 3/20/02) +! (12) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation (bmy, 6/25/02) +! (13) Removed GEOS_2 switch; added GEOS_4 switch. Also added SPARC switch +! to invoke Sun/Sparc specific code. (bmy, 3/23/03) +! (14) Added IBM_AIX switch (bmy, 6/27/03) +! (15) Added INTEL_FC switch (bmy, 10/21/03) +! (16) Added GRID30LEV switch for 30L GEOS-3 or GEOS-4 grid (bmy, 10/31/03) +! (17) Renamed cpp switch "LINUX" to "LINUX_PGI". Renamed cpp switch +! "INTEL_FC" to "LINUX_IFC". Renamed cpp switch "SGI" to "SGI_MIPS". +! Added cpp switch "LINUX_EFC". Removed cpp switch SMALLCHEM. +! (bmy, 12/2/03) +! (18) Added "A_LLK_03" switch to denote GEOS-4 "a_llk_03" met fields. This +! will be temporary since "a_llk_03" met fields will be replaced by +! a newer product. (bmy, 3/22/04) +! (19) Added NESTED_NA and NESTED_CH cpp switches. Also add GRID1x125 +! cpp switch. (bmy, 12/1/04) +! (20) Removed obsolete A_LLK_03, LFASTJ, LSLOWJ, FULLCHEM, LGEOSCO switches. +! Also added extra switches for GCAP and GEOS_5 met fields. +! (bmy, 6/23/05) +! (21) Added LINUX_IFORT switch to delineate Intel compilers v8 or v9 +! from v7. (bmy, 10/18/05) +! (22) Removed GEOS_1, GEOS_STRAT, LINUX_IFC, LINUX_EFC (bmy, 8/4/06) +! (23) Renamed GRID30LEV to GRIDREDUCED (bmy, 2/7/07) +! (24) Added IN_CLOUD_OD flag for reprocessed GEOS-5 met. Added GRID05x0666 +! flag for GEOS-5 nested grids (yxw, dan, bmy, hyl, 11/6/08) +!****************************************************************************** +! +!============================================================================== +! Undefine all "switches" so that they cannot be accidentally reset +!============================================================================== +#undef GCAP +#undef GEOS_3 +#undef GEOS_4 +#undef GEOS_5 +#undef GEOS_FP +#undef GRIDREDUCED +#undef GRID4x5 +#undef GRID2x25 +#undef GRID1x125 +#undef GRID1x1 +#undef GRID05x0666 +#undef GRID025x03125 +#undef NESTED_NA +#undef NESTED_CH +#undef NESTED_SD +#undef COMPAQ +#undef IBM_AIX +#undef LINUX_PGI +#undef LINUX_IFORT +#undef SGI_MIPS +#undef SPARC +#undef IN_CLOUD_OD + +!============================================================================== +! Define the necessary "switches" for GEOS-CHEM. +! Give each switch its own name as a value, since this will prevent +! the C-preprocessor overwriting the name everywhere in the code. +!============================================================================== + +!----- Model types ----- +!#define GCAP 'GCAP' +!#define GEOS_3 'GEOS_3' +!#define GEOS_4 'GEOS_4' +#define GEOS_5 'GEOS_5' +!#define GEOS_FP 'GEOS_FP' + +!----- Grid sizes ----- +!#define NESTED_CH 'NESTED_CH' +!#define NESTED_NA 'NESTED_NA' +!#define NESTED_SD 'NESTED_SD' +!#define GRID05x0666 'GRID05x0666' +!#define GRID025x03125 'GRID025x03125' +!#define GRID1x1 'GRID1x1' +!#define GRID1x125 'GRID1x125' +!#define GRID2x25 'GRID2x25' +#define GRID4x5 'GRID4x5' +#define GRIDREDUCED 'GRIDREDUCED' + +!----- Compilers ----- +!#define COMPAQ 'COMPAQ' +!#define IBM_AIX 'IBM_AIX' +!#define LINUX_PGI 'LINUX_PGI' +#define LINUX_IFORT 'LINUX_IFORT' +!#define SGI_MIPS 'SGI_MIPS' +!#define SPARC 'SPARC' + +!----- FOR GEOS-5 MET FIELDS ONLY ----- +! NOTE: If you are using GEOS-5 met fields that were reprocessed to +! correctly regrid the in-cloud optical depth and cloud fraction fields, +! then be sure to uncomment the following line of code. This will cause +! FAST-J to interpret the optical depth correctly. Leaving this option +! commented will cause a "quick fix" (i.e. multiplying the optical depth +! by the cloud fracton) to be applied, which should be a good enough fix +! in the meantime. (bmy, hyl, 10/24/08) +#define IN_CLOUD_OD 'IN_CLOUD_OD' + +!============================================================================== +! Force a compile error if IN_CLOUD_OD is used with GEOS_3 or GEOS_4 +!============================================================================== +#if defined(GEOS_3) || defined(GEOS_4) || defined (GCAP) +#if defined(IN_CLOUD_OD) +#error "ERROR: IN_CLOUD_OD option set with GEOS_3, GEOS_4, or GCAP" +#endif +#endif + +!============================================================================== +! Force a compile error if IN_CLOUD_OD is used with GEOS_3 or GEOS_4 +!============================================================================== +#if defined(GEOS_3) || defined(GEOS_4) || defined (GCAP) +#if defined(IN_CLOUD_OD) +#error "ERROR: IN_CLOUD_OD option set with GEOS_3, GEOS_4, or GCAP" +#endif +#endif + +!============================================================================== +! Force a compile error if GEOS_1, GEOS_STRAT, GEOS_3, GEOS_4 are undefined +!============================================================================== +#if !defined(GEOS_3) && !defined(GEOS_4) && !defined(GEOS_5) && !defined(GEOS_FP) && !defined(GCAP) +#error "ERROR: GEOS_STRAT, GEOS_3, GEOS_4, GEOS_5, and GCAP" +#error "are ALL und efined in header file define.h" +#endif + +!============================================================================== +! Force a compile error if GRID1x1, GRID2x25, and GRID4x5 are all undefined +!============================================================================== +#if !defined(GRID2x25) && !defined(GRID4x5) && !defined(GRID1x125) && !defined(GRID1x1) && !defined(GRID05x0666) && !defined(GRID025x03125) +#error "ERROR: GRID4x5, GRID2x25, GRID1x125, GRID05x0666 and GRID1x1" +#error "are ALL undefined in header file define.h" +#endif + +!============================================================================== +! Force a compile error if all compiler switches are undefined +!============================================================================== +#if !defined(COMPAQ) && !defined(IBM_AIX) && !defined(LINUX_PGI) && !defined(LINUX_IFORT) && !defined(SGI_MIPS) && !defined(SPARC) +#error "ERROR: One of COMPAQ, IBM_AIX, LINUX_PGI, LINUX_IFORT," +#error "SGI_MIPS, SPARC must be defined in header file define.h" +#endif diff --git a/code/define.h~ b/code/define.h~ new file mode 100644 index 0000000..5d039db --- /dev/null +++ b/code/define.h~ @@ -0,0 +1,184 @@ + +! $Id: define.h,v 1.6 2012/03/01 22:00:26 daven Exp $ +! +!****************************************************************************** +! Include file "define.h" specifies C-preprocessor "switches" that are +! used to include or exclude certain sections of code. +! (bmy, bdf, 1/30/98, 11/6/08) +! +! List of "Switches" +! =========================================================================== +! (1 ) GCAP : Enables code for GCAP met fields & chemistry +! (2 ) GEOS_3 : Enables code for GEOS-3 met fields & chemistry +! (3 ) GEOS_4 : Enables code for GEOS-4 met fields & chemistry +! (4 ) GEOS_5 : Enables code for GEOS-5 met fields & chemistry +! (5 ) GRIDREDUCED : Enables code for reduced stratosphere grids +! (6 ) GRID1x1 : Enables code for 1 x 1 GLOBAL GRID +! (7 ) NESTED_CH : Enables code for 1 x 1 CHINA NESTED GRID +! (8 ) NESTED_NA : Enables code for 1 x 1 N. AM. NESTED GRID +! (9 ) GRID1x125 : Enables code for 1 x 1.25 GLOBAL GRID +! (10) GRID2x25 : Enables code for 2 x 2.5 GLOBAL GRID +! (11) GRID4x5 : Enables code for 4 x 5 GLOBAL GRID +! (12) COMPAQ : Enables code for Alpha w/ COMPAQ/HP Alpha compiler +! (13) IBM_AIX : Enables code for IBM/AIX compiler +! (14) LINUX_PGI : Enables code for Linux w/ PGI compiler +! (15) LINUX_IFORT : Enables code for Linux v8 or v9 "IFORT" compiler +! (16) SGI_MIPS : Enables code for SGI Origin w/ MIPS compiler +! (17) SPARC : Enables code for Sun w/ SPARC or Sun Studio compiler +! +! NOTES: +! (1 ) "define.h" is #include'd at the top of CMN_SIZE. All subroutines +! that normally reference CMN_SIZE will also reference "define.h". +! (2 ) Only define the "switches" that are *absolutely* needed for a +! given implementation, as the criteria for code inclusion/exclusion +! is the #if defined() statement. Undefined "switches" are "off". +! (3 ) To turn off a switch, comment that line of code out. +! (4 ) As of 11/30/99, DO_MASSFLUX is obsolete, since the mass flux +! arrays are now declared allocatable in "diag_mod.f". +! (5 ) Eliminate DO_MASSB switch -- ND63 diagnostic is now obsolete. +! (bmy, 4/12/00) +! (6 ) Add GEOS_3 and GRID1x1 switches for future use (bmy, 7/7/00) +! (7 ) Make sure that one of FULLCHEM, SMALLCHEM, or LGEOSCO is turned on. +! Also cosmetic changes. (bmy, 10/3/00) +! (8 ) Added new switches "DEC_COMPAQ" and "SGI" (bmy, 3/9/01) +! (9 ) Added new "LINUX" switch (bmy, 7/16/01) +! (10) Added new "GEOS_4" switch for GEOS-4/fvDAS met fields (bmy, 11/21/01) +! (11) Now enclose switch names in ' ', since the PGI compiler chokes +! on barewords (bmy, 3/20/02) +! (12) Changed RCS ID tag comment character from "C" to "!" to allow freeform +! compilation (bmy, 6/25/02) +! (13) Removed GEOS_2 switch; added GEOS_4 switch. Also added SPARC switch +! to invoke Sun/Sparc specific code. (bmy, 3/23/03) +! (14) Added IBM_AIX switch (bmy, 6/27/03) +! (15) Added INTEL_FC switch (bmy, 10/21/03) +! (16) Added GRID30LEV switch for 30L GEOS-3 or GEOS-4 grid (bmy, 10/31/03) +! (17) Renamed cpp switch "LINUX" to "LINUX_PGI". Renamed cpp switch +! "INTEL_FC" to "LINUX_IFC". Renamed cpp switch "SGI" to "SGI_MIPS". +! Added cpp switch "LINUX_EFC". Removed cpp switch SMALLCHEM. +! (bmy, 12/2/03) +! (18) Added "A_LLK_03" switch to denote GEOS-4 "a_llk_03" met fields. This +! will be temporary since "a_llk_03" met fields will be replaced by +! a newer product. (bmy, 3/22/04) +! (19) Added NESTED_NA and NESTED_CH cpp switches. Also add GRID1x125 +! cpp switch. (bmy, 12/1/04) +! (20) Removed obsolete A_LLK_03, LFASTJ, LSLOWJ, FULLCHEM, LGEOSCO switches. +! Also added extra switches for GCAP and GEOS_5 met fields. +! (bmy, 6/23/05) +! (21) Added LINUX_IFORT switch to delineate Intel compilers v8 or v9 +! from v7. (bmy, 10/18/05) +! (22) Removed GEOS_1, GEOS_STRAT, LINUX_IFC, LINUX_EFC (bmy, 8/4/06) +! (23) Renamed GRID30LEV to GRIDREDUCED (bmy, 2/7/07) +! (24) Added IN_CLOUD_OD flag for reprocessed GEOS-5 met. Added GRID05x0666 +! flag for GEOS-5 nested grids (yxw, dan, bmy, hyl, 11/6/08) +!****************************************************************************** +! +!============================================================================== +! Undefine all "switches" so that they cannot be accidentally reset +!============================================================================== +#undef GCAP +#undef GEOS_3 +#undef GEOS_4 +#undef GEOS_5 +#undef GEOS_FP +#undef GRIDREDUCED +#undef GRID4x5 +#undef GRID2x25 +#undef GRID1x125 +#undef GRID1x1 +#undef GRID05x0666 +#undef GRID025x03125 +#undef NESTED_NA +#undef NESTED_CH +#undef NESTED_SD +#undef COMPAQ +#undef IBM_AIX +#undef LINUX_PGI +#undef LINUX_IFORT +#undef SGI_MIPS +#undef SPARC +#undef IN_CLOUD_OD + +!============================================================================== +! Define the necessary "switches" for GEOS-CHEM. +! Give each switch its own name as a value, since this will prevent +! the C-preprocessor overwriting the name everywhere in the code. +!============================================================================== + +!----- Model types ----- +!#define GCAP 'GCAP' +!#define GEOS_3 'GEOS_3' +!#define GEOS_4 'GEOS_4' +!#define GEOS_5 'GEOS_5' +#define GEOS_FP 'GEOS_FP' + +!----- Grid sizes ----- +!#define NESTED_CH 'NESTED_CH' +!#define NESTED_NA 'NESTED_NA' +!#define NESTED_SD 'NESTED_SD' +!#define GRID05x0666 'GRID05x0666' +!#define GRID025x03125 'GRID025x03125' +!#define GRID1x1 'GRID1x1' +!#define GRID1x125 'GRID1x125' +!#define GRID2x25 'GRID2x25' +#define GRID4x5 'GRID4x5' +#define GRIDREDUCED 'GRIDREDUCED' + +!----- Compilers ----- +!#define COMPAQ 'COMPAQ' +!#define IBM_AIX 'IBM_AIX' +!#define LINUX_PGI 'LINUX_PGI' +#define LINUX_IFORT 'LINUX_IFORT' +!#define SGI_MIPS 'SGI_MIPS' +!#define SPARC 'SPARC' + +!----- FOR GEOS-5 MET FIELDS ONLY ----- +! NOTE: If you are using GEOS-5 met fields that were reprocessed to +! correctly regrid the in-cloud optical depth and cloud fraction fields, +! then be sure to uncomment the following line of code. This will cause +! FAST-J to interpret the optical depth correctly. Leaving this option +! commented will cause a "quick fix" (i.e. multiplying the optical depth +! by the cloud fracton) to be applied, which should be a good enough fix +! in the meantime. (bmy, hyl, 10/24/08) +#define IN_CLOUD_OD 'IN_CLOUD_OD' + +!============================================================================== +! Force a compile error if IN_CLOUD_OD is used with GEOS_3 or GEOS_4 +!============================================================================== +#if defined(GEOS_3) || defined(GEOS_4) || defined (GCAP) +#if defined(IN_CLOUD_OD) +#error "ERROR: IN_CLOUD_OD option set with GEOS_3, GEOS_4, or GCAP" +#endif +#endif + +!============================================================================== +! Force a compile error if IN_CLOUD_OD is used with GEOS_3 or GEOS_4 +!============================================================================== +#if defined(GEOS_3) || defined(GEOS_4) || defined (GCAP) +#if defined(IN_CLOUD_OD) +#error "ERROR: IN_CLOUD_OD option set with GEOS_3, GEOS_4, or GCAP" +#endif +#endif + +!============================================================================== +! Force a compile error if GEOS_1, GEOS_STRAT, GEOS_3, GEOS_4 are undefined +!============================================================================== +#if !defined(GEOS_3) && !defined(GEOS_4) && !defined(GEOS_5) && !defined(GEOS_FP) && !defined(GCAP) +#error "ERROR: GEOS_STRAT, GEOS_3, GEOS_4, GEOS_5, and GCAP" +#error "are ALL und efined in header file define.h" +#endif + +!============================================================================== +! Force a compile error if GRID1x1, GRID2x25, and GRID4x5 are all undefined +!============================================================================== +#if !defined(GRID2x25) && !defined(GRID4x5) && !defined(GRID1x125) && !defined(GRID1x1) && !defined(GRID05x0666) && !defined(GRID025x03125) +#error "ERROR: GRID4x5, GRID2x25, GRID1x125, GRID05x0666 and GRID1x1" +#error "are ALL undefined in header file define.h" +#endif + +!============================================================================== +! Force a compile error if all compiler switches are undefined +!============================================================================== +#if !defined(COMPAQ) && !defined(IBM_AIX) && !defined(LINUX_PGI) && !defined(LINUX_IFORT) && !defined(SGI_MIPS) && !defined(SPARC) +#error "ERROR: One of COMPAQ, IBM_AIX, LINUX_PGI, LINUX_IFORT," +#error "SGI_MIPS, SPARC must be defined in header file define.h" +#endif diff --git a/code/diag03_mod.f b/code/diag03_mod.f new file mode 100644 index 0000000..9a4eb81 --- /dev/null +++ b/code/diag03_mod.f @@ -0,0 +1,441 @@ +! $Id: diag03_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE DIAG03_MOD +! +!****************************************************************************** +! Module DIAG03_MOD contains arrays and routines for archiving the ND03 +! diagnostic -- Hg emissions, mass, and production. (bmy, 1/21/05, 9/5/06) +! +! Module Variables: +! ============================================================================ +! (1 ) AD03 (REAL*4) : Array for Hg emissions & ocean masses +! (2 ) AD03_Hg2_Hg0 (REAL*4) : Array for Hg(II) produced from Hg(0) +! (3 ) AD03_Hg2_OH (REAL*4) : Array for Hg(II) produced from OH +! (4 ) AD03_Hg2_O3 (REAL*4) : Array for Hg(II) produced from O3 +! +! Module Routines: +! ============================================================================ +! (1 ) ZERO_DIAG03 : Sets all module arrays to zero +! (2 ) WRITE_DIAG03 : Writes data in module arrays to bpch file +! (3 ) INIT_DIAG03 : Allocates all module arrays +! (4 ) CLEANUP_DIAG03 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag03_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary pch file I/O +! (2 ) error_mod.f : Module w/ NaN and other error check routines +! (3 ) file_mod.f : Module w/ file unit numbers and error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) time_mod.f : Module w/ routines to compute date & time +! +! Nomenclature: +! ============================================================================ +! (1 ) Hg(0) a.k.a. Hg0 : Elemental mercury +! (2 ) Hg(II) a.k.a. Hg2 : Divalent mercury +! (3 ) HgP : Particulate mercury +! +! NOTES: +! (1 ) Updated for GCAP grid (bmy, 6/28/05) +! (2 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (3 ) Add 2 extra diagnostics to ND03. Set PD03=15. (cdh, bmy, 12/15/05) +! (4 ) Add loss of Hg2 by sea salt (eck, bmy, 4/6/06) +! (5 ) Replace TINY(1d0) w/ 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag03_mod.f" + !================================================================= + + ! Make everything PUBLIC + PUBLIC + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + INTEGER :: ND03, LD03 + INTEGER, PARAMETER :: PD03 = 16 + + ! Arrays + REAL*4, ALLOCATABLE :: AD03(:,:,:) + REAL*4, ALLOCATABLE :: AD03_Hg2_Hg0(:,:,:) + REAL*4, ALLOCATABLE :: AD03_Hg2_OH(:,:,:) + REAL*4, ALLOCATABLE :: AD03_Hg2_O3(:,:,:) + REAL*4, ALLOCATABLE :: AD03_Hg2_SS(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE ZERO_DIAG03 +! +!****************************************************************************** +! Subroutine ZERO_DIAG03 zeroes the ND03 diagnostic arrays. +! (bmy, 1/21/05, 4/6/06) +! +! NOTES: +! (1 ) Now references N_Hg_CATS from "tracerid_mod.f". Now zero AD03_Hg2_SS +! array. (bmy, 4/6/06) +!****************************************************************************** +! + ! References to F90 modules + USE TRACERID_MOD, ONLY : N_Hg_CATS + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: I, J, L, N + + !================================================================= + ! ZERO_DIAG03 begins here! + !================================================================= + + ! Exit if ND03 is turned off + IF ( ND03 == 0 ) RETURN + + ! Zero arrays +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N ) +!$OMP+SCHEDULE( DYNAMIC ) + DO L = 1, LD03 + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Zero spatial 3-D arrays + AD03_Hg2_Hg0(I,J,L) = 0e0 + AD03_Hg2_OH(I,J,L) = 0e0 + AD03_Hg2_O3(I,J,L) = 0e0 + + ! Zero spatial 2-D arrays + IF ( L == 1 ) THEN + DO N = 1, PD03-3 + AD03(I,J,N) = 0e0 + ENDDO + + DO N = 1, N_Hg_CATS + AD03_Hg2_SS(I,J,N) = 0e0 + ENDDO + ENDIF + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE ZERO_DIAG03 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG03 +! +!****************************************************************************** +! Subroutine WRITE_DIAG03 writes the ND03 diagnostic arrays to the binary +! punch file at the proper time. (bmy, 1/21/05, 2/24/06) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) HG-SRCE : Anthropogenic HG0 emission : kg : 1 +! (2 ) HG-SRCE : Total mass of oceanic Hg0 : kg : 1 +! (3 ) HG-SRCE : Oceanic HgO emission : kg : 1 +! (4 ) HG-SRCE : Land reemission : kg : 1 +! (5 ) HG-SRCE : Land natural emission : kg : 1 +! (6 ) HG-SRCE : Anthropogenic Hg2 emission : kg : 1 +! (7 ) HG-SRCE : Total mass of oceanic Hg2 : kg : 1 +! (8 ) HG-SRCE : Mass of Hg2 sunk in the ocean : kg : 1 +! (9 ) HG-SRCE : Anthropogenic HgP emission : kg : 1 +! (10) HG-SRCE : Henry's law piston velocity Kw : cm/h : em timesteps +! (11) HG-SRCE : Mass of Hg(C) : kg : 1 +! (12) HG-SRCE : Converted to Colloidal : kg : 1 +! (13) PL-HG2-$ : Production of Hg2 from Hg0 : kg : 1 +! (14) PL-HG2-$ : Production of Hg2 from rxn w/OH : kg : 1 +! (15) PL-HG2-$ : Production of Hg2 from rxn w/O3 : kg : 1 +! (16) PL-HG2-$ : Loss of Hg2 from rxn w/ seasalt : kg : 1 +! +! NOTES: +! (1 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (2 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (3 ) Add HgC ocean mass and converted to colloidal to ND03 diagnostic. +! The units of the Kw and conversion terms in ND03 should be kg +! and not divided by the scale factor. (cdh, sas, bmy, 2/26/02) +! (4 ) Replace TINY(1d0) w/ 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_MODELNAME, GET_HALFPOLAR + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : GET_CT_EMIS, GET_DIAGb, GET_DIAGe + USE TRACERID_MOD, ONLY : N_Hg_CATS + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! TINDEX + + ! Local variables + INTEGER :: CENTER180, HALFPOLAR, IFIRST + INTEGER :: JFIRST, LFIRST, LMAX + INTEGER :: M, N, NN + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR) + REAL*4 :: LONRES, LATRES + REAL*8 :: DIAGb, DIAGe, SCALE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY, RESERVED, UNIT + + !================================================================= + ! WRITE_DIAG03 begins here! + !================================================================= + + ! Exit if ND03 is turned off + IF ( ND03 == 0 ) RETURN + + ! Initialize + CENTER180 = 1 + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + HALFPOLAR = GET_HALFPOLAR() + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LATRES = DJSIZE + LFIRST = 1 + LONRES = DISIZE + MODELNAME = GET_MODELNAME() + RESERVED = '' + SCALE = DBLE( GET_CT_EMIS() ) + 1d-32 + + !================================================================= + ! Write data to the bpch file + !================================================================= + + ! Loop over ND03 diagnostic tracers + DO M = 1, TMAX(3) + + ! Get ND03 tracer # + N = TINDEX(3,M) + + ! Pick the proper array & dimensions + IF ( N == 1 .or. N == 3 .or. N == 4 .or. + & N == 5 .or. N == 6 .or. N == 9 ) THEN + + !-------------------------------- + ! #1,3,4,5,6,9: Hg emissions + !-------------------------------- + CATEGORY = 'HG-SRCE' + UNIT = 'kg' + LMAX = 1 + NN = N + ARRAY(:,:,1) = AD03(:,:,N) + + ELSE IF ( N == 2 .or. N == 7 ) THEN + + !-------------------------------- + ! #2,7: Hg0, Hg2 ocean masses + !-------------------------------- + CATEGORY = 'HG-SRCE' + UNIT = 'kg' + LMAX = 1 + NN = N + ARRAY(:,:,1) = AD03(:,:,N) / SCALE + + ELSE IF ( N == 8 ) THEN + + !-------------------------------- + ! #8: Hg2 sinking loss rate + !-------------------------------- + CATEGORY = 'HG-SRCE' + UNIT = 'kg' + LMAX = 1 + NN = N + ARRAY(:,:,1) = AD03(:,:,N) + + ELSE IF ( N == 10 ) THEN + + !-------------------------------- + ! #10: Kw (piston velocity) + ! Divide by # of emiss timesteps + !-------------------------------- + CATEGORY = 'HG-SRCE' + UNIT = 'cm/h' + LMAX = 1 + NN = N + ARRAY(:,:,1) = AD03(:,:,N) / SCALE + + ELSE IF ( N == 11 ) THEN + + !-------------------------------- + ! #11: Hg(C) ocean mass + !-------------------------------- + CATEGORY = 'HG-SRCE' + UNIT = 'kg' + LMAX = 1 + NN = N + ARRAY(:,:,1) = AD03(:,:,N) / SCALE + + ELSE IF ( N == 12 ) THEN + + !-------------------------------- + ! #12: Converted to colloidal + !-------------------------------- + CATEGORY = 'HG-SRCE' + UNIT = 'kg' + LMAX = 1 + NN = N + ARRAY(:,:,1) = AD03(:,:,N) + + ELSE IF ( N == 13 ) THEN + + !-------------------------------- + ! #13: Prod of Hg(II) from Hg(0) + !-------------------------------- + CATEGORY = 'PL-HG2-$' + UNIT = 'kg' + LMAX = LD03 + NN = 1 + ARRAY(:,:,1:LMAX) = AD03_Hg2_Hg0(:,:,1:LMAX) + + ELSE IF ( N == 14 ) THEN + + !-------------------------------- + ! #14: Prod of Hg(II) from OH + !-------------------------------- + CATEGORY = 'PL-HG2-$' + UNIT = 'kg' + LMAX = LD03 + NN = 2 + ARRAY(:,:,1:LMAX) = AD03_Hg2_OH(:,:,1:LMAX) + + ELSE IF ( N == 15 ) THEN + + !-------------------------------- + ! #15: Prod of Hg(II) from O3 + !-------------------------------- + CATEGORY = 'PL-HG2-$' + UNIT = 'kg' + LMAX = LD03 + NN = 3 + ARRAY(:,:,1:LMAX) = AD03_Hg2_O3(:,:,1:LMAX) + + ELSE IF ( N == 16 ) THEN + + !-------------------------------- + ! #16: Loss of Hg(II) from SS + ! NOTE: implement this better later + !-------------------------------- + CATEGORY = 'PL-HG2-$' + UNIT = 'kg' + LMAX = N_Hg_CATS + NN = 4 + ARRAY(:,:,1:LMAX) = AD03_Hg2_SS(:,:,1:LMAX) + + ELSE + + !-------------------------------- + ! Otherwise skip to next N + !-------------------------------- + CYCLE + + ENDIF + + ! Write data to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LMAX, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LMAX) ) + ENDDO + + ! Return to calling program + END SUBROUTINE WRITE_DIAG03 + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG03 +! +!****************************************************************************** +! Subroutine INIT_DIAG03 allocates all module arrays (bmy, 1/21/05, 4/6/06) +! +! NOTES: +! (1 ) Now allocates AD03_Hg2_SS (eck, bmy, 4/6/06) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE TRACERID_MOD, ONLY : N_Hg_CATS + +# include "CMN_SIZE" + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DIAG03 begins here! + !================================================================= + + ! Exit if ND03 is turned off + IF ( ND03 == 0 ) THEN + LD03 = 0 + RETURN + ENDIF + + ! Get number of levels for 3-D arrays + LD03 = MIN( ND03, LLPAR ) + + ! 2-D array ("HG-SRCE") + ALLOCATE( AD03( IIPAR, JJPAR, PD03-3 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD03' ) + + ! 3-D arrays ("PL-HG2-$") + ALLOCATE( AD03_Hg2_Hg0( IIPAR, JJPAR, LD03 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD03_Hg2_Hg0' ) + + ALLOCATE( AD03_Hg2_OH( IIPAR, JJPAR, LD03 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD03_Hg2_OH' ) + + ALLOCATE( AD03_Hg2_O3( IIPAR, JJPAR, LD03 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD03_Hg2_O3' ) + + ALLOCATE( AD03_Hg2_SS( IIPAR, JJPAR, N_Hg_CATS ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD03_Hg2_SS' ) + + ! Zero arrays + CALL ZERO_DIAG03 + + ! Return to calling program + END SUBROUTINE INIT_DIAG03 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG03 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG03 deallocates all module arrays +! (bmy, 1/21/05, 4/6/06) +! +! NOTES: +! (1 ) Now deallocates AD03_Hg2_SS (eck, bmy, 4/6/06) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG03 begins here! + !================================================================= + IF ( ALLOCATED( AD03 ) ) DEALLOCATE( AD03 ) + IF ( ALLOCATED( AD03_Hg2_Hg0 ) ) DEALLOCATE( AD03_Hg2_Hg0 ) + IF ( ALLOCATED( AD03_Hg2_OH ) ) DEALLOCATE( AD03_Hg2_OH ) + IF ( ALLOCATED( AD03_Hg2_O3 ) ) DEALLOCATE( AD03_Hg2_O3 ) + IF ( ALLOCATED( AD03_Hg2_SS ) ) DEALLOCATE( AD03_Hg2_SS ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG03 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG03_MOD diff --git a/code/diag04_mod.f b/code/diag04_mod.f new file mode 100644 index 0000000..2391de4 --- /dev/null +++ b/code/diag04_mod.f @@ -0,0 +1,287 @@ +! $Id: diag04_mod.f,v 1.2 2010/05/07 20:39:47 daven Exp $ + MODULE DIAG04_MOD +! +!****************************************************************************** +! Module DIAG04_MOD contains arrays and routines for archiving the ND04 +! diagnostic -- CO2 emissions and fluxes (bmy, 7/26/05, 9/5/06) +! +! Module Variables: +! ============================================================================ +! (1 ) AD04 (REAL*4) : Array for 2-D CO2 emissions/uptake +! (2 ) AD04_plane (REAL*4) : Array for 3-D CO2 emissions from aircraft +! (3 ) AD04_chem (REAL*4) : Array for 3-D CO2 emissions from chemical oxidation +! +! Module Routines: +! ============================================================================ +! (1 ) ZERO_DIAG04 : Sets all module arrays to zero +! (2 ) WRITE_DIAG04 : Writes data in module arrays to bpch file +! (3 ) INIT_DIAG04 : Allocates all module arrays +! (4 ) CLEANUP_DIAG04 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag04_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary pch file I/O +! (2 ) error_mod.f : Module w/ NaN and other error check routines +! (3 ) file_mod.f : Module w/ file unit numbers and error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) time_mod.f : Module w/ routines to compute date & time +! +! NOTES: +! (1 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (2 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (3 ) Modified for ship emissions (2-D), aircraft emissions (3-D) and +! chemical source for CO2 (3-D) (RayNassar, 2009-12-23) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag04_mod.f" + !================================================================= + + ! Make everything PUBLIC + PUBLIC + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + INTEGER :: ND04, LD04 + INTEGER, PARAMETER :: PD04 = 10 + + ! Arrays + REAL*4, ALLOCATABLE :: AD04(:,:,:) + REAL*4, ALLOCATABLE :: AD04_plane(:,:,:) + REAL*4, ALLOCATABLE :: AD04_chem(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE ZERO_DIAG04 +! +!****************************************************************************** +! Subroutine ZERO_DIAG04 zeroes the ND04 diagnostic array (bmy, 7/26/05) +!****************************************************************************** +! +! ! References to F90 modules + +# include "CMN_SIZE" ! Size parameters + + !================================================================= + ! ZERO_DIAG04 begins here! + !================================================================= + + ! Exit if ND04 is turned off + IF ( ND04 == 0 ) RETURN + + ! Zero 2-D array (for N=7 tracers) and 3-D plane and chem arrays + AD04(:,:,:) = 0e0 + AD04_plane(:,:,:) = 0e0 + AD04_chem(:,:,:) = 0e0 + + ! Return to calling program + END SUBROUTINE ZERO_DIAG04 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG04 +! +!****************************************************************************** +! Subroutine WRITE_DIAG04 writes the ND04 diagnostic arrays to the binary +! punch file at the proper time. (bmy, 7/26/05, 9/3/06) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) CO2-SRCE : CO2 fossil fuel emissions : molec/cm2/s : SCALE +! (2 ) CO2-SRCE : CO2 ocean emissions : molec/cm2/s : SCALE +! (3 ) CO2-SRCE : CO2 balanced biosphere : molec/cm2/s : SCALE +! (4 ) CO2-SRCE : CO2 biomass emissions : molec/cm2/s : SCALE +! (5 ) CO2-SRCE : CO2 biofuel emissions : molec/cm2/s : SCALE +! (6 ) CO2-SRCE : CO2 net terrestrial exchange : molec/cm2/s : SCALE +! (7 ) CO2-SRCE : CO2 ship emissions : molec/cm2/s : SCALE +! (8 ) CO2-SRCE : CO2 aircraft emissions (3-D) : molec/cm2/s : SCALE +! (9 ) CO2-SRCE : CO2 chemical source (3-D) : molec/cm2/s : SCALE +! (10) CO2-SRCE : CO2 chem source surf correct : molec/cm2/s : SCALE +! +! NOTES: +! (1 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (2 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_MODELNAME, GET_HALFPOLAR + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : GET_CT_EMIS, GET_DIAGb, GET_DIAGe + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! TINDEX + + ! Local variables + INTEGER :: CENTER180, HALFPOLAR, IFIRST, JFIRST + INTEGER :: LFIRST, LMAX, M, N + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR) + REAL*4 :: LONRES, LATRES + REAL*8 :: DIAGb, DIAGe, SCALE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY, RESERVED, UNIT + + !================================================================= + ! WRITE_DIAG04 begins here! + !================================================================= + + ! Exit if ND04 is turned off + IF ( ND04 == 0 ) RETURN + + ! Initialize + CENTER180 = 1 + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + HALFPOLAR = GET_HALFPOLAR() + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LATRES = DJSIZE + LFIRST = 1 + LONRES = DISIZE + MODELNAME = GET_MODELNAME() + RESERVED = '' + SCALE = DBLE( GET_CT_EMIS() ) + 1d-32 + + !================================================================= + ! Write data to the bpch file + ! Note: if any of the ARRAY or AD04* dimensions are wrong, the + ! run will crash with "ERROR RUNNING GEOS-CHEM" at the end. + !================================================================= + + ! Loop over ND04 diagnostic tracers + DO M = 1, TMAX(4) + + ! Get quantities + N = TINDEX(4,M) + + IF (N <= 7) THEN + + CATEGORY = 'CO2-SRCE' + UNIT = 'molec/cm2/s' + !UNIT = '' ! Let GAMAP pick the unit + LMAX = 1 + ARRAY(:,:,1) = AD04(:,:,N) / SCALE + + ELSEIF (N == 8) THEN + + CATEGORY = 'CO2-SRCE' + UNIT = 'molec/cm3/s' + LMAX = LD04 + ARRAY(:,:,1:LMAX) = AD04_plane(:,:,1:LMAX) / SCALE + + ELSEIF (N == 9) THEN + + CATEGORY = 'CO2-SRCE' + UNIT = 'molec/cm3/s' + LMAX = LD04 + ARRAY(:,:,1:LMAX) = AD04_chem(:,:,1:LMAX) / SCALE + + ELSEIF (N == 10) THEN + + CATEGORY = 'CO2-SRCE' + UNIT = 'molec/cm2/s' + LMAX = 1 + ARRAY(:,:,1) = AD04(:,:,N) / SCALE + + ELSE + + CYCLE + + ENDIF + + ! Write data to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LMAX, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LMAX) ) + + ENDDO + + ! Return to calling program + END SUBROUTINE WRITE_DIAG04 + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG04 +! +!****************************************************************************** +! Subroutine INIT_DIAG04 allocates all module arrays (bmy, 7/26/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DIAG04 begins here! + !================================================================= + + ! Exit if ND04 is turned off + IF ( ND04 == 0 ) RETURN + + ! Get number of levels for 3-D arrays + LD04 = MIN( ND04, LLPAR ) + + ! 2-D array ("CO2-SRCE") + +! ALLOCATE( AD04( IIPAR, JJPAR, PD04-2 ), STAT=AS ) + ALLOCATE( AD04( IIPAR, JJPAR, PD04 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD04' ) + + ! 3-D arrays ("CO2-SRCE") + + ALLOCATE( AD04_plane( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD04_plane' ) + + ALLOCATE( AD04_chem( IIPAR, JJPAR, LLPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD04_chem' ) + + ! Zero arrays + CALL ZERO_DIAG04 + + ! Return to calling program + END SUBROUTINE INIT_DIAG04 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG04 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG04 deallocates all module arrays (bmy, 7/26/05) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG04 begins here! + !================================================================= + + IF ( ALLOCATED( AD04 ) ) DEALLOCATE( AD04 ) + IF ( ALLOCATED( AD04_plane ) ) DEALLOCATE( AD04_plane ) + IF ( ALLOCATED( AD04_chem ) ) DEALLOCATE( AD04_chem ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG04 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG04_MOD diff --git a/code/diag1.f b/code/diag1.f new file mode 100644 index 0000000..b96b888 --- /dev/null +++ b/code/diag1.f @@ -0,0 +1,622 @@ +! $Id: diag1.f,v 1.1 2009/06/09 21:51:50 daven Exp $ + SUBROUTINE DIAG1 +! +!****************************************************************************** +! Subroutine DIAG1 accumulates diagnostic quantities every NDIAG minutes +! (bmy, bey, 6/16/98, 1/28/04) +! +! NOTES: +! (1 ) This subroutine was reconstructed from gmg's version of (10/10/97) +! (2 ) GISS-specific code has been eliminated (bmy, 3/15/99) +! (3 ) UWND, VWND, WW no longer needs to be passed (bmy, 4/7/99) +! (4 ) Use F90 syntax for declarations, etc (bmy, 4/7/99) +! (5 ) Remove counter KWACC...this is now redundant (bmy, 11/5/99) +! (6 ) ND31, ND33, ND35, ND67, and ND69 now use dynamically +! allocatable arrays declared in "diag_mod.f". (bmy, 3/9/00) +! (7 ) LTOTH is now an allocatable array in "diag_mod.f". (bmy, 3/17/00) +! (8 ) Add parallel loops over tracer where expedient (bmy, 5/4/00) +! (9 ) Updated comments and diagnostics list. Also add more parallel +! loops for ND31 and ND68. (bmy, 6/21/00) +! (10) Use NTRACE to dimension STT_VV instead of NNPAR (bmy, 10/17/00) +! (11) Removed obsolete code from 10/17/00 (bmy, 12/21/00) +! (12) Updated diagnostic list & comments, cosmetic changes (bmy, 6/19/01) +! (13) Updated diagnostic list & comments (bmy, 9/4/01) +! (14) Now reference AVGW from "dao_mod.f", and make sure it is allocated +! before we reference it in the ND68 diagnostic. Also reference PBL, +! PS, AIRDEN from "dao_mod.f". (bmy, 9/25/01) +! (15) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (16) Renamed ND33 to "ATMOSPHERIC COLUMN SUM OF TRACER", since this is +! a sum over all levels and not just in the troposphere. Also +! removed more obsolete code from 9/01. Now use P(I,J)+PTOP instead +! of PS, since that is the way to ensure that we use will be used +! consistently. Remove reference to PS from "dao_mod.f"(bmy, 4/11/02) +! (17) Replaced all instances of IM with IIPAR and JM with JJPAR, in order +! to prevent namespace confusion for the new TPCORE. Also removed +! obsolete, commented-out code. Also now replaced reference to +! P(IREF,JREF) with P(I,J). (bmy, 6/25/02) +! (18) Replaced references to P(I,J) with call to GET_PEDGE(I,J,1) from +! "pressure_mod.f" Eliminated obsolete commented-out code from +! 6/02. (dsa, bdf, bmy, 8/20/02) +! (19) Now reference AD, and BXHEIGHT from "dao_mod.f". Removed obsolete +! code. Now refEerence IDTOX from "tracerid_mod.f". (bmy, 11/6/02) +! (20) Now replace DXYP(J) with routine GET_AREA_M2 from "grid_mod.f" +! (bmy, 2/4/03) +! (21) Now compute PBL top for ND67 for GEOS-4/fvDAS. Also now include +! SCALE_HEIGHT from header file "CMN_GCTM". (bmy, 6/23/03) +! (22) Now references N_TRACERS, STT, and ITS_A_FULLCHEM_SIM from +! "tracer_mod.f" (bmy, 7/20/04) +! (23) Fixed ND67 PS-PBL for GCAP and GEOS-5 met fields (swu, bmy, 6/9/05) +! (24) Now archive ND30 diagnostic for land/water/ice flags (bmy, 8/18/05) +! (25) Now reference XNUMOL from "tracer_mod.f" (bmy, 10/25/05) +! (26) Remove support for GEOS-1 and GEOS-STRAT met fields (bmy, 8/4/06) +! (27) Added count for time in the troposphere - array AD54 (phs, 9/22/06) +! (28) Now only archive O3 in ND45 and ND47 at chem timsteps (phs, 1/24/07) +! (29) Bug fix: Update ND30 for both GEOS-3 and otherwise. Also now save +! 3-D pressure edges in ND31 instead of PS-PTOP. Revert to the ! +! pre-near-land ND30 diagnostic algorithm. (bmy, 1/28/04) +!****************************************************************************** +! List of GEOS-CHEM Diagnostics (bmy, 10/25/05) +! +! FLAG DIM'S QUANTITY UNITS +! ---- -------- -------- ----- +! ND01 (I,J,L,3) RADON 222 - LEAD 210 - BERYLLIUM 7 SOURCE [kg/s] +! +! ND02 (I,J,L,3) RADON 222 - LEAD 210 - BERYLLIUM 7 DECAY [kg/s] +! +! ND03 ---- Free Diagnostic +! ND04 ---- Free Diagnostic +! +! ND05 PROD/LOSS for SULFATE CHEMISTRY QUANTITIES +! (I,J,L) P(SO2) from DMS + OH [kg S] +! (I,J,L) P(SO2) from DMS + NO3 [kg S] +! (I,J,L) Total P(SO2) [kg S] +! (I,J,L) P(MSA) from DMS [kg S] +! (I,J,L) P(SO4) gas phase [kg S] +! (I,J,L) P(SO4) aqueous phase [kg S] +! (I,J,L) Total P(SO4) [kg S] +! (I,J,L) L(OH) by DMS [kg OH] +! (I,J,L) L(NO3) by DMS [kg NO3] +! (I,J,L) L(H2O2) [kg H2O2] +! +! ND06 (I,J) DESERT DUST EMISSIONS [kg] +! +! ND07 SOURCES OF BLACK CARBON & ORGANIC CARBON +! (I,J) BLACK CARBON from anthro sources [kg] +! (I,J) BLACK CARBON from biomass burning [kg] +! (I,J) BLACK CARBON from biofuels [kg] +! (I,J,L) Hydrophilic BC from Hydrophobic BC [kg] +! (I,J) ORGANIC CARBON from anthro sources [kg] +! (I,J) ORGANIC CARBON from biomass burning [kg] +! (I,J) ORGANIC CARBON from biofuels [kg] +! (I,J) ORGANIC CARBON from biogenic sources [kg] +! (I,J) Hydrophilic OC from Hydrophobic OC [kg] +! +! ND08 (I,J) SEA SALT EMISSIONS [kg] +! +! ND09 ---- Free Diagnostic +! ND10 ---- Free Diagnostic +! +! ND11 ACETONE SOURCES & SINKS +! (I,J) Acetone source from MONOTERPENES atoms C/cm2/s +! (I,J) Acetone source from METHYL BUTENOL atoms C/cm2/s +! (I,J) Acetone source from DIRECT EMISSION atoms C/cm2/s +! (I,J) Acetone source from DRY LEAF MATTER atoms C/cm2/s +! (I,J) Acetone source from GRASSLANDS atoms C/cm2/s +! (I,J) Acetone source from OCEANS atoms C/cm2/s +! (I,J) Acetone sink from OCEANS atoms C/cm2/s +! +! ND12 (I,J) FRACTION OF BOUNDARY LAYER OCCUPIED BY unitless +! LEVEL L (for new emissions in "setemis.f") +! +! ND13 TROPOSPHERIC SULFUR EMISSIONS +! (I,J) DMS kg S +! (I,J,L) Aircraft SO2 ( 1 <= L <= ND13 ) kg S +! (I,J,L) Anthro SO2 ( 1 <= L <= 2 ) kg S +! (I,J) Biomass SO2 kg S +! (I,J,L) Non-eruptive volcano SO2 ( 1 <= L <= ND13 ) kg S +! (I,J,L) Eruptive volcano SO2 ( 1 <= L <= ND13 ) kg S +! (I,J,L) Anthro SO4 ( 1 <= L <= 2 ) kg S +! (I,J) Anthro NH3 kg NH3 +! (I,J) Biomass NH3 kg NH3 +! (I,J) Biofuel NH3 kg NH3 +! +! ND14 (I,J,L,N) UPWARD MASS FLUX DUE TO WET CONVECTION kg/s +! ( 1 <= L <= ND14 ) +! +! ND15 (I,J,L,N) MASS CHANGE DUE TO BOUNDARY-LAYER MIXING kg/s +! ( 1 <= L <= ND15 ) +! +! ND16 (I,J,L) AREAL FRACTION OF LARGE-SCALE PRECIP unitless +! (I,J,L) AREAL FRACTION OF CONVECTIVE PRECIP unitless +! ( 1 <= L <= ND16 ) +! +! ND17 (I,J,L,4) RAINOUT FRACTION IN LARGE-SCALE PRECIP unitless +! (I,J,L,4) RAINOUT FRACTION IN CONVECTIVE PRECIP unitless +! ( 1 <= L <= ND17 ) +! +! ND18 (I,J,L,4) WASHOUT FRACTION IN LARGE-SCALE PRECIP unitless +! (I,J,L,4) WASHOUT FRACTION IN CONVECTIVE PRECIP unitless +! ( 1 <= L <= ND18 ) +! +! ND19 ---- Free Diagnostic +! +! ND20 (I,J,L,2) SAVE O3 PROD/LOSS RATES TO DISK molec/cm3/s +! ( 1 <= L <= LLTROP ) +! +! ND21 (I,J,L,3) CLOUD OPTICAL DEPTHS AND CLOUD FRACTIONS unitless +! ( 1 <= L <= ND21 ) +! +! ND22 (I,J,L,6) J-VALUES: NO2, HNO3, H2O2, CH2O, OH, O3 s^-1 +! ( 1 <= L <= ND22 ) +! +! ND23 ---- METHYL CHLOROFORM (CH3CCl3) LIFETIME years +! +! ND24 (I,J,L,N) EASTWARD MASS FLUX BY TRANSPORT kg/s +! ( 1 <= L <= ND24 ) +! +! ND25 (I,J,L,N) NORTHWARD MASS FLUX BY TRANSPORT kg/s +! ( 1 <= L <= ND25 ) +! +! ND26 (I,J,L,N) UPWARD MASS FLUX BY TRANSPORT kg/s +! ( 1 <= L <= ND26 ) +! +! ND27 (I,J,3) STRATOSPHERIC INFLUX of NOX, OX, HNO3 kg/s +! +! ND28 (I,J,10) BIOMASS BURNING EMISSIONS: molec/cm2/s +! NOX, CO, ALK4, ACET, MEK, +! ALD2, PRPE, C3H8, CH2O, C2H6 +! +! ND29 TROPOSPHERIC CO EMISSIONS molec/cm2/s +! (I,J) Anthropogenic +! (I,J) Biomass +! (I,J) Biofuel +! (I,J) CO produced from monoterpenes +! (I,J) CO produced from methanol +! +! ND30 (I,J) PLOT LAND MAP FOR GISS or GEOS models integers +! +! ND31 (I,J) SURFACE PRESSURE - PTOP mb +! +! ND32 TROPOSPHERIC NOx EMISSIONS +! (I,J,L) Aircraft ( 1 <= L <= LAIREMS ) molec/cm2/s +! (I,J,L) Anthropogenic ( 1 <= L <= NOXEXTENT ) molec/cm2/s +! (I,J) Biomass molec/cm2/s +! (I,J) Fertilization molec/cm2/s +! (I,J,L) Lightning ( 1 <= L <= LCONVM ) molec/cm2/s +! (I,J) Soils molec/cm2/s +! (I,J) Upper Boundary molec/cm2/s +! +! ND33 (I,J,N) ATMOSPHERIC COLUMN SUM OF TRACER kg +! +! ND34 (I,J,10) BIOFUEL BURNING EMISSIONS: molec/cm2/s +! NOx, CO, ALK4, ACET, MEK, +! ALD2, PRPE, C3H8, CH2O, C2H6 +! +! ND35 (I,J,N) TRACER AT 500 HPA ( L = 9 ) v/v +! +! ND36 (I,J,9) ANTHROPOGENIC EMISSIONS (for NSRCX == 3) molec/cm2/s +! NOx, CO, ALK4, ACET, +! MEK, ALD2, PRPE, C3H8, C2H6 +! OR CH3I EMISSIONS (for NSRCX == 2) ng/m2/s +! +! ND37 (I,J,L,4) FRACTION OF TRACER SCAVENGED BY CLOUD +! UPDRAFTS IN MOIST CONVECTION unitless +! ( 1 <= L <= ND37 ) +! +! ND38 (I,J,L,N) LOSS OF TRACER IN MOIST CONVECTION kg/s +! ( 1 <= L <= ND38 ) +! +! ND39 (I,J,L,N) LOSS OF TRACER IN AEROSOL WET DEPOSITION kg/s +! ( 1 <= L <= ND39 ) +! +! ND40 ---- Free diagnostic kg/m2 +! +! ND41 (I,J) AFTERNOON PBL DEPTH (1200-1600 LT) m +! +! ND42 ---- Free Diagnostic +! +! ND43 (I,J,L,2) OH CONCENTRATIONS (from SMVGEAR) and molec/cm3/s +! NO CONCENTRATIONS (from SMVGEAR) v/v +! ( 1 <= L <= ND43 ) +! +! ND44 (I,J,M) DRYDEP FLUXES molec/cm2/s +! (I,J,M) DRYDEP VELOCITIES cm/s +! ( M = NUMDEP ) +! +! ND45 (I,J,L,N) TRACER CONCENTRATION, AVERAGED BETWEEN v/v +! OTH_HR1 and OTH_HR2 (from "input.geos") +! ( 1 <= L <= ND45 ) +! +! ND46 (I,J,5) BIOGENIC EMISSIONS of ISOP, PRPE, ACET, molec/cm2/s +! MONOTERPENES, METHYL BUTENOL +! +! ND47 (I,J,L,N) DAILY (24-h) AVERAGE TRACER CONCENTRATIONS v/v +! ( 1 <= L <= ND47 ) +! +! ND48 (I,J,L,N) TIME SERIES AT N = NNSTA LOCATIONS +! FOR MS = 0, store tracer concentrations v/v +! FOR MS = 1, store the following +! N = 1, store O3 RURAL molec/cm3 +! N = 2, store OH RURAL molec/cm3 +! N = 3, store NOy RURAL molec/cm3 +! N = 4, store Drydep Vel for NO2 cm/s +! N = 5, store Drydep Vel for O3 cm/s +! N = 6, store Drydep Vel for PAN cm/s +! N = 7, store Drydep Vel for HNO3 cm/s +! N = 8, store Drydep Vel for H2O2 cm/s +! N = 9, store NO RURAL molec/cm3 +! (get I,J,L,MS,N from "inptr.ctm") +! +! ND49 (I,J,L,N) 3-D INSTANTANEOUS TRACER TIMESERIES v/v +! SAVED IN BINARY PUNCH FILE FORMAT +! (get I,J,L,N from "timeseries.dat") +! +! ND50 (I,J,L,N) 3-D 24-h AVERAGE TRACER TIMESERIES v/v +! SAVED IN BINARY PUNCH FILE FORMAT +! (get I,J,L,N from "timeseries.dat") +! +! ND51 (I,J,L,N) 3-D 1-4pm AVERAGE TRACER TIMESERIES v/v +! SAVED IN BINARY PUNCH FILE FORMAT +! (get I,J,L,N from "timeseries.dat") +! +! ND52 (I,J,L,N) HO2 aerosol uptake coefficient (gamma) unitless +! +! ND53 ---- Free Diagnostic +! +! ND54 (I,J,L) Time in troposphere (fraction of total time) unitless +! +! ND55 TROPOPAUSE DIAGNOSTICS +! (I,J) Tropopause level number unitless +! (I,J) Tropopause height km +! (I,J) Tropopause pressure hPa +! +! ND60 ---- Free Diagnostic +! +! ND61 ---- Free Diagnostic +! +! ND62 (I,J,N) INSTANTANEOUS COLUMN MIXING RATIO v/v +! +! ND63 ---- Free Diagnostic +! +! ND65 (I,J,L,N) PRODUCTION & LOSS OF SELECTED molec/cm3/s +! CHEMCIAL SPECIES (see "prodloss.dat") +! +! ND66 DAO 3-D FIELDS ( 1 <= L <= ND66 ) +! (I,J,L) UWND : U-winds m/s +! (I,J,L) VWND : V-winds m/s +! (I,J,L) TMPU : Temperature K +! (I,J,L) SPHU : Specific humidity g H20/kg air +! (I,J,L) CLDMAS : Convective Mass Flux kg/m2/s +! +! ND67 DAO SURFACE FIELDS +! (I,J) HFLUX : sensible heat flux from surface W/m2 +! (I,J) RADSWG : solar radiation @ ground W/m2 +! (I,J) PREACC : total precip. @ ground mm/day +! (I,J) PRECON : conv. precip. @ ground mm/day +! (I,J) TS : surface air temperature K +! (I,J) RADSWT : solar radiation @ atm. top W/m2 +! (I,J) USTAR : friction velocity m/s +! (I,J) Z0 : surface roughness height m +! (I,J) PBL : planetary boundary layer depth hPa +! (I,J) CLDFRC : column cloud fraction 0 - 1 +! (I,J) U10M : U-winds @ 10 meters altitude m/s +! (I,J) V10M : V-winds @ 10 meters altitude m/s +! (I,J) PS-PBL : Boundary Layer Top Pressure hPa +! (I,J) ALBD : Surface Albedo unitless +! (I,J) PHIS : Geopotential Heights m +! (I,J) CLTOP : Cloud Top Height levels +! (I,J) TROPP : Tropopause pressure hPa +! (I,J) SLP : Sea Level pressure hPa +! (I,J) TSKIN : Ground / sea surface temperature K +! (I,J) PARDF : Photosyn active diffuse rad W/m2 +! (I,J) PARDR : Photosyn active direct rad hPa +! (I,J) GWETTOP : Top soil wetness unitless +! +! ND68 GRID BOX QUANTITIES ( 1 <= L <= ND68 ) +! (I,J,L) BXHEIGHT : (grid box heights) m +! (I,J,L) AD :(air mass in grid box) kg +! (I,J,L) AVGW : mixing ratio of water vapor v/v +! (I,J,L) N_AIR : Air number density molec air/m3 +! +! ND69 (I,J) DXYP : grid box surface areas m2 +! +! ND70 ---- DEBUG PRINTOUT to stdout file via routine DEBUG_MSG +!***************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AD, AIRDEN, AVGW, BXHEIGHT + USE DAO_MOD, ONLY : PBL, IS_ICE, IS_WATER, IS_LAND, IS_NEAR + USE DIAG_MOD, ONLY : AD30, AD31, AD33, AD35, AD45, AD54 + USE DIAG_MOD, ONLY : AD47, AD67, AD68, AD69, LTOTH + USE GRID_MOD, ONLY : GET_AREA_M2 + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : ITS_TIME_FOR_CHEM + USE TRACER_MOD, ONLY : N_TRACERS, STT, TCVV + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : XNUMOLAIR + USE TRACERID_MOD, ONLY : IDTOX + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! Diagnostic arrays & parameters +# include "CMN_O3" ! FRACO3 +# include "CMN_GCTM" ! Physical constants + + ! Local variables + LOGICAL :: AVGW_ALLOCATED, IS_FULLCHEM, IS_CHEM + INTEGER :: I, J, K, L, N, NN, IREF, JREF, LN45 + REAL*8 :: FDTT, XLOCTM, AREA_M2 + REAL*8 :: STT_VV(IIPAR,JJPAR,LLPAR,N_TRACERS) + + !================================================================= + ! DIAG1 begins here! + !================================================================= + + ! Is it a fullchem run? + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_CHEM = ITS_TIME_FOR_CHEM() + + ! Compute conc. in mixing ratio for ND35, ND45, ND47 diagnostics + IF ( ND35 > 0 .or. ND45 > 0 .or. ND47 > 0 ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N ) + DO N = 1, N_TRACERS + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + STT_VV(I,J,L,N) = + & MAX( STT(I,J,L,N) * TCVV(N) / AD(I,J,L), 0d0 ) + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND30: Land/water/ice flags + !================================================================= + IF ( ND30 > 0 ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + IF ( IS_WATER( I, J ) ) AD30(I,J) = AD30(I,J) + 0e0 + IF ( IS_LAND ( I, J ) ) AD30(I,J) = AD30(I,J) + 1e0 + IF ( IS_ICE ( I, J ) ) AD30(I,J) = AD30(I,J) + 2e0 + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND31: Surface pressure diagnostic (PS - PTOP) in hPa + !================================================================= + IF ( ND31 > 0 ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) + DO L = 1, LD31 + DO J = 1, JJPAR + DO I = 1, IIPAR + AD31(I,J,L) = AD31(I,J,L) + GET_PEDGE( I, J, L ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND33: Atmospheric column sum of tracer [kg] + !================================================================= + IF ( ND33 > 0 ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N ) + DO N = 1, N_TRACERS + DO L = 1, LLPAR + DO J = 1, JJPAR + DO I = 1, IIPAR + AD33(I,J,N) = AD33(I,J,N) + STT(I,J,L,N) + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND35: 500 HPa fields. + ! + ! NOTES: + ! (1 ) Use level 9 for both GEOS-1 and GEOS-STRAT. + ! They are both close to 500 hPa (bmy, 4/7/99) + !================================================================= + IF ( ND35 > 0 ) THEN + L = 9 +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, N ) + DO N = 1, N_TRACERS + DO J = 1, JJPAR + DO I = 1, IIPAR + AD35(I,J,N) = AD35(I,J,N) + STT_VV(I,J,L,N) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND45: Tracer (V/V) at level 1 to level LD45, averaged over + ! the time period OTH_HR1 to OTH_HR2. + ! + ! Store pure O3 (as opposed to Ox) in the NTRACE+1 location of + ! AD45. FRACO3(I,J,L) is the fraction of Ox that is actually O3, + ! and is calculated in subroutine OHSAVE. + ! + ! NOTES: + ! (1 ) AD45 array replaces the AIJ array for this diagnostic + ! (bmy, 3/22/99) + ! (2 ) Add parallel loop over tracers (bmy, 5/4/00) + !================================================================= + IF ( ND45 > 0 ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N ) + DO N = 1, N_TRACERS + DO L = 1, LD45 + DO J = 1, JJPAR + DO I = 1, IIPAR + AD45(I,J,L,N) = AD45(I,J,L,N) + + & STT_VV(I,J,L,N) * LTOTH(I,J) + ENDDO + ENDDO + ENDDO + + ! NOTE: Only update on chem timesteps (phs, 1/24/07) + IF ( N == IDTOX .and. IS_FULLCHEM .and. IS_CHEM ) THEN + DO L = 1, LD45 + DO J = 1, JJPAR + DO I = 1, IIPAR + AD45(I,J,L,N_TRACERS+1) = AD45(I,J,L,N_TRACERS+1) + + & ( STT_VV(I,J,L,N) * FRACO3(I,J,L) * LTOTH(I,J) ) + ENDDO + ENDDO + ENDDO + ENDIF + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND47: Tracer (V/V) at level 1 to level LD45, + ! averaged from 0-24 hours + ! + ! Added parallel loop over tracers (bmy, 5/4/00) + !================================================================= + IF ( ND47 > 0 ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N ) + DO N = 1, N_TRACERS + DO L = 1, LD47 + DO J = 1, JJPAR + DO I = 1, IIPAR + AD47(I,J,L,N) = AD47(I,J,L,N) + STT_VV(I,J,L,N) + ENDDO + ENDDO + ENDDO + + ! NOTE: Only update on chem timesteps (phs, 1/24/07) + IF ( N == IDTOX .and. IS_FULLCHEM .and. IS_CHEM ) THEN + DO L = 1, LD47 + DO J = 1, JJPAR + DO I = 1, IIPAR + AD47(I,J,L,N_TRACERS+1) = AD47(I,J,L,N_TRACERS+1) + + & ( STT_VV(I,J,L,N) * FRACO3(I,J,L) ) + ENDDO + ENDDO + ENDDO + ENDIF + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND54: Count time the box was tropospheric + !================================================================= + IF ( ND54 > 0 ) THEN + + DO L = 1, LD54 + DO J = 1, JJPAR + DO I = 1, IIPAR + IF ( ITS_IN_THE_TROP(I,J,L) ) + & AD54(I,J,L) = AD54(I,J,L) + 1. + ENDDO + ENDDO + ENDDO + + ENDIF + + + !================================================================= + ! ND67: Store PBL top pressure [hPa] + !================================================================= + IF ( ND67 > 0 ) THEN + DO J = 1, JJPAR + DO I = 1, IIPAR + +#if defined( GEOS_3 ) + + ! PBL is in [hPa], subtract from PSurface + AD67(I,J,13) = AD67(I,J,13) + GET_PEDGE(I,J,1) - PBL(I,J) + +#else + + ! PBL is in [m], use hydrostatic law to get [hPa] + AD67(I,J,13) = AD67(I,J,13) + + & ( GET_PEDGE(I,J,1) * EXP( -PBL(I,J) / SCALE_HEIGHT ) ) + +#endif + + ENDDO + ENDDO + ENDIF + + !================================================================= + ! ND68: Quantity 1: BXHEIGHT(I,J,L) in meters + ! Quantity 2: AD(I,J,L) in kg + ! Quantity 3: AVGW(I,J,L) in v/v + ! Quantity 4: N_AIR(I,J,L) in molecules air / m3 + ! + ! NOTE: AVGW is now an allocatable array from "dao_mod.f" + !================================================================= + IF ( ND68 > 0 ) THEN + + ! Set a flag for whether AVGW is allocated or not + AVGW_ALLOCATED = ALLOCATED( AVGW ) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) + DO L = 1, LD68 + DO J = 1, JJPAR + DO I = 1, IIPAR + AD68(I,J,L,1) = AD68(I,J,L,1) + BXHEIGHT(I,J,L) + AD68(I,J,L,2) = AD68(I,J,L,2) + AD(I,J,L) + AD68(I,J,L,4) = AD68(I,J,L,4) + AIRDEN(L,I,J) * XNUMOLAIR + + ! Make sure AVGW is now allocated (bmy, 9/25/01) + IF ( AVGW_ALLOCATED ) THEN + AD68(I,J,L,3) = AD68(I,J,L,3) + AVGW(I,J,L) + ENDIF + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !================================================================= + ! ND69: Grid box surface areas [m2] + ! + ! NOTE: Only save areas on the first timestep since the + ! grid box surface areas are a time-invariant field. + !================================================================= + IF ( ND69 > 0 ) THEN + DO J = 1, JJPAR + AREA_M2 = GET_AREA_M2( J ) + + DO I = 1, IIPAR + AD69(I,J,1) = AREA_M2 + ENDDO + ENDDO + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG1 + diff --git a/code/diag3.f b/code/diag3.f new file mode 100644 index 0000000..8b51bfc --- /dev/null +++ b/code/diag3.f @@ -0,0 +1,3531 @@ +! $Id: diag3.f,v 1.3 2012/03/01 22:00:26 daven Exp $ + SUBROUTINE DIAG3 +! +!****************************************************************************** +! Subroutine DIAG3 prints out diagnostics to the BINARY format punch file +! (bmy, bey, mgs, rvm, 5/27/99, 12/15/08) +! +! NOTES: +! (40) Bug fix: Save levels 1:LD13 for ND13 diagnostic for diagnostic +! categories "SO2-AC-$" and "SO2-EV-$". Now reference F90 module +! "tracerid_mod.f". Now reference NUMDEP from "drydep_mod.f". +! Now save anthro, biofuel, biomass NH3 in ND13; also fixed ND13 +! tracer numbers. For ND13, change scale factor from SCALESRCE to 1. +! Now references "wetscav_mod.f". Now also save true tracer numbers +! for ND38 and ND39 diagnostic. Now also write out biomass SO2. +! Now convert ND01, ND02, ND44 diagnostics for Rn/Pb/Be from kg to +! kg/s here. (bmy, 1/24/03) +! (41) Now save out natural NH3 in ND13 as "NH3-NATU" (rjp, bmy, 3/23/03) +! (42) Now replace DXYP(JREF) by routine GET_AREA_M2, GET_XOFFSET, and +! GET_YOFFSET of "grid_mod.f". Now references "time_mod.f". +! DIAGb, DIAGe are now local variables. Now remove obsolete statements +! IF ( LBPNCH > 0 ). Removed SCALE1, replaced with SCALEDYN. +! (bmy, 2/24/03) +! (43) Added TSKIN, PARDF, PARDR, GWET to ND67 diagnostic. For GEOS-4/fvDAS, +! UWND, VWND, TMPU, SPHU are A-6 fields. Adjust the ND66 scale factors +! accordingly. Delete KZZ from ND66. Updated comments. (bmy, 6/23/03) +! (44) Bug fix: use LD68 instead of ND68 in DO-loop to avoid out-of-bounds +! error. (bec, bmy, 7/15/03) +! (45) Now print out NTRACE drydep fluxes for tagged Ox. Also tagged Ox +! now saves drydep in molec/cm2/s. Now print out Kr85 prod/loss in +! ND03. (bmy, 8/20/03) +! (46) Now use actual tracer number for ND37 diagnostic. (bmy, 1/21/04) +! (47) Now loop over the actual # of soluble tracers for ND17, ND18. +! (bmy, 3/19/04) +! (48) Now use the actual tracer # for ND17 and ND18 diagnostics. +! Rearrange ND44 code for clarity. (bmy, 3/23/04) +! (49) Added ND06 (dust aerosol) and ND07 (carbon aerosol) diagnostics. +! Now scale online dust optical depths by SCALECHEM in ND21 diagnostic. +! (rjp, tdf, bmy, 4/5/04) +! (50) Added ND08 (seasalt aerosol) diagnostic (rjp, bec, bmy, 4/20/04) +! (51) Now save out SO2 from ships (if LSHIPSO2=T) (bec, bmy, 5/20/04) +! (52) Added NVOC source diagnostics for ND07 (rjp, bmy, 7/13/04) +! (53) Now reference "logical_mod.f", "tracer_mod.f", and "diag_pl_mod.f". +! Bug fix in write to DMS_BIOG. (bmy, 7/20/04) +! (54) Comment out ND27 for GEOS-4. It isn't working 100% right. If you +! examine the flux at 200 hPa, you get the same info. (bmy, 10/15/04) +! (55) Added biofuel SO4 to the bpch file under ND13. Bug fix: replace ND68 +! with LD68 in call to BPCH2 (auvray, bmy, 11/17/04) +! (56) Now save ND03 mercury diagnostic arrays to bpch file. Also updated +! ND44 for tagged Hg tracers (eck, bmy, 12/14/04) +! (57) Now print out extra ND21 diagnostics for crystalline sulfur tracers. +! Also now save total oceanic mass of Hg0 and Hg2. Now call +! WRITE_DIAG03 from "diag03_mod.f" (bmy, 1/21/05) +! (58) Now call WRITE_DIAG41 from "diag41_mod.f" (bmy, 2/17/05) +! (59) Add P(SO4s) to row 8 of ND05 diagnostic. Also remove special tracer +! numbers for the ND67 diagnostic. Now do not save CLDMAS for ND67 +! for GEOS-4, since GEOS-4 convection uses different met fields. +! (bec, bmy, 5/3/05) +! (60) Bug fix in ND68 diagnostic: use LD68 instead of ND68 in call to BPCH2. +! Now modified for GEOS-5 and GCAP met fields. Remove references to +! CO-OH param simulation. Also remove references to TRCOFFSET since +! that is always zero now. Now call GET_HALFPOLAR from "bpch2_mod.f" +! to get the HALFPOLAR value for GEOS or GCAP grids. (swu, bmy, 6/24/05) +! (61) References ND04, WRITE_DIAG04 from "diag04_mod.f". Also now updated +! ND30 diagnostic for land/water/ice flags. Also remove reference +! to LWI array. (bmy, 8/18/05) +! (62) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (63) Added MBO as tracer #5 in ND46 diagnostic (tmf, bmy, 10/20/05) +! (64) Removed duplicate variable declarations. Now remove restriction on +! printing out cloud mass flux in GEOS-4 for the ND66 diagnostic. +! (bmy, 3/14/06) +! (65) References ND56, WRITE_DIAG56 from "diag56_mod.f" (ltm, bmy, 5/5/06) +! (66) Now remove TRCOFFSET; it's obsolete. References ND42, WRITE_DIAG42 +! from "diag42_mod.f" (dkh, bmy, 5/22/06) +! (67) Updated ND36 diagnostic for CH3I (bmy, 7/25/06) +! (68) Remove support for GEOS-1 and GEOS-STRAT met fields (bmy, 8/4/06) +! (69) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (70) Now write diag 54 (time in the troposphere) if asked for (phs, 9/22/06) +! (71) Now use new time counters for ND43 & ND45, Also now average between +! 0 and 24 UT for ND47. Bug fix in ND36. (phs, bmy, 3/5/07) +! (72) Bug fix in ND65: use 3-D counter array (phs, bmy, 3/6/07) +! (73) Bug fix in ND07: now save out IDTSOA4 tracer. Modifications for H2/HD +! diagnostics (ND10, ND27, ND44) (tmf, phs, bmy, 9/18/07) +! (74) Now save out true pressure at 3-D level edges for ND31. Change ND31 +! diagnostic category name to "PEDGE-$". Bug fix in ND28 diagnostic to +! allow you to print out individual biomass tracers w/o having to print +! all of them. (bmy, dkh, 1/24/08) +! (75) Bug fix: Now divide ALBEDO in ND67 by SCALE_I6 for GEOS-3 met, but +! by SCALE_A3 for all other met types (phs, bmy, 10/7/08) +! (76) Fix ND65, ND47, and ozone case in ND45. Now only ND45 depends +! on LD45 (phs, 11/17/08) +! (77) Bug fix: Select the right index of AD34 to write. Pick the right +! tracer field from AD22 if only a subset of tracers are requested +! to be printed out. (ccc, 12/15/08) +! (78) Added ND52 for gamma(HO2) (jaegle, 02/26/09) +! (79) Updated test on ship emissions flag for AD13 (phs, 3/3/09) +! (80) Add AD07_SOAGM for dicarbonyl SOA formation (tmf, 3/6/09) +! (81) Add output in AD22 for dicarbonyl photolysis J values (tmf, 3/6/09) +! (82) Add output in AD46 for biogenic C2H4 emissions (tmf, 3/6/09) +! (87) Add diagnostics 19, 58 and 60 for methane. (kjw, 8/18/09, adj32_023) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE BIOMASS_MOD, ONLY : BIOTRCE, NBIOMAX + USE BIOFUEL_MOD, ONLY : NBFTRACE, BFTRACE + USE DIAG_MOD, ONLY : AD01, AD02, AD05 + USE DIAG_MOD, ONLY : AD06, AD07, AD07_BC + USE DIAG_MOD, ONLY : AD07_SOAGM + USE DIAG_MOD, ONLY : AD07_OC, AD07_HC, AD08 + USE DIAG_MOD, ONLY : AD09, AD09_em, AD11 + USE DIAG_MOD, ONLY : AD12, AD13_DMS, AD13_SO2_ac + USE DIAG_MOD, ONLY : AD13_SO2_an, AD13_SO2_bb, AD13_SO2_bf + USE DIAG_MOD, ONLY : AD13_SO2_ev, AD13_SO2_nv, AD13_SO4_an + USE DIAG_MOD, ONLY : AD13_SO4_bf, AD13_SO2_sh, AD13_NH3_an + USE DIAG_MOD, ONLY : AD13_NH3_na, AD13_NH3_bb, AD13_NH3_bf + USE DIAG_MOD, ONLY : CONVFLUP, TURBFLUP, AD16 + USE DIAG_MOD, ONLY : CT16, AD17, CT17 + USE DIAG_MOD, ONLY : AD18, CT18, AD21 + USE DIAG_MOD, ONLY : AD21_cr, AD22, LTJV + USE DIAG_MOD, ONLY : CTJV, MASSFLEW, MASSFLNS + USE DIAG_MOD, ONLY : MASSFLUP, AD28, AD29 + USE DIAG_MOD, ONLY : AD30, AD31 + USE DIAG_MOD, ONLY : AD32_ac, AD32_an, AD32_bb + USE DIAG_MOD, ONLY : AD32_bf, AD32_fe, AD32_li + USE DIAG_MOD, ONLY : AD32_so, AD32_ub, AD33 + USE DIAG_MOD, ONLY : AD32_SHIP, AD32_SHIP_COUNT + USE DIAG_MOD, ONLY : AD34, AD35, AD36 + USE DIAG_MOD, ONLY : AD36_SHIP, AD36_SHIP_COUNT + USE DIAG_MOD, ONLY : AD37, AD38, AD39 + USE DIAG_MOD, ONLY : AD43, LTNO + USE DIAG_MOD, ONLY : CTNO, LTOH, CTOH + USE DIAG_MOD, ONLY : LTHO2, CTHO2, LTNO2 + USE DIAG_MOD, ONLY : CTNO2, LTNO3, CTNO3 + USE DIAG_MOD, ONLY : AD44, AD45, LTOTH + USE DIAG_MOD, ONLY : CTOTH, AD46, AD47 + USE DIAG_MOD, ONLY : AD52 + USE DIAG_MOD, ONLY : AD54, CTO3, CTO3_24h + USE DIAG_MOD, ONLY : AD19, AD58, AD60 + USE DIAG_MOD, ONLY : AD55, AD66, AD67 + USE DIAG_MOD, ONLY : AD68, AD69 + USE DIAG_MOD, ONLY : AD10, AD10em + USE DIAG03_MOD, ONLY : ND03, WRITE_DIAG03 + USE DIAG04_MOD, ONLY : ND04, WRITE_DIAG04 + USE DIAG41_MOD, ONLY : ND41, WRITE_DIAG41 + USE DIAG42_MOD, ONLY : ND42, WRITE_DIAG42 + USE DIAG56_MOD, ONLY : ND56, WRITE_DIAG56 +! diag59 added, (lz,10/11/10) + USE DIAG59_MOD, ONLY : ND59, WRITE_DIAG59 + USE DIAG_PL_MOD, ONLY : AD65 + USE DRYDEP_MOD, ONLY : NUMDEP, NTRAIND + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_AREA_M2, GET_XOFFSET, GET_YOFFSET + USE LOGICAL_MOD, ONLY : LCARB, LCRYST, LDUST + USE LOGICAL_MOD, ONLY : LSHIPSO2, LSOA, LSSALT + USE LOGICAL_MOD, ONLY : LEDGARSHIP, LARCSHIP, LEMEPSHIP + USE LOGICAL_MOD, ONLY : LICOADSSHIP, LRCPSHIP + USE TIME_MOD, ONLY : GET_DIAGb, GET_DIAGe, GET_CT_A3 + USE TIME_MOD, ONLY : GET_CT_A6, GET_CT_CHEM, GET_CT_CONV + USE TIME_MOD, ONLY : GET_CT_DYN, GET_CT_EMIS, GET_CT_I6 + USE TIME_MOD, ONLY : GET_CT_A1, GET_CT_I3 !! (geosfp, lzh,11/01/2014) + USE TRACER_MOD, ONLY : N_TRACERS, STT, TRACER_MW_G + USE TRACER_MOD, ONLY : TRACER_NAME + USE TRACER_MOD, ONLY : ITS_AN_AEROSOL_SIM + USE TRACER_MOD, ONLY : ITS_A_CH3I_SIM + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : ITS_A_H2HD_SIM + USE TRACER_MOD, ONLY : ITS_A_MERCURY_SIM + USE TRACER_MOD, ONLY : ITS_A_RnPbBe_SIM + USE TRACER_MOD, ONLY : ITS_A_TAGOX_SIM + USE TRACERID_MOD, ONLY : IDTPB, IDTDST1, IDTDST2 + USE TRACERID_MOD, ONLY : IDTDST3, IDTDST4, IDTBCPI + USE TRACERID_MOD, ONLY : IDTOCPI, IDTALPH, IDTLIMO + USE TRACERID_MOD, ONLY : IDTSOA1, IDTSOA2, IDTSOA3 + USE TRACERID_MOD, ONLY : IDTSALA, IDTSALC, IDTDMS + USE TRACERID_MOD, ONLY : IDTSO2, IDTSO4, IDTNH3 + USE TRACERID_MOD, ONLY : IDTOX, IDTNOX, IDTHNO3 + USE TRACERID_MOD, ONLY : IDTISOP, IDTACET, IDTPRPE + USE TRACERID_MOD, ONLY : IDTH2, IDTHD + USE TRACERID_MOD, ONLY : NEMANTHRO , IDTSOA4 + USE TRACERID_MOD, ONLY : IDTSOAG, IDTSOAM + USE TRACERID_MOD, ONLY : IDTMONX, IDTMBO, IDTC2H4 + USE WETSCAV_MOD, ONLY : GET_WETDEP_NSOL + USE WETSCAV_MOD, ONLY : GET_WETDEP_IDWETD + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN" ! IFLX, LPAUSE +# include "CMN_DIAG" ! Diagnostic switches & arrays +# include "CMN_O3" ! FMOL, XNUMOL +# include "comode.h" ! IDEMS + + ! Local variables + INTEGER :: I, IREF, J, JREF, L, M, MM, MMB, LMAX + INTEGER :: N, NN, NMAX, NTEST + INTEGER :: IE, IN, IS, IW, ITEMP(3) + REAL*8 :: SCALE_TMP(IIPAR,JJPAR) + REAL*8 :: SCALE_I6, SCALE_A6, SCALE_A3, SCALED + + !! (geosfp, lzh, 11/01/2014) + REAL*8 :: SCALE_I3, SCALE_A1 + REAL*8 :: SCALE_ND66, SCALE_ND67 + + REAL*8 :: SCALEDYN, SCALECONV, SCALESRCE, SCALECHEM + REAL*8 :: SCALEX, SECONDS, PMASS, PRESSX + REAL*8 :: FDTT, AREA_M2, DIAGb, DIAGe + + ! For binary punch file, version 2.0 + CHARACTER (LEN=40) :: CATEGORY + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR+1) + REAL*4 :: LONRES, LATRES + INTEGER :: IFIRST, JFIRST, LFIRST + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180 = 1 + CHARACTER (LEN=20) :: MODELNAME + CHARACTER (LEN=40) :: UNIT + CHARACTER (LEN=40) :: RESERVED = '' +! +!****************************************************************************** +! DIAG3 begins here! +! +! Define scale factors for division. +! Add a small number (e.g. 1d-32) to prevent division by zero errors. +!****************************************************************************** +! + ! Now use counter variables from "time_mod.f" (bmy, 3/27/03) + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + SECONDS = ( DIAGe - DIAGb ) * 3600d0 + SCALED = 1d0 + SCALEDYN = DBLE( GET_CT_DYN() ) + 1d-32 + SCALECONV = DBLE( GET_CT_CONV() ) + 1d-32 + SCALESRCE = DBLE( GET_CT_EMIS() ) + 1d-32 + SCALECHEM = DBLE( GET_CT_CHEM() ) + 1d-32 + SCALE_A3 = DBLE( GET_CT_A3() ) + 1d-32 + SCALE_A6 = DBLE( GET_CT_A6() ) + 1d-32 + SCALE_I6 = DBLE( GET_CT_I6() ) + 1d-32 + !! (lzh, 11/01/2014) geosfp + SCALE_A1 = DBLE( GET_CT_A1() ) + 1d-32 + SCALE_I3 = DBLE( GET_CT_I3() ) + 1d-32 +! +!****************************************************************************** +! Setup for binary punch file: +! +! IFIRST, JFIRST, LFIRST = I, J, L indices of the starting grid box +! LONRES = DISIZE, cast to REAL*4 +! LATRES = DJSIZE, cast to REAL*4 +!****************************************************************************** +! + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LFIRST = 1 + LONRES = DISIZE + LATRES = DJSIZE + + ! Get the proper model name and HALFPOLAR setting for the bpch file + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() +! +!****************************************************************************** +! ND01: Rn, Pb, Be emissions (Category: "RN--SRCE") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) Rn222 : Emissions of 222Rn : kg/s : SCALESRCE +! (2) Pb210 : Emissions of 210Pb : kg/s : SCALECHEM +! (3) Be7 : Emissions of 7Be : kg/s : SCALESRCE +! +! and Rn, Pb, Be lost to radioactive decay (Category: "RN-DECAY") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) Rn222 : Loss of 222Rn : kg/s : SCALECHEM +! (2) Pb210 : Loss of 210Pb : kg/s : SCALECHEM +! (3) Be7 : Loss of 7Be : kg/s : SCALECHEM +!****************************************************************************** +! + IF ( ND01 > 0 ) THEN + CATEGORY = 'RN--SRCE' + UNIT = 'kg/s' + + DO M = 1, TMAX(1) + N = TINDEX(1,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! Pb "emission" comes from chemical decay of Rn, which happens + ! in the chemistry routine, so use SCALECHEM (bmy, 1/27/03) + IF ( N == IDTPB ) THEN + SCALEX = SCALECHEM + ELSE + SCALEX = SCALESRCE + ENDIF + + ! Divide by # of emission timesteps + DO L = 1, LD01 + ARRAY(:,:,L) = AD01(:,:,L,N) / SCALEX + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD01, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD01) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND02: Rn, Pb, Be lost to radioactive decay (Category: "RN-DECAY") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) Rn222 : Loss of 222Rn : kg/s : SCALECHEM +! (2) Pb210 : Loss of 210Pb : kg/s : SCALECHEM +! (3) Be7 : Loss of 7Be : kg/s : SCALECHEM +!****************************************************************************** +! + IF ( ND02 > 0 ) THEN + CATEGORY = 'RN-DECAY' + UNIT = 'kg/s' + + DO M = 1, TMAX(2) + N = TINDEX(2,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! Divide by # of chemistry timesteps + DO L = 1, LD02 + ARRAY(:,:,L) = AD02(:,:,L,N) / SCALECHEM + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD02, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD02) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND03: Diagnostics from Hg0/Hg2/HgP offline simulation (eck, bmy, 1/20/05) +!****************************************************************************** +! + IF ( ND03 > 0 ) CALL WRITE_DIAG03 +! +!****************************************************************************** +! ND04: Diagnostics from CO2 simulation (pns, bmy, 7/26/05) +!****************************************************************************** +! + IF ( ND04 > 0 ) CALL WRITE_DIAG04 +! +!****************************************************************************** +! ND05: Production/Loss for coupled fullchem/aerosol runs (NSRCX==3) or +! offline sulfate chemistry runs (NSRCX==10). +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1 ) SO2dms : P(SO2) from DMS + OH : kg S : SCALEX +! (2 ) SO2no3 : P(SO2) from DMS + NO3 : kg S : SCALEX +! (3 ) SO2 : Total P(SO2) : kg S : SCALEX +! (4 ) MSAdms : P(MSA) from DMS : kg S : SCALEX +! (5 ) SO4gas : P(SO4) gas phase : kg S : SCALEX +! (6 ) SO4aq : P(SO4) aqueous phase : kg S : SCALEX +! (7 ) PSO4 : Total P(SO4) : kg S : SCALEX +! (8 ) PSO4s : Total P(SO4 from seasalt) : kg S : SCALEX +! (9 ) LOH : L(OH) by DMS : kg OH : SCALEX +! (10) LNO3 : L(NO3) by DMS : kg NO3 : SCALEX +!****************************************************************************** +! + IF ( ND05 > 0 ) THEN + CATEGORY = 'PL-SUL=$' + + DO M = 1, TMAX(5) + N = TINDEX(5,M) + + ! Tracers 9, 10 are OH, NO3 + ! and are in [kg] instead of [kg S] + IF ( N < 9 ) THEN + UNIT = 'kg S' + ELSE + UNIT = 'kg' + ENDIF + + NN = N + SCALEX = 1.d0 + + DO L = 1, LD05 + ARRAY(:,:,L) = AD05(:,:,L,N) / SCALEX + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD05, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD05) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND06: Dust aerosol emissions +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) DUST : Soil dust (4 different classes) : kg : 1 +!****************************************************************************** +! + IF ( ND06 > 0 .and. LDUST ) THEN + + ! Category & unit string + UNIT = 'kg' + CATEGORY = 'DUSTSRCE' + + ! Loop over # of dust bins + DO N = 1, NDSTBIN + + ! At present we have 4 dust bins + IF ( N == 1 ) NN = IDTDST1 + IF ( N == 2 ) NN = IDTDST2 + IF ( N == 3 ) NN = IDTDST3 + IF ( N == 4 ) NN = IDTDST4 + + ! Save dust into ARRAY + ARRAY(:,:,1) = AD06(:,:,N) + + ! Write to BPCH file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND07: Emissions of BC and OC aerosols +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) Carbon : Carbonaceous aerosols : kg : 1 +!****************************************************************************** +! + IF ( ND07 > 0 .and. LCARB ) THEN + + ! Unit + UNIT = 'kg' + + !------------------- + ! BC ANTHRO source + !------------------- + CATEGORY = 'BC-ANTH' + N = IDTBCPI + ARRAY(:,:,1) = AD07(:,:,1) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------- + ! BC BIOMASS source + !------------------- + CATEGORY = 'BC-BIOB' + N = IDTBCPI + ARRAY(:,:,1) = AD07(:,:,2) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------- + ! BC BIOFUEL source + !------------------- + CATEGORY = 'BC-BIOF' + N = IDTBCPI + ARRAY(:,:,1) = AD07(:,:,3) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! H-philic BC from H-phobic BC + !------------------------------ + CATEGORY = 'PL-BC=$' + N = IDTBCPI + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_BC(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + !------------------------------ + ! OC ANTHRO source + !------------------------------ + CATEGORY = 'OC-ANTH' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,4) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! OC BIOMASS source + !------------------------------ + CATEGORY = 'OC-BIOB' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,5) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! OC BIOFUEL source + !------------------------------ + CATEGORY = 'OC-BIOF' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,6) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! OC BIOGENIC source + !------------------------------ + CATEGORY = 'OC-BIOG' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,7) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! H-philic OC from H-phobic OC + !------------------------------ + CATEGORY = 'PL-OC=$' + N = IDTOCPI + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_OC(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + ! Only save extra SOA diagnostics if LSOA=T + IF ( LSOA ) THEN + + !------------------------------ + ! NVOC SOURCE diagnostics + !------------------------------ + DO N = 8, 12 + + SELECT CASE ( N ) + + ! ALPH + CASE ( 8 ) + CATEGORY = 'OC-ALPH' + NN = IDTALPH + + ! LIMO + CASE ( 9 ) + CATEGORY = 'OC-LIMO' + NN = IDTLIMO + + ! TERP + CASE ( 10 ) + CATEGORY = 'OC-TERP' + NN = IDTLIMO + 1 + + ! ALCO + CASE ( 11 ) + CATEGORY = 'OC-ALCO' + NN = IDTLIMO + 2 + + ! SESQ + CASE ( 12 ) + CATEGORY = 'OC-SESQ' + NN = IDTLIMO + 3 + + END SELECT + + ARRAY(:,:,1) = AD07(:,:,N) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + + !----------------------------------------------- + ! SOA Production from NVOC oxidation [kg] + ! 1:ALPH+LIMO+TERP, 2:ALCO, 3:SESQ, 4:ISOP + !----------------------------------------------- + CATEGORY = 'PL-OC=$' + + DO N = 1, 4 + + IF ( N == 1 ) NN = IDTSOA1 + IF ( N == 2 ) NN = IDTSOA2 + IF ( N == 3 ) NN = IDTSOA3 + IF ( N == 4 ) NN = IDTSOA4 ! (tmf, bmy, 3/20/07) + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_HC(:,:,L,N) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + ENDDO + + !----------------------------------------------- + ! SOA Production from GLYX and MGLY [kg] + ! 1: SOAG <- GLYX; 2: SOAM <- MGLY IN AEROSOL + ! 3: SOAG <- GLYX; 4: SOAM <- MGLY INCLOUD + ! (tmf, 1/7/09) + ! Test if SOAG and SOAM tracers are valid before + ! saving them. (ccc, 1/7/09) + !----------------------------------------------- + IF ( IDTSOAG /= 0 .AND. IDTSOAM /= 0 ) THEN + CATEGORY = 'SOAGM=$' + + DO N = 1, 4 + + IF ( N == 1 ) NN = 91 + IF ( N == 2 ) NN = 92 + IF ( N == 3 ) NN = 93 + IF ( N == 4 ) NN = 94 + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_SOAGM(:,:,L,N) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + ENDDO + ENDIF + ENDIF + ENDIF +! +!****************************************************************************** +! ND08: Sea salt aerosol emissions +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) SALA : Accumulation mode seasalt : kg : 1 +! (2) SALC : Coarse mode seasalt : kg : 1 +!****************************************************************************** +! + IF ( ND08 > 0 .and. LSSALT ) THEN + + ! Category & unit string + UNIT = 'kg' + CATEGORY = 'SALTSRCE' + + ! Loop over seasalt tracers + DO N = 1, 2 + + ! At present we have 2 seasalts + IF ( N == 1 ) NN = IDTSALA + IF ( N == 2 ) NN = IDTSALC + + ! Save seasalts into ARRAY + ARRAY(:,:,1) = AD08(:,:,N) + + ! Write to BPCH file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND09: HCN/CH3CN sources/sinks (Categories: "HCN-PL-$", "HCN-SRCE") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1:N) sink : Loss of tagged tracer to OH : kg +! (N+1) HCNbb : HCN from biomass burning : molec/cm2/s : SCALESRCE +! (N+2) CH3CNbb : CH3CN from biomass burning : molec/cm2/s : SCALESRCE +! (N+3) HCNdf : HCN from domestic fossil fuel : molec/cm2/s : SCALESRCE +! (N+4) CH3CNdf : CH3CN from domestic fossil fuel : molec/cm2/s : SCALESRCE +! (N+5) HCNoc : HCN loss to ocean uptake : molec/cm2/s : SCALECHEM +! (N+6) CH3CNoc : CH3CN loss to ocean uptake : molec/cm2/s : SCALECHEM +!****************************************************************************** +! + IF ( ND09 > 0 ) THEN + + ! Binary punch file + DO M = 1, TMAX(9) + N = TINDEX(9,M) + IF ( N > N_TRACERS+6 ) CYCLE + + ! Test tracer number + IF ( N <= N_TRACERS ) THEN + + !--------------------------- + ! HCN/CH3CN sinks + !--------------------------- + CATEGORY = 'HCN-PL-$' + UNIT = 'kg' + NN = N + + DO L = 1, LD09 + ARRAY(:,:,L) = AD09(:,:,L,N) + ENDDO + + ! Save to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD09, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD09) ) + + ELSE + + !--------------------------- + ! HCN/CH3CN sources + !--------------------------- + CATEGORY = 'HCN-SRCE' + UNIT = 'molec/cm2/s' + NN = N - N_TRACERS + + ! Pick proper scale + IF ( NN <= 4 ) THEN + SCALEX = SCALESRCE + ELSE + SCALEX = SCALECHEM + ENDIF + + ! Scale data + ARRAY(:,:,1) = AD09_em(:,:,NN) / SCALEX + + ! Write to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND10: H2/HD source diagnostics, prod and loss (phs, 9/18/07) +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) H2oh : H2 Loss by OH : mol/cm3/s : SCALECHEM +! (2 ) H2iso : H2 Prod from isoprene : mol/cm3/s : SCALECHEM +! (3 ) H2ch4 : H2 Prod from CH4 : mol/cm3/s : SCALECHEM +! (4 ) H2ch3oh: H2 Prod from CH3OH : mol/cm3/s : SCALECHEM +! (5 ) H2mono : H2 Prod from monoprene : mol/cm3/s : SCALECHEM +! (6 ) H2acet : H2 Prod from acetone : mol/cm3/s : SCALECHEM +! (7 ) H2o1d : H2 Loss by strat O1D : mol/cm3/s : SCALECHEM +! +! (8 ) HDoh : H2 Loss by OH : mol/cm3/s : SCALECHEM +! (9 ) HDiso : H2 Prod from isoprene : mol/cm3/s : SCALECHEM +! (10) HDch4 : H2 Prod from CH4 : mol/cm3/s : SCALECHEM +! (11) HDch3oh: H2 Prod from CH3OH : mol/cm3/s : SCALECHEM +! (12) HDmono : H2 Prod from monoprene : mol/cm3/s : SCALECHEM +! (13) HDacet : H2 Prod from acetone : mol/cm3/s : SCALECHEM +! (14) HDo1d : H2 Loss by strat O1D : mol/cm3/s : SCALECHEM +! +! (15) ALPHA : OH k rates kHD/kH2 ratio: unitless : SCALECHEM +! +! (16) H2anth : H2 from Anthro Sources : mol/cm2/s : SCALESRCE +! (17) H2bb : H2 from Biomass Burning : mol/cm2/s : SCALESRCE +! (18) H2bf : H2 from Biofuel Burning : mol/cm2/s : SCALESRCE +! (19) H2ocean: H2 from Ocean : mol/cm2/s : SCALESRCE +! (19) HDocean: HD from Ocean : mol/cm2/s : SCALESRCE +! +! NOTES: +! (1 ) Non zero only if ND10>0 and it is a H2/HD offline simulation +! (2 ) +!****************************************************************************** +! + IF ( ND10 > 0 ) THEN + DO M = 1, TMAX(10) + N = TINDEX(10,M) + IF ( N > PD10 ) CYCLE + + ! Test tracer number (NEMISS=5, see "ndxx_setup.f" ) + IF ( N <= ( PD10 - 5 ) ) THEN + + !--------------------------- + ! H2/HD Prod-Loss + !--------------------------- + CATEGORY = 'PL-H2HD-' + UNIT = 'molec/cm3/s' + NN = N + + DO L = 1, LD10 + ARRAY(:,:,L) = AD10(:,:,L,N) / SCALECHEM + ENDDO + + ! Save to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD10, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD10) ) + + ELSE + + !--------------------------- + ! H2/HD sources + !--------------------------- + CATEGORY = 'H2HD-SRC' + UNIT = 'molec/cm2/s' + NN = N - 15 + + ! Scale data + ARRAY(:,:,1) = AD10em(:,:,NN) / SCALESRCE + + ! Write to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND11: Acetone source & sink diagnostic (Category: "ACETSRCE") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) ACETmo : Acetone source from MONOTERPENES : at C/cm2/s : SCALESRCE +! (2) ACETmb : Acetone source from METHYL BUTENOL : at C/cm2/s : SCALESRCE +! (3) ACETbg : Acetone source from DIRECT EMISSION: at C/cm2/s : SCALESRCE +! (4) ACETdl : Acetone source from DRY LEAF MATTER: at C/cm2/s : SCALESRCE +! (5) ACETgr : Acetone source from GRASSLANDS : at C/cm2/s : SCALESRCE +! (6) ACETop : Acetone source from OCEANS : at C/cm2/s : SCALESRCE +! (7) ACETol : Acetone sink from OCEANS : at C/cm2/s : SCALECHEM +!****************************************************************************** +! + IF ( ND11 > 0 ) THEN + CATEGORY = 'ACETSRCE' + UNIT = 'atoms C/cm2/s' + + DO M = 1, TMAX(11) + N = TINDEX(11,M) + IF ( N > PD11 ) CYCLE + NN = N + + ! Acetone ocean sink is on the chemistry timestep + ! but acetone sources are all on the emission timestep + IF ( N == 7 ) THEN + SCALEX = SCALECHEM + ELSE + SCALEX = SCALESRCE + ENDIF + + ARRAY(:,:,1) = AD11(:,:,N) / SCALEX + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND12: distribution of suface emissions in the boundry layer: [fraction] +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) EMDIS-BL : Fraction of BL occupied by level L : unitless : SCALECHEM +!****************************************************************************** +! + IF ( ND12 > 0 ) THEN + UNIT = 'unitless' + CATEGORY = 'EMDIS-BL' + + DO L = 1, LD12 + ARRAY(:,:,L) = AD12(:,:,L) / SCALECHEM + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLTROP, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD12) ) + ENDIF +! +!****************************************************************************** +! ND13: Sulfur emissions (for DMS/SO2/SO4/MSA/NH3/NH4/NIT chemistry) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) DMS-BIOG : Biogenic DMS emission : kg S : 1 +! (2 ) SO2-AC-$ : Aircraft SO2 emission : kg S : 1 +! (3 ) SO2-AN-$ : Anthropogenic SO2 emission : kg S : 1 +! (4 ) SO2-BIOB : Biomass SO2 emission : kg S : 1 +! (5 ) SO2-BIOF : Biofuel SO2 emission : kg S : 1 +! (6 ) SO2-NV-$ : Non-eruptive volcano SO2 em. : kg S : 1 +! (7 ) SO2-EV-$ : Eruptive volcano SO2 emissions : kg S : 1 +! (8 ) SO4-AN-$ : Anthropogenic SO4 emission : kg S : 1 +! (9 ) NH3-ANTH : Anthropogenic NH3 emission : kg NH3 : 1 +! (10) NH3-NATU : Natural source NH3 emission : kg NH3 : 1 +! (11) NH3-BIOB : Biomass burning NH3 emission : kg NH3 : 1 +! (12) NH3-BIOF : Biofuel burning NH3 emission : kg NH3 : 1 +!****************************************************************************** +! + IF ( ND13 > 0 .and. + & ( ITS_A_FULLCHEM_SIM() .or. ITS_AN_AEROSOL_SIM() ) ) THEN + UNIT = 'kg S' + + !============================================================== + ! Biogenic DMS + !============================================================== + CATEGORY = 'DMS-BIOG' + ARRAY(:,:,1) = AD13_DMS(:,:) + N = IDTDMS + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Aircraft SO2 + !============================================================== + CATEGORY = 'SO2-AC-$' + N = IDTSO2 + + DO L = 1, LD13 + ARRAY(:,:,L) = AD13_SO2_ac(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD13, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD13) ) + + !============================================================== + ! Anthropogenic SO2 + !============================================================== + CATEGORY = 'SO2-AN-$' + N = IDTSO2 + + DO L = 1, NOXEXTENT + ARRAY(:,:,L) = AD13_SO2_an(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 2, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:2) ) + + + + + !============================================================== + ! Biomass SO2 + !============================================================== + CATEGORY = 'SO2-BIOB' + ARRAY(:,:,1) = AD13_SO2_bb(:,:) + N = IDTSO2 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + + !============================================================== + ! Biofuel SO2 + !============================================================== + CATEGORY = 'SO2-BIOF' + ARRAY(:,:,1) = AD13_SO2_bf(:,:) + N = IDTSO2 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Eruptive volcano SO2 + !============================================================== + CATEGORY = 'SO2-EV-$' + N = IDTSO2 + + DO L = 1, LD13 + ARRAY(:,:,L) = AD13_SO2_ev(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD13, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD13) ) + + !============================================================== + ! Non-eruptive volcano SO2 + !============================================================== + CATEGORY = 'SO2-NV-$' + N = IDTSO2 + + DO L = 1, LD13 + ARRAY(:,:,L) = AD13_SO2_nv(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD13, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD13) ) + + + !============================================================== + ! Ship SO2 bec (5/17/04) + ! New test on logical flag (phs, 3/2/09) + !============================================================== + ! Add ICOADSSHIP (cklee, 6/30/09) + ! Add RCP + IF ( LSHIPSO2 .OR. LEDGARSHIP .OR. LARCSHIP .OR. + $ LEMEPSHIP .OR. LICOADSSHIP .OR. LRCPSHIP ) THEN + + CATEGORY = 'SO2-SHIP' + ARRAY(:,:,1) = AD13_SO2_sh(:,:) + N = IDTSO2 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF + + !============================================================== + ! Anthropogenic SO4 + !============================================================== + CATEGORY = 'SO4-AN-$' + N = IDTSO4 + + ! Fix loop to make compatible with NEI2008 + ! DO L = 1, NOXEXTENT + DO L = 1, 2 + ARRAY(:,:,L) = AD13_SO4_an(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 2, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:2) ) + + !============================================================== + ! Biofuel SO4 + !============================================================== + CATEGORY = 'SO4-BIOF' + ARRAY(:,:,1) = AD13_SO4_bf(:,:) + N = IDTSO4 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + + !============================================================== + ! Anthropogenic NH3 + !============================================================== + UNIT = 'kg' + CATEGORY = 'NH3-ANTH' + ARRAY(:,:,1) = AD13_NH3_an(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Natural source NH3 + !============================================================== + CATEGORY = 'NH3-NATU' + ARRAY(:,:,1) = AD13_NH3_na(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Biomass NH3 + !============================================================== + CATEGORY = 'NH3-BIOB' + ARRAY(:,:,1) = AD13_NH3_bb(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Biofuel NH3 + !============================================================== + CATEGORY = 'NH3-BIOF' + ARRAY(:,:,1) = AD13_NH3_bf(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF +! +!****************************************************************************** +! ND14: Upward mass flux from wet convection (NFCLDMX) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) CONVFLUP : Upward mass flux from wet conv : kg/s : SCALECONV +! +! NOTES: +! (1) Bug fix -- only write LD14 levels to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND14 > 0 ) THEN + CATEGORY = 'CV-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(14) + N = TINDEX(14,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1:LD14) = CONVFLUP(:,:,1:LD14,N) / SCALECONV + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD14, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD14) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND15: Upward mass flux from boundary layer mixing (TURBDAY) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) TURBFLUX : Upward mass flux from BL mixing : kg/s : SCALECONV +! +! NOTES: +! (1) Bug fix -- only write LD15 levels to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND15 > 0 ) THEN + CATEGORY = 'TURBMC-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(15) + N = TINDEX(15,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1:LD15) = TURBFLUP(:,:,1:LD15,N) / SCALECONV + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD15, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD15) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND16: Fraction of grid box experiencing LS or convective precipitation +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WD-FLS-$ : LS precip fraction : unitless : CT16(:,:,:,1) +! (2) WD-FCV-$ : Convective precip fraction : unitless : CT16(:,:,:,2) +!****************************************************************************** +! + IF ( ND16 > 0 ) THEN + + ! Large-scale area of precipitation + CATEGORY = 'WD-FRC-$' + UNIT = 'unitless' + + DO M = 1, TMAX(16) + N = TINDEX(16,M) + IF ( N > PD16 ) CYCLE + NN = N + + DO L = 1, LD16 + SCALE_TMP(:,:) = FLOAT( CT16(:,:,L,N) ) + 1d-20 + ARRAY(:,:,L) = AD16(:,:,L,N) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD16, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD16) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND17: Fraction of tracer lost rainout in LS and convective precip +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WD-LSR-$ : Rainout fraction/LS Precip : unitless : CT17(:,:,:,1) +! (2) WD-CVR-$ : Rainout fraction/conv precip : unitless : CT17(:,:,:,2) +! +! NOTES: +! (1) Now loop over all soluble tracers (bmy, 3/19/04) +! (2) Now use actual tracer number (bmy, 3/23/04) +!****************************************************************************** +! + IF ( ND17 > 0 ) THEN + UNIT = 'unitless' + + ! Get max # of soluble tracers for this simulation + NMAX = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, NMAX + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(17) ) + MMB = TINDEX(17,MM) + MM = MM + 1 + ENDDO + + IF ( MMB /= NN ) CYCLE + + ! Large-scale rainout/washout fractions + CATEGORY = 'WD-LSR-$' + + DO L = 1, LD17 + SCALE_TMP(:,:) = FLOAT( CT17(:,:,L,1) ) + 1d-20 + ARRAY(:,:,L) = AD17(:,:,L,N,1) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD17, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD17) ) + + + ! Convective rainout/washout fractions + CATEGORY = 'WD-CVR-$' + + DO L = 1, LD17 + SCALE_TMP(:,:) = FLOAT( CT17(:,:,L,2) ) + 1d-20 + ARRAY(:,:,L) = AD17(:,:,L,N,2) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD17, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD17) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND18: Fraction of tracer lost to washout in LS or convective precip +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WD-LSW-$ : Washout fraction/LS precip : unitless : CT18(:,:,:,1) +! (2) WD-CVW-$ : Washout fraction/conv precip : unitless : CT18(:,:,:,2) +! +! NOTES: +! (1) Now loop over all soluble tracers (bmy, 3/19/04) +! (2) Now use actual tracer number (bmy, 3/23/04) +!****************************************************************************** +! + IF ( ND18 > 0 ) THEN + UNIT = 'unitless' + + ! Get max # of soluble tracers for this simulation + NMAX = GET_WETDEP_NSOL() + + DO N = 1, NMAX + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(18) ) + MMB = TINDEX(18,MM) + MM = MM + 1 + ENDDO + + IF ( MMB /= NN ) CYCLE + + ! Large-scale rainout/washout fractions + CATEGORY = 'WD-LSW-$' + + DO L = 1, LD18 + SCALE_TMP(:,:) = FLOAT( CT18(:,:,L,1) ) + 1d-20 + ARRAY(:,:,L) = AD18(:,:,L,N,1) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD18, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD18) ) + + + ! Convective washout fractions + CATEGORY = 'WD-CVW-$' + + DO L = 1, LD18 + SCALE_TMP(:,:) = FLOAT( CT18(:,:,L,2) ) + 1d-20 + ARRAY(:,:,L) = AD18(:,:,L,N,2) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD18, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD18) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND19: CH4 loss +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) CH4-LOSS : CH4 removing by OH : kg CH4 : 1 +!****************************************************************************** +! + IF ( ND19 > 0 ) THEN + + UNIT = 'kg' + + !============================================================== + ! CH4 Loss + !============================================================== + CATEGORY = 'CH4-LOSS' + N = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLPAR, IFIRST, + & JFIRST, LFIRST, AD19(:,:,:) ) + + ENDIF +! +!****************************************************************************** +! ND21: Optical depth diagnostics +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) OPTD Cloud Optical Depth : unitless : SCALECHEM +! (2 ) CLMO Max Overlap Cloud Fraction (GEOS1,S): unitless : SCALECHEM +! or CLDF 3-D Total Cloud fraction (GEOS3,4): unitless : SCALECHEM +! (3 ) CLRO Random Overlap Cloud Fraction : unitless : SCALECHEM +! (4 ) OPD Mineral Dust Optical Depth (400 nm) : unitless : none +! (5 ) SD Mineral Dust Surface Area : cm2/cm3 : none +! (6 ) OPSO4 Sulfate Optical Depth (400 nm) : unitless : SCALECHEM +! (7 ) HGSO4 Hygroscopic growth of SO4 : unitless : SCALECHEM +! (8 ) SSO4 Sulfate Surface Area : cm2/cm3 : SCALECHEM +! (9 ) OPBC Black Carbon Optical Depth (400 nm) : unitless : SCALECHEM +! (10) HGBC Hygroscopic growth of BC : unitless : SCALECHEM +! (11) SBC Black Carbon Surface Area : cm2/cm3 : SCALECHEM +! (12) OPOC Organic C Optical Depth (400 nm) : unitless : SCALECHEM +! (13) HGOC Hygroscopic growth of OC : unitless : SCALECHEM +! (14) SOC Organic Carbon Surface Area : cm2/cm3 : SCALECHEM +! (15) OPSSa Sea Salt (accum) Opt Depth (400 nm) : unitless : SCALECHEM +! (16) HGSSa Hygroscopic growth of SSa : unitless : SCALECHEM +! (17) SSSa Sea Salt (accum) Surface Area : cm2/cm3 : SCALECHEM +! (18) OPSSc Sea Salt (coarse) Opt Depth(400 nm) : unitless : SCALECHEM +! (19) HGSSc Hygroscopic growth of SSc : unitless : SCALECHEM +! (20) SSSc Sea Salt (coarse) Surface Area : cm2/cm3 : SCALECHEM +! +! NOTES: +! (1 ) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2 ) Don't divide monthly mean AOD by SCALECHEM (rvm, bmy, 12/8/00) +! (3 ) Use SCALE_A6 for GEOS-2, GEOS-3 fields, since optical depths are read +! in from disk every 6 hours. Use SCALECHEM for GEOS-1, GEOS-STRAT +! fields, since optical depths are computed every chemistry timestep. +! Use SCALEDYN for CO-OH parameterization simulation. (bmy, 4/23/01) +! (4 ) Now GEOS-2, GEOS-3 use SCALECHEM for ND21 (bmy, 8/13/01) +! (5 ) Updated tracers for new aerosols from Mian Chin (rvm, bmy, 3/1/02) +! (6 ) Now scale online dust fields by SCALECHEM (bmy, 4/9/04) +! (7 ) Also save out extra diagnostics for cryst sulfur tracers (bmy, 1/5/05) +!****************************************************************************** +! + IF ( ND21 > 0 ) THEN + CATEGORY = 'OD-MAP-$' + + ! ND21 is updated every chem timestep + SCALEX = SCALECHEM + + DO M = 1, TMAX(21) + N = TINDEX(21,M) + IF ( N > PD21 ) CYCLE + NN = N + + ! Select proper unit string (cf list above) + SELECT CASE( N ) + CASE ( 5, 8, 11, 14, 17, 20 ) + UNIT = 'cm2/cm3' + CASE DEFAULT + UNIT = 'unitless' + END SELECT + + IF ( N > 3 .AND. N < 6 ) THEN + + ! Online or offline dust fields? + IF ( LDUST ) THEN + + ! If LDUST=T, then we are using online dust fields, + ! so we must scale by the chemistry timestep. (4/9/04) + ARRAY(:,:,1:LD21) = AD21(:,:,1:LD21,N) / SCALEX + + ELSE + + ! If LDUST=F, then we are using offline monthly-mean + ! dust fields. These don't have to be scaled by + ! the chemistry timestep. (bmy, 4/9/04) + ARRAY(:,:,1:LD21) = AD21(:,:,1:LD21,N) + + ENDIF + + ELSE + + ! For all other types of optical depths, we need + ! to scale by the chemistry timestep (bmy, 4/9/04) + ARRAY(:,:,1:LD21) = AD21(:,:,1:LD21,N) / SCALEX + + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD21, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD21) ) + ENDDO + + !============================================================== + ! If we are using the crystalline sulfate tracers (LCRYST=T), + ! then also save out the extra ND21 diagnostics: + ! + ! #21: Opt depth for HYSTERESIS CASE [unitless] + ! #22: Opt depth for SOLID CASE [unitless] + ! #23: Opt depth for LIQUID CASE [unitless] + ! #24: Opt depth HYSTERESIS - Opt depth SOLID [unitless] + ! #25: Opt depth HYSTERESIS - Opt depth LIQUID [unitless] + ! #26: Radiative forcing [W/m2 ] + !============================================================== + IF ( LCRYST ) THEN + + ! Category + CATEGORY = 'OD-MAP-$' + + ! Loop over extra + DO N = 1, 6 + + ! Define unit string + IF ( N == 6 ) THEN + UNIT = 'W/m2' + ELSE + UNIT = 'unitless' + ENDIF + + ! Scale by chemistry timestep + ARRAY(:,:,1) = AD21_cr(:,:,N) / SCALECHEM + + ! Save to BPCH file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N+PD21, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF + ENDIF +! +!****************************************************************************** +! ND22: J-value diagnostics +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) JNO2 : NO2 J-Value : s-1 : SCALE_JV +! (2 ) JHNO3 : HNO3 J-Value : s-1 : SCALE_JV +! (3 ) JH2O2 : H2O2 J-Value : s-1 : SCALE_JV +! (4 ) JCH2O : CH2O J-Value : s-1 : SCALE_JV +! (5 ) JO3 : O3 J-Value : s-1 : SCALE_JV +! (6 ) POH : OH-source from O3 photolysis : s-1 : SCALE_JV +! (7 ) JGLYX : GLYX J-Value : s-1 : SCALE +! (8 ) JMGLY : MGLY J-Value : s-1 : SCALE +! (71 ) JCH3I : CH3I J-value (s^-1) : s-1 : SCALE_JV +! (81 ) JHCN : HCN J-value (s^-1) : s-1 : SCALE_JV +! +! NOTES: +! (1) We must add TRCOFFSET for CH3I and HCN runs, so that GAMAP can +! recognize those photo rates as distinct from the NO2, HNO3, +! H2O2, CH2O, O3, and POH photo rates. +! (2) Pick the right tracer field from AD22 if only a subset of tracers +! are requested to be printed out. (ccc, 12/15/08) +! (3) Add GLYX and MGLY tracers (tmf, 3/6/09) +!****************************************************************************** +! + IF ( ND22 > 0 ) THEN + CATEGORY = 'JV-MAP-$' + SCALE_TMP = FLOAT( CTJV ) + 1d-20 + UNIT = 's-1' + + DO M = 1, TMAX(22) + N = TINDEX(22,M) + !----------------------------------------------------------------- + ! Prior to 12/15/08: + !IF ( N > PD22 ) CYCLE + !----------------------------------------------------------------- + NN = N + + !----------------------------------------------------------------- + ! NOTE: We can no longer select "all" in "input.geos", but we + ! must specify the tracer #'s for ND22 explicitly: + ! + ! Fullchem: CH3I HCN + ! 1 = NOx 1 = CH3I 1 = HCN + ! 7 = HNO3 + ! 8 = H2O2 + ! 20 = CH2O + ! 55 = GLYX + ! 56 = MGLY + ! N_TRACERS+1 = O3 & OH + ! + ! (ccc, bmy, 12/15/08) + !----------------------------------------------------------------- + IF ( NN >= N_TRACERS+1 ) THEN + MM = 5 ! Write 'O3' and 'OH' + ELSE + SELECT CASE ( TRIM( TRACER_NAME(NN) ) ) + CASE ( 'NOx', 'HCN', 'CH3I' ) + MM = 1 + CASE ( 'HNO3' ) + MM = 2 + CASE ( 'H2O2' ) + MM = 3 + CASE ( 'CH2O' ) + MM = 4 + CASE ( 'GLYX' ) + MM = 7 + CASE ( 'MGLY' ) + MM = 8 + CASE DEFAULT + MM = 0 + END SELECT + ENDIF + + ! Skip if not a valid index + IF ( MM == 0 ) CYCLE + + DO L = 1, LD22 + !--------------------------------------------------------------- + ! Prior to 12/15/08: + !ARRAY(:,:,L) = AD22(:,:,L,N) / SCALE_TMP(:,:) + !--------------------------------------------------------------- + ARRAY(:,:,L) = AD22(:,:,L,MM) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, MM, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD22, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD22) ) + + ! If we have just written out O3, then write out OH + ! (ccc, bmy, 12/15/08) + IF ( MM == 5 ) THEN + MMB = 6 + DO L = 1, LD22 + ARRAY(:,:,L) = AD22(:,:,L,MMB) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, MMB, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD22, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD22) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND24: Eastward mass flux from transport (TPCORE, XTP) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) MASSFLEW : Eastward mass flux - transport : kg/s : SCALEDYN +! +! NOTES: +! (1) MASSFLEW is REAL*8...store to ARRAY, which is REAL*4 +! before sending to BPCH or IJSCAL (bey, bmy, 4/23/99) +! (2) Now only write LD24 levels out to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND24 > 0 ) THEN + CATEGORY = 'EW-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(24) + N = TINDEX(24,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! (dkh, 02/09/12, adj32_022) + !ARRAY(:,:,1:LD24) = MASSFLEW(:,:,1:LD24,N) / SCALEDYN + ARRAY(:,:,1:LD24) = MASSFLEW(:,:,LLPAR:LLPAR-LD24+1:-1,N) + & / SCALEDYN + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD24, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD24) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND25: Northward mass flux from transport (TPCORE, YTP) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) MASSFLNS : Northward mass flux - transport : kg/s : SCALEDYN +! +! NOTES: +! (1) MASSFLNS is REAL*8...store to ARRAY, which is REAL*4 +! before sending to BPCH or IJSCAL (bey, bmy, 4/23/99) +! (2) Now only write LD25 levels out to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND25 > 0 ) THEN + CATEGORY = 'NS-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(25) + N = TINDEX(25,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! (dkh, 02/09/12, adj32_022) + !ARRAY(:,:,1:LD25) = MASSFLNS(:,:,1:LD25,N) / SCALEDYN + ARRAY(:,:,1:LD25) = MASSFLNS(:,:,LLPAR:LLPAR-LD25+1:-1,N) + & / SCALEDYN + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD25, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD25) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND26: Upward mass flux from transport (TPCORE, FZPPM) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) MASSFLUP : Upward mass flux - transport : kg/s : SCALEDYN +! +! NOTES: +! (1) MASSFLNS is REAL*8...store to ARRAY, which is REAL*4 +! before sending to BPCH or IJSCAL (bey, bmy, 4/23/99) +! (2) Now only write LD26 levels to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND26 > 0 ) THEN + CATEGORY = 'UP-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(26) + N = TINDEX(26,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! (dkh, 02/09/12, adj32_022) + !ARRAY(:,:,1:LD26) = MASSFLUP(:,:,1:LD26,N) / SCALEDYN + ARRAY(:,:,1:LD26) = MASSFLUP(:,:,LLPAR:LLPAR-LD26+1:-1,N) + & / SCALEDYN + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD26, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD26) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND27: Cross-tropopause Stratospheric Influx of Ox +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) : Ox : Ox from the stratosphere : kg/s : SCALEDYN +! +! NOTES: +! (1) Only print out if we are doing a NOx-Ox-HC run (NSRCX == 3) +! or a single tracer Ox run (NSRCX == 6). (bey, bmy, 11/10/99) +! (2) Now consider the cross-tropopause stratospheric influx of ozone, +! which, in some grid boxes, includes horizontal influxes as well as +! up(down)ward flux. (qli, 1/5/2000) +! (3) Now error check for N > NTRACE (bmy, 10/23/01) +! (4) NOTE: There is a problem with for ND27 with GEOS-4. Djj says that +! the downward flux at the 200 hPa level should be more or less the +! same as the ND27 diagnostic. (bmy, 10/15/04) +! (5) Now provides stratrospheric flux of H2/HD if it is a H2/HD simulation +! (lyj, phs, 9/18/07) +!****************************************************************************** +! +#if !defined( GEOS_4 ) + IF ( ND27 > 0 .and. IDTOX > 0 ) then + IF ( ( IDTOX > 0 .and. + & ( ITS_A_FULLCHEM_SIM() .or. ITS_A_TAGOX_SIM() ) ) .OR. + & ( ITS_A_H2HD_SIM() ) ) THEN + + CATEGORY = 'STRT-FLX' + UNIT = 'kg/s' + + ! Full chemistry -- compute NOx, Ox, HNO3 fluxes + ! H2/HD -- compute H2, HD fluxes + ! Single tracer Ox -- compute Ox flux only, hardwire + ! to tracer = 1 (bmy, 2/7/00) + IF ( ITS_A_FULLCHEM_SIM() ) THEN + ITEMP = (/ IDTNOX, IDTOX, IDTHNO3 /) + ELSE IF ( ITS_A_H2HD_SIM() ) THEN + ITEMP = (/ IDTH2, IDTHD, 0 /) + ELSE + ITEMP = (/ 1, 0, 0 /) + ENDIF + + ! Loop over tracers + DO M = 1, 3 + N = ITEMP(M) + IF ( N == 0 ) CYCLE + IF ( N > N_TRACERS ) CYCLE + + ! Loop over grid boxes + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Get the level of the tropopause + L = LPAUSE(I,J) + + ! Initialize integer flags + IS = 0 + IN = 0 + IW = 0 + IE = 0 + + ! Set integer flags based on the value of each bit of IFLX + IF ( BTEST( IFLX(I,J), 0 ) ) IS = 1 + IF ( BTEST( IFLX(I,J), 1 ) ) IN = 1 + IF ( BTEST( IFLX(I,J), 2 ) ) IW = 1 + IF ( BTEST( IFLX(I,J), 3 ) ) IE = 1 + + ! Add fluxes from the top, south, and west + ARRAY(I,J,1) = MASSFLUP(I,J,L,N) + + & ( MASSFLNS(I,J,L,N) * IS ) + + & ( MASSFLEW(I,J,L,N) * IW ) + + ! Add fluxes from the north + ! (take poles into account !) + IF ( J < JJPAR ) THEN + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLNS(I,J+1,L,N) * IN ) + ELSE + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLNS(I, 1,L,N) * IN ) + ENDIF + + ! Add fluxes from the east + !(wrap around dateline if necessary) + IF ( I < IIPAR ) THEN + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLEW(I+1,J,L,N) * IE ) + ELSE + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLEW( 1,J,L,N) * IE ) + ENDIF + ENDDO + ENDDO + + UNIT = 'kg/s' + NN = N + + ARRAY(:,:,1) = ARRAY(:,:,1) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, PD27, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF + ENDIF +#endif +! +!****************************************************************************** +! ND28: Biomass burning diagnostic +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) NOx : NOx : molec NOx /cm2/s : SCALESRCE +! (4 ) CO : CO : molec CO /cm2/s : SCALESRCE +! (9 ) ACET : Acetone : atoms C /cm2/s : SCALESRCE +! (10) MEK : Ketones(>C3) : atoms C /cm2/s : SCALESRCE +! (11) ALD2 : Acetaldehyde : atoms C /cm2/s : SCALESRCE +! (18) PRPE : Propene : atoms C /cm2/s : SCALESRCE +! (19) C3H8 : Propane : atoms C /cm2/s : SCALESRCE +! (20) C2HO : Formaldehyde : molec CH2O/cm2/s : SCALESRCE +! (21) C2H6 : Ethane : atoms C /cm2/s : SCALESRCE +! (26) SO2 : Sulfur dioxide : molec SO2 /cm2/s : SCALESRCE +! (30) NH3 : Ammonia : molec NH3 /cm2/s : SCALESRCE +! (34) BCPO : Black carbon : atoms C /cm2/s : SCALESRCE +! (35) OCPO : Organic carbon : atoms C /cm2/s : SCALESRCE +! +! NOTES: +! (1) Use the F90 intrinsic "ANY" function to make sure that N +! corresponds to actual biomass burning tracers (bmy, 4/8/99) +! (2) ND28 now uses allocatable array AD28 instead of AIJ. (bmy, 3/16/00) +! (3) Now write biofuel burning tracers to the punch file in the same order +! as they are listed in "diag.dat". (bmy, 4/17/01) +!****************************************************************************** +! + IF ( ND28 > 0 ) THEN + CATEGORY = 'BIOBSRCE' + UNIT = '' + + DO M = 1, TMAX(28) + N = TINDEX(28,M) + IF ( .not. ANY( BIOTRCE == N ) ) CYCLE + NN = N + + DO MM = 1, NBIOMAX + IF ( BIOTRCE(MM) == NN ) THEN + MMB = MM + EXIT + ENDIF + ENDDO + + ARRAY(:,:,1) = AD28(:,:,MMB) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + ENDIF +! +!****************************************************************************** +! ND29: CO source diagnostics +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) COanth : CO from Anthro Sources : mol/cm2/s : SCALESRCE +! (2) CObb : CO from Biomass Burning : mol/cm2/s : SCALESRCE +! (3) CObf : CO from Biofuel Burning : mol/cm2/s : SCALESRCE +! (4) COmeth : CO from Methanol : mol/cm2/s : SCALESRCE +! (5) COmono : CO from Monoterpenes : mol/cm2/s : SCALESRCE +! +! NOTES: +! (1) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2) ND29 now uses allocatable array AD29 instead of AIJ. (bmy, 3/16/00) +! (3) Added CO-sources from isoprene and monoterpenes (bnd, bmy, 1/2/01) +!****************************************************************************** +! + IF ( ND29 > 0 ) THEN + CATEGORY ='CO--SRCE' + UNIT = 'mol/cm2/s' + + DO M = 1, TMAX(29) + N = TINDEX(29,M) + IF ( N > PD29 ) CYCLE + NN = N + + ARRAY(:,:,1) = AD29(:,:,N) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND30: Land map diagnostic +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) LWI : GMAO Land-Water indices : unitless : SCALED +! +! NOTES: +! (1) Values are: 0=water; 1=land; 2=ice (bmy, 8/18/05) +!****************************************************************************** +! + IF ( ND30 > 0 ) THEN + CATEGORY = 'LANDMAP' + UNIT = 'unitless' + + ARRAY(:,:,1) = AD30(:,:) / SCALEDYN + NN = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF +! +!****************************************************************************** +! ND31: Surface pressure diagnostic +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) Pedge : Pressure at bot edge of level L : mb : SCALEDYN +! +! NOTES: +! (1) The ASCII punch file was using SCALE2 instead of SCALE1. +! This has now been fixed. (hyl, bmy, 12/21/99). +! (2) Now use AD31 dynamically allocatable array (bmy, 2/17/00) +! (3) Bug fix: write out 1 level to the bpch file (bmy, 12/7/00) +! (4) Now remove SCALE1, replace with SCALEDYN (bmy, 2/24/03) +! (5) Now save out true pressure at level edges. Now (bmy, 5/8/07) +!****************************************************************************** +! + IF ( ND31 > 0 ) THEN + CATEGORY = 'PEDGE-$' + UNIT = 'mb' + ARRAY(:,:,1:LD31) = AD31(:,:,1:LD31) / SCALEDYN + NN = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD31, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD31) ) + ENDIF +! +!****************************************************************************** +! ND32: NOx source diagnostic +! +! Levels : Field : Units : Scale Factor +! ------------------------------------------------------------------------- +! 1 - LLTROP : Aircraft NOx : molec/cm2/s : SCALESRCE +! 1 - NOXEXTENT : Anthropogenic NOx : molec/cm2/s : SCALESRCE +! Surface : Biomass Burning NOx : molec/cm2/s : SCALESRCE +! Surface : Biofuel Burning NOx : molec/cm2/s : SCALESRCE +! Surface : Fertilizer NOx : molec/cm2/s : SCALESRCE +! 1 - LLCONVM : Lightning NOx : molec/cm2/s : SCALESRCE +! Surface : Soil NOx : molec/cm2/s : SCALESRCE +! Above TP : NOx from upper boundary: molec/cm2/s : SCALEDYN +! +! Print out all of the types of NOx, for all levels. +! +! NOTES: +! (1) Only print out ND32 if for an O3 chemistry run ( NSRCX == 3 ), +! and if NOx is a defined tracer ( IDTNOX > 0 ). (bmy, 5/26/99) +! (2) ND32 now uses allocatable arrays instead of AIJ. (bmy 3/16/00) +! (3) Added biofuel burning to ND32 diagnostic (bmy, 9/12/00) +!****************************************************************************** +! + IF ( ND32 > 0 .and. IDTNOX > 0 .and. ITS_A_FULLCHEM_SIM() ) THEN + + ! All categories of NOx are in molec/cm2/s + UNIT = 'molec/cm2/s' + + !============================================================== + ! Aircraft NOx + !============================================================== + CATEGORY = 'NOX-AC-$' + + DO L = 1, LLTROP + ARRAY(:,:,L) = AD32_ac(:,:,L) / SCALESRCE + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLTROP, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LLTROP) ) + + !============================================================== + ! Anthropogenic NOx + !============================================================== + CATEGORY = 'NOX-AN-$' + + ! Add ship NOx to layer 1 + ! We scale by AD32_ship_count because the ship emission diagnostic + ! is recorded every CHEMISTRY timestep when using INSTANT PBL mixing + ! and every CONVECTION timestep when using NON-LOCAL PBL mixing + IF ( AD32_SHIP_COUNT >= 1 ) THEN + ARRAY(:,:,1) = AD32_an(:,:,1) / SCALESRCE + + & AD32_SHIP(:,:) / REAL( AD32_SHIP_COUNT ) + ARRAY(:,:,2:NOXEXTENT) = AD32_an(:,:,2:NOXEXTENT) / SCALESRCE + ELSE + ARRAY(:,:,1:NOXEXTENT) = AD32_an(:,:,1:NOXEXTENT) / SCALESRCE + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, NOXEXTENT, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:NOXEXTENT) ) + + !============================================================== + ! Biomass Burning NOx + !============================================================== + CATEGORY = 'NOX-BIOB' + ARRAY(:,:,1) = AD32_bb(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Binary punch file: NOx from Biofuel + !============================================================== + CATEGORY = 'NOX-BIOF' + ARRAY(:,:,1) = AD32_bf(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Fertilizer NOx + !============================================================== + CATEGORY = 'NOX-FERT' + ARRAY(:,:,1) = AD32_fe(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Lightning NOx + !============================================================== + CATEGORY = 'NOX-LI-$' + + DO L = 1, LLCONVM + ARRAY(:,:,L) = AD32_li(:,:,L) / SCALESRCE + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLCONVM, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LLCONVM) ) + + !============================================================== + ! Soil NOx + !============================================================== + CATEGORY = 'NOX-SOIL' + ARRAY(:,:,1) = AD32_so(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Stratospheric NOx (boundary condition) + !============================================================== + CATEGORY = 'NOX-STRT' + ARRAY(:,:,1) = AD32_ub(:,:) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF +! +!****************************************************************************** +! ND33: Atmospheric column sum of Tracer +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) COLUMN-T : Trop. Column Sum of Tracer : kg : SCALEDYN +! +! NOTES: +! (1) Now use dynamically allocatable array AD33 (bmy, 2/17/00) +! (2) Rename category to COLUMN-T, since this is a column sum of tracer over +! the entire atmosphere, not just the troposphere. (bmy, 4/3/02) +! (3) Now replace SCALE1 with SCALEDYN (bmy, 3/27/03) +!****************************************************************************** +! + IF ( ND33 > 0 ) THEN + CATEGORY = 'COLUMN-T' + UNIT = 'kg' + + DO M = 1, TMAX(33) + N = TINDEX(33,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1) = AD33(:,:,N) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND34: Biofuel burning diagnostic +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) NOx : NOx : molec NOx /cm2/s : SCALESRCE +! (4 ) CO : CO : molec CO /cm2/s : SCALESRCE +! (5 ) ALK4 : Alkanes(>C4) : atoms C /cm2/s : SCALESRCE +! (9 ) ACET : Acetone : atoms C /cm2/s : SCALESRCE +! (10) MEK : Metyl Ethyl Ketone : atoms C /cm2/s : SCALESRCE +! (11) ALD2 : Acetaldehyde : atoms C /cm2/s : SCALESRCE +! (18) PRPE : Alkenes(>=C3) : atoms C /cm2/s : SCALESRCE +! (19) C3H8 : Propane : atoms C /cm2/s : SCALESRCE +! (20) CH2O : Formaldehyde : molec CH2O/cm2/s : SCALESRCE +! (21) C2H6 : Ethane : atoms C /cm2/s : SCALESRCE +! +! NOTES: +! (1) Use the F90 intrinsic "ANY" function to make sure that N +! corresponds to actual biofuel burning tracers (bmy, 3/15/01) +! (3) Now write biofuel burning tracers to the punch file in the same order +! as they are listed in "diag.dat". (bmy, 4/17/01) +! (4) Use BFTRACE and NBFTRACE to get the right index for AD34. +! (ccc, 12/8/2008) +!****************************************************************************** +! + IF ( ND34 > 0 ) THEN + CATEGORY = 'BIOFSRCE' + UNIT = '' + + DO M = 1, TMAX(34) + N = TINDEX(34,M) + IF ( .not. ANY( BFTRACE == N ) ) CYCLE + NN = N + + DO MM = 1, NBFTRACE + IF ( BFTRACE(MM) == NN ) THEN + MMB = MM + EXIT + ENDIF + ENDDO + + ARRAY(:,:,1) = AD34(:,:,MMB) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND35: Tracer concentration at 500 mb +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) 500-AVRG : Tracer at 500 mb : v/v : SCALEDYN +! +! NOTES: +! (1) Now use dynamically allocatable array AD35 (bmy, 2/17/00) +! (2) Now replace SCALE1 with SCALEDYN (bmy, 2/24/03) +!****************************************************************************** +! + IF ( ND35 > 0 ) THEN + CATEGORY = '500-AVRG' + UNIT = '' + + DO M = 1, TMAX(35) + N = TINDEX(35,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1) = AD35(:,:,N) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND36: Anthropogenic source diagnostic +! +! # Field : Description : Units : S. Factor +! --------------------------------------------------------------------------- +! (1 ) NOx : NOx : mol/cm2/s : SCALE3 +! (4 ) CO : CO : mol/cm2/s : SCALE3 +! (5 ) ALK4 : Alkanes(>C4) : atoms C/cm2/s : SCALE3 +! (9 ) ACET : Acetone : atoms C/cm2/s : SCALE3 +! (10) MEK : Ketones(>C3) : atoms C/cm2/s : SCALE3 +! (18) PRPE : Propene : atoms C/cm2/s : SCALE3 +! (19) C3H8 : Propane : atoms C/cm2/s : SCALE3 +! (21) C2H6 : Ethane : atoms C/cm2/s : SCALE3 +! (71) CH3Ioc : Methyl Iodide (oceanic source) : ng/m2/s : SCALE3 +! (72) CH3Ibb : Methyl Iodide (biomass burning) : ng/m2/s : SCALE3 +! (73) CH3Iwb : Methyl Iodide (wood burning) : ng/m2/s : SCALE3 +! (74) CH3Irc : Methyl Iodide (rice paddies) : ng/m2/s : SCALE3 +! (75) CH3Iwl : Methyl Iodide (wetlands) : ng/m2/s : SCALE3 +! +! NOTES: +! (1) ND36 is also used for CH3I emissions diagnostics when NSRCX=2. +! (2) For an O3 run (NSRCX = 3, the "default" run) make sure that the +! tracer number N matches an entry in the IDEMS emission index +! array (bmy, 4/9/99) +! (3) Write the tracers out to the punch file in the same order as +! they are listed in the IDEMS array. Thus, we have to re-assign +! N = IDEMS(M) after we test to make sure it is a valid tracer +! number (bmy, 4/16/99) +! (4) For a CH3I run, make sure that the tracer number N is not larger +! than NTRACE (bmy, 4/9/99) +! (5) ND36 now uses the AD36 array instead of AIJ. (bmy, 3/16/00) +! (6) Rewritten for clarity; also fixed for CH3I (bmy, 7/25/06) +! (7) Bug fix: given the tracer number, now search for entry in IDEMS +! to jive with historical baggage (bmy, 3/6/07) +!****************************************************************************** +! + IF ( ND36 > 0 ) THEN + + ! Loop over # of tracers + DO M = 1, TMAX(36) + + ! Get the tracer # from input.geos + N = TINDEX(36,M) + + IF ( ITS_A_CH3I_SIM() ) THEN + + !-------------------------------------------------------- + ! For CH3I simulation only + !-------------------------------------------------------- + CATEGORY = 'CH3ISRCE' + UNIT = 'ng/m2/s' + IF ( N > NEMANTHRO ) CYCLE + + ! Tracer number + NN = N + + ! Index for AD36 array + MM = M + + ELSE + + !-------------------------------------------------------- + ! For full-chemistry. Note, due to historical baggage, + ! the order of the tracers in AD36 array corresponds to + ! the order as given in IDEMS. Therefore, for the given + ! tracer number N, we must find the corresponding entry + ! in IDEMS. (bmy, 3/5/07) + !-------------------------------------------------------- + CATEGORY = 'ANTHSRCE' + UNIT = '' + + ! reset these + MM = 0 + NN = 0 + + ! Given the tracer number N, find the proper entry in the + ! IDEMS array and select that for output (bmy, 3/5/07) + DO NMAX = 1, NEMANTHRO + IF ( N == IDEMS(NMAX) ) THEN + MM = NMAX + NN = N + EXIT + ENDIF + ENDDO + + ! We haven't found a match, skip to next tracer + IF ( MM == 0 ) CYCLE + + ENDIF + + ! Divide by seconds for AD36 and by AD36_SHIP_COUNT for AD36_SHIP + ! We scale by AD32_ship_count because the ship emission diagnostic + ! is recorded every CHEMISTRY timestep when using INSTANT PBL mixing + ! and every CONVECTION timestep when using NON-LOCAL PBL mixing + IF ( AD36_SHIP_COUNT >= 1 ) THEN + ARRAY(:,:,1) = AD36(:,:,MM) / SECONDS + + & AD36_SHIP(:,:,MM) / REAL( AD36_SHIP_COUNT ) + ELSE + ARRAY(:,:,1) = AD36(:,:,MM) / SECONDS + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND37: Fraction of tracer scavenged in convective cloud updrafts +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WETCVF-$ : Scavenging fraction : unitless : SCALECONV +!****************************************************************************** +! + IF ( ND37 > 0 ) THEN + CATEGORY = 'MC-FRC-$' + UNIT = 'unitless' + + ! Get actual # of soluble tracers + NMAX = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, NMAX + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(37) ) + MMB = TINDEX(37,MM) + MM = MM + 1 + ENDDO + + IF ( MMB /= NN ) CYCLE + + DO L = 1, LD37 + ARRAY(:,:,L) = AD37(:,:,L,N) / SCALECONV + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD37, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD37) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND38: Rainout loss of tracer in convective updrafts +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WETDCV-$ : Rainout loss of tracer : kg/s : SCALECONV +! +! NOTES: +! (1) Now write only LD38 levels to bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND38 > 0 ) THEN + CATEGORY = 'WETDCV-$' + UNIT = 'kg/s' + + ! Get actual # of soluble tracers + M = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, M + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(38) ) + MMB = TINDEX(38,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Divide by # of convective timesteps + DO L = 1, LD38 + ARRAY(:,:,L) = AD38(:,:,L,N) / SCALECONV + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD38, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD38) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND39: Rainout loss of tracer in large scale rains +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WETDLS-$ : Large-scale loss of tracer : kg/s : SCALEDYN +!****************************************************************************** +! + IF ( ND39 > 0 ) THEN + CATEGORY = 'WETDLS-$' + UNIT = 'kg/s' + + ! Get actual # of soluble tracers + M = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, M + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(39) ) + MMB = TINDEX(39,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Divide by # of wetdep (= dynamic) timesteps + DO L = 1, LD39 + ARRAY(:,:,L) = AD39(:,:,L,N) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD39, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD39) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND41: Afternoon boundary layer heights +!****************************************************************************** +! + IF ( ND41 > 0 ) CALL WRITE_DIAG41 +! +!****************************************************************************** +! ND42: SOA concentrations [ug/m3] +!****************************************************************************** +! + IF ( ND42 > 0 ) CALL WRITE_DIAG42 +! +!****************************************************************************** +! ND42: Free diagnostic as of 11/24/99 +! +! ND43: Chemical production of OH and NO +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) OH : OH Chemical Diagnostic : mol/cm3 : CTOH +! (2) NO : NO Chemical Diagnostic : v/v : CTNO +! (3) HO2 : HO2 Chemical Diagnostic : v/v : CTHO2 +! (4) NO2 : NO2 Chemical Diagnostic : v/v : CTNO2 +! (5) NO3 : NO3 Chemical Diagnostic : v/v : CTNO3 +! +! NOTES: +! (1) Print output for either a NOx-Ox-HC run (NSRCX == 3), or a CO run +! with parameterized OH (NSRCX== 5). (bmy, 4/17/00) +! (2) Add parentheses in IF test since .AND. has higher precedence +! than .OR. (jsw, bmy, 12/5/00) +! (3) Added HO2, NO2 to ND43 (rvm, bmy, 2/27/02) +! (4) Added NO3 to ND43 (bmy, 1/16/03) +! (5) Now uses 3D counters (phs, 1/24/07) +! (6) Now assume that LD43 can't be higher than LD45 (phs, 1/24/07) +! (7) Check that CTxx are not zero, instead of adding 1e-20 (phs, 11/13/07) +!****************************************************************************** +! + IF ( ND43 > 0 .and. ITS_A_FULLCHEM_SIM() ) THEN + + CATEGORY = 'CHEM-L=$' + + DO M = 1, TMAX(43) + N = TINDEX(43,M) + NN = N + + ! default units + UNIT = 'v/v' + + + SELECT CASE ( N ) + + ! OH + CASE ( 1 ) + WHERE( CTOH /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTOH ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + UNIT = 'molec/cm3' + + ! NO + CASE ( 2 ) + WHERE( CTNO /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTNO ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + + ! HO2 (rvm, bmy, 2/27/02) + CASE ( 3 ) + WHERE( CTHO2 /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTHO2 ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + + ! NO2 (rvm, bmy, 2/27/02) + CASE ( 4 ) + WHERE( CTNO2 /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTNO2 ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + ! NO3 (rjp, bmy, 1/16/03) + CASE ( 5 ) + WHERE( CTNO3 /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTNO3 ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + + CASE DEFAULT + CYCLE + + END SELECT + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD43, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD43) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND44: Drydep flux (molec/cm2/s) and velocity (cm/s) diagnostics +! +! # : Field : Quantity : Units : Scale factor +! ------------------------------------------------------------------------- +! (1 ) : DRYD-FLX : drydep fluxes : molec/cm2/s or kg/s : SCALECHEM +! (2 ) : DRYD-VEL : drydep velocities : cm/s : SCALECHEM +! +! NOTES: +! (1 ) Remove diagnostics for wetdep HNO3, H2O2 from ND44. +! (2 ) For NSRCX == 1 (Rn-Pb-Be), save the actual tracer number +! instead of the dry deposition index. Add TRCOFFSET to N. +! (3 ) For NSRCX == 6 (single tracer Ox), drydep fluxes are in kg/s. +! (4 ) ND44 now uses allocatable array AD44 instead of AIJ. (bmy, 3/16/00) +! (5 ) Add code from amf for multi-tracer Ox (bmy, 7/3/01) +! (6 ) Now divide by SCALECHEM since DRYFLX is only called after the +! chemistry routines for all relevant simulations (bmy, 1/27/03) +! (7 ) Now print out NTRACE drydep fluxes for tagged Ox. Also tagged Ox +! now saves drydep in molec/cm2/s. (bmy, 8/19/03) +! (8 ) Rearrange ND44 code for clarity (bmy, 3/24/04) +! (9 ) Add code for H2/HD simulation (phs, 5/8/07) +!****************************************************************************** +! + IF ( ND44 > 0 ) THEN + + !============================================================== + ! Drydep fluxes + !============================================================== + + ! Category name + CATEGORY = 'DRYD-FLX' + + ! # of drydep flux tracers + IF ( ITS_A_TAGOX_SIM() .or. ITS_A_MERCURY_SIM() ) THEN + M = N_TRACERS + ELSE + M = NUMDEP + ENDIF + + ! Loop over drydep tracers + DO N = 1, M + + IF ( ITS_A_RnPbBe_SIM() .or. ITS_A_H2HD_SIM() ) THEN + + ! Radon or H2/HD + UNIT = 'kg/s' + NN = NTRAIND(N) + + ELSE IF ( ITS_A_TAGOX_SIM() .or. ITS_A_MERCURY_SIM() ) THEN + + ! Tagged Ox or Tagged Hg + UNIT = 'molec/cm2/s' + NN = N + + ELSE + + ! Other simulations + UNIT = 'molec/cm2/s' + NN = NTRAIND(N) + + ENDIF + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(44) ) + MMB = TINDEX(44,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Save into ARRAY + ARRAY(:,:,1) = ( AD44(:,:,N,1) / SCALECHEM ) + + ! Write to file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + + !============================================================== + ! Drydep velocities + !============================================================== + + ! Category and Unit + CATEGORY = 'DRYD-VEL' + UNIT = 'cm/s' + + ! # of drydep velocity tracers + IF ( ITS_A_TAGOX_SIM() ) THEN + M = 1 + ELSE IF ( ITS_A_MERCURY_SIM() ) THEN + M = 2 + ELSE + M = NUMDEP + ENDIF + + ! Loop over drydep tracers + DO N = 1, M + + NN = NTRAIND(N) + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(44) ) + MMB = TINDEX(44,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Tracer number plus GAMAP offset + ARRAY(:,:,1) = AD44(:,:,N,2) / SCALESRCE + + ! Write to file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + ENDIF +! +!****************************************************************************** +! ND45: Tracer Mixing Ratio (v/v) for Levels L = 1, LD45 +! averaged between hours OTH_HR1 and OTH_HR2 +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) IJ-AVG-$ : Tracer mixing ratio : v/v : CTOTH +! +! NOTES: +! (1) For NSRCX == 3 (NOx-Ox-HC run), store pure O3 with index NTRACE+1. +! (2) Now store pure O3 as NNPAR+1 (now tracer #32). (bmy, 1/10/03) +! (3) Now uses CTO3 instead of CTOH for pure O3 (phs, 1/24/07) +! (4) Better handling of O3 case (phs, 11/17/08) +!****************************************************************************** +! + IF ( ND45 > 0 ) THEN + CATEGORY = 'IJ-AVG-$' + SCALE_TMP = FLOAT( CTOTH ) + 1d-20 + UNIT = '' + + DO M = 1, TMAX(45) + N = TINDEX(45,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + DO L = 1, LD45 + ARRAY(:,:,L) = AD45(:,:,L,N) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD45, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD45) ) + + ! Store pure O3 as NNPAR+1 (bmy, 1/10/03) + IF ( ITS_A_FULLCHEM_SIM() .and. NN == IDTOX ) THEN + + WHERE( CTO3 /= 0 ) + ARRAY(:,:,1:LD45) = AD45(:,:,1:LD45,N_TRACERS+1) / + $ FLOAT( CTO3 ) + ELSEWHERE + ARRAY(:,:,1:LD45) = 0. + ENDWHERE + + NN = N_TRACERS + 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD45, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD45) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND46: Biogenic source diagnostic +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) ISOP : Isoprene : atoms C/cm2/s : SCALE3 +! (2) ACET : Acetone : atoms C/cm2/s : SCALE3 +! (3) PRPE : Propene : atoms C/cm2/s : SCALE3 +! (4) MONOT : Monoterpenes : atoms C/cm2/s : SCALE3 +! (5) MBO : Methyl Butenol : atoms C/cm2/s : SCALE3 +! (6) C2H4 : Ethene : atoms C/cm2/s : SCALE3 +! +! NOTES: +! (1) ND46 now uses allocatable array AD46 instead of AIJ (bmy, 3/16/00) +! (2) Also write out PRPE for CO-OH run (NSRCX == 5), regardless of +! the setting of IDTPRPE. This is to print out monterpene +! diagnostics. (bnd, bmy, 4/18/00) +! (3) Added monoterpenes as tracer #4. This requires updated versions +! of "tracerinfo.dat" and "diaginfo.dat" for GAMAP. (bmy, 1/2/01) +! (4) Added MBO as tracer #5. (tmf, bmy, 10/20/05) +! (5) Added C2H4 as tracer #6. (tmf, 1/20/09) +!****************************************************************************** +! + IF ( ND46 > 0 ) THEN + CATEGORY = 'BIOGSRCE' + UNIT = '' + + DO M = 1, TMAX(46) + N = TINDEX(46,M) + IF ( N > PD46 ) CYCLE + NN = N + + ! Skip if ISOP, ACET, PRPE are not tracers + IF ( N == 1 .and. IDTISOP == 0 ) CYCLE + IF ( N == 2 .and. IDTACET == 0 ) CYCLE + IF ( N == 3 .and. IDTPRPE == 0 ) CYCLE + IF ( N == 6 .and. IDTC2H4 == 0 ) CYCLE + + ARRAY(:,:,1) = AD46(:,:,N) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND47: Tracer Mixing Ratio (v/v) for Levels L = 1, LD47 +! *always* averaged between 0000 and 2400 Local time. +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) IJ-24H-$ : 24h avg Tracer mixing ratio : v/v : SCALEDYN +! +! NOTES: +! (1) For NSRCX == 3 (NOx-Ox-HC run), store pure O3 with index NTRACE+1. +! (2) Now store pure O3 as NNPAR+1 (now tracer #32). (bmy, 1/10/03) +! (3) Now replace SCALE1 with SCALEDYN +! (4) Now averaged between 0 and 24 UT. Replace SCALEDYN with CTOH and +! CTO3 (phs, 1/24/07) +! (5) Revert to SCALEDYN for all species, except O3, which uses new +! CTO3_24h counter (phs, 11/17/08) +!****************************************************************************** +! + IF ( ND47 > 0 ) THEN + CATEGORY = 'IJ-24H-$' + UNIT = '' + + DO M = 1, TMAX(47) + N = TINDEX(47,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + DO L = 1, LD47 + ARRAY(:,:,L) = AD47(:,:,L,N) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD47, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD47) ) + + ! Store pure O3 as NNPAR+1 (bmy, 1/10/03) + IF ( ITS_A_FULLCHEM_SIM() .and. NN == IDTOX ) THEN + + WHERE( CTO3_24h(:,:,1:LD47) /= 0 ) + ARRAY(:,:,1:LD47) = AD47(:,:,1:LD47,N_TRACERS+1) / + $ FLOAT( CTO3_24h(:,:,1:LD47) ) + ELSEWHERE + ARRAY(:,:,1:LD47) = 0. + ENDWHERE + + NN = N_TRACERS + 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD47, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD47) ) + ENDIF + ENDDO + ENDIF + +!****************************************************************************** +! ND52: gamma HO2 and aerosol radius (jaegle 02/26/09) +! # Category +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1): GAMMAHO2 : Uptake coef for HO2 : unitless : SCALECHEM +! +!****************************************************************************** + IF ( ND52 > 0 ) THEN + CATEGORY = 'GAMMA' + UNIT = 'unitless' + + DO L = 1, LD52 + ARRAY(:,:,L) = AD52(:,:,L) / SCALECHEM + ENDDO + + ! Save to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD52, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD52) ) + + ENDIF + + +! +!****************************************************************************** +! ND54: Time-in-the-Troposphere diagnostic +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) TIME-TPS : Time spend in troposphere : fraction : SCALEDYN +!****************************************************************************** +! + IF ( ND54 > 0 ) THEN + CATEGORY = 'TIME-TPS' + UNIT = 'unitless' + + DO L = 1, LD54 + ARRAY(:,:,L) = AD54(:,:,L) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD54, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD54) ) + ENDIF +! +!****************************************************************************** +! ND55: Tropopause diagnostics +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) TP-LEVEL : Tropopause level : unitless : SCALEDYN +! (2) TP-HGHT : Tropopause height : km : SCALEDYN +! (3) TP-PRESS : Tropopause pressure : mb : SCALEDYN +!****************************************************************************** +! + IF ( ND55 > 0 ) THEN + CATEGORY = 'TR-PAUSE' + + DO M = 1, TMAX(55) + N = TINDEX(55,M) + IF ( N > PD55 ) CYCLE + NN = N + + ! Pick the appropriate unit string + SELECT CASE ( N ) + CASE ( 1 ) + UNIT = 'unitless' + CASE ( 2 ) + UNIT = 'km' + CASE ( 3 ) + UNIT = 'mb' + END SELECT + + ARRAY(:,:,1) = AD55(:,:,N) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND56: Lightning flash rate diagnostics (ltm, bmy, 5/5/06)) +!****************************************************************************** +! + IF ( ND56 > 0 ) CALL WRITE_DIAG56 +! +!****************************************************************************** +! ND58: CH4 Emission Diagnostics +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1 ) CH4-TOT : CH4 Emissions total(w/o sab): kg : 1 +! (2 ) CH4-GAO : CH4 Emissions gas & oil : kg : 1 +! (3 ) CH4-COL : CH4 Emissions coal : kg : 1 +! (4 ) CH4-LIV : CH4 Emissions livestock : kg : 1 +! (5 ) CH4-WST : CH4 Emissions waste : kg : 1 +! (6 ) CH4-BFL : CH4 Emissions biofuel : kg : 1 +! (7 ) CH4-RIC : CH4 Emissions rice : kg : 1 +! (8 ) CH4-OTA : CH4 Emissions other anthro : kg : 1 +! (9 ) CH4-BBN : CH4 Emissions bioburn : kg : 1 +! (10) CH4-WTL : CH4 Emissions wetlands : kg : 1 +! (11) CH4-SAB : CH4 Emissions soil abs : kg : 1 +! (12) CH4-OTN : CH4 Emissions other natural : kg : 1 +!****************************************************************************** +! + IF ( ND58 > 0 ) THEN + CATEGORY = 'CH4-EMIS' + + DO M = 1, TMAX(58) + N = TINDEX(58,M) + IF ( N > PD58 ) CYCLE + NN = N + + UNIT = 'kg' + + ARRAY(:,:,1) = AD58(:,:,N) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND59: NH3 concentrations [ug/m3] (diag59 added, lz,10/11/10) +!****************************************************************************** +! + IF ( ND59 > 0 ) CALL WRITE_DIAG59 +! +!****************************************************************************** +! ND60: Wetland fraction +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) WET-FRAC : WETLAND FRACTION : unitless : 1 +!****************************************************************************** +! + IF ( ND60 > 0 ) THEN + + UNIT = 'unitless' + CATEGORY = 'WET-FRAC' + ARRAY(:,:,1) = AD60(:,:) + N = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDIF +! +!***************************************************************************** +! ND62: I-J Instantaneous Column Maps for Tracers (molec/cm^2) +! +! The unit conversion is as follows: +! +! STT (kg) | 6.022e23 molec | mole | 1000 g | 1 | m^2 +! ---------+----------------+----------+--------+-------------+---------- +! | mole | MOLWT g | kg | AREA_M2 m^2 | 10^4 cm^2 +! +! +! which is equivalent to +! +! ( STT * 6.022e22 ) / ( MOLWT * AREA_M2 ) +!***************************************************************************** +! + IF ( ND62 > 0 ) THEN + CATEGORY = 'INST-MAP' + + DO M = 1, TMAX(62) + N = TINDEX(62,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + DO J = 1, JJPAR + + ! Grid box surface area [cm2] + AREA_M2 = GET_AREA_M2( J ) + + DO I = 1, IIPAR + ARRAY(I,J,1) = ( SUM( STT(I,J,:,N) ) * 6.022d22 ) + & / ( TRACER_MW_G(N) * AREA_M2 ) + ENDDO + ENDDO + + ! Write the proper unit string + IF ( TRACER_MW_G(N) > 12d0 ) THEN + UNIT = 'molec/cm2' + ELSE + UNIT = 'atoms C/cm2' + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + ENDIF +! +!****************************************************************************** +! ND65: Production/Loss of specified chemical families +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) PORL-L=$ : Chemical family P-L rates : mol/cm3/s : SCALECHEM +! +! NOTES: +! (1 ) Make sure the units for NSRCX == 6 (single tracer O3) P-L +! coincide with those in "chemo3.f". +! (2 ) ND65 now uses allocatable array AD65 instead of AIJ. (bmy, 3/16/00) +! (3 ) Add L(CH3I) to the ND65 diagnostic -- do not take the average +! but instead compute the total sum of L(CH3I) (nad, bmy, 3/20/01) +! (4 ) Add updates for multi-tracer Ox run from amf (bmy, 7/3/01) +! (5 ) Now account for time in troposphere for full chemistry. It is +! assumed that LD45 >= LD65 in using CTO3 (phs, 3/6/07) +! (6 ) Do not use CTO3 anymore, but the new CTO3_24h, which is the 3D +! tropospheric chemistry counter (phs, 11/17/08) +!****************************************************************************** +! + IF ( ND65 > 0 ) THEN + CATEGORY = 'PORL-L=$' + + ! Loop over ND65 families + DO N = 1, NFAMILIES + + ! Don't add TRCOFFSET for single tracer Ox + ! Also select proper unit string + IF ( ITS_A_CH3I_SIM() ) THEN + NN = N + UNIT = 'kg/s' + + DO L = 1, LD65 + ARRAY(:,:,L) = AD65(:,:,L,N) + ENDDO + + ELSE IF ( ITS_A_TAGOX_SIM() ) THEN + NN = N + UNIT = 'kg/s' + + WHERE( CTO3_24h(:,:,1:LD65) /= 0 ) + ARRAY(:,:,1:LD65) = AD65(:,:,1:LD65,N) / + $ FLOAT( CTO3_24h(:,:,1:LD65) ) + ELSEWHERE + ARRAY(:,:,1:LD65) = 0. + ENDWHERE + + ELSE IF ( ITS_AN_AEROSOL_SIM() ) THEN + NN = N + UNIT = 'mol/cm3/s' + + DO L = 1, LD65 + ARRAY(:,:,L) = AD65(:,:,L,N) / SCALECHEM + ENDDO + + ELSE + NN = N + UNIT = 'mol/cm3/s' + + WHERE( CTO3_24h(:,:,1:LD65) /= 0 ) + ARRAY(:,:,1:LD65) = AD65(:,:,1:LD65,N) / + $ FLOAT( CTO3_24h(:,:,1:LD65) ) + ELSEWHERE + ARRAY(:,:,1:LD65) = 0. + ENDWHERE + + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD65, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD65) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND66: GMAO 3-D fields +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) UWND : GMAO Zonal Winds : m/s : SCALE_I6 or _A6 +! (2) VWND : GMAO Meridional Winds : m/s : SCALE_I6 or _A6 +! (3) TMPU : GMAO Temperatures : K : SCALE_I6 or _A6 +! (4) SPHU : GMAO Specific Humidity : g/kg : SCALE_I6 or _A6 +! (5) CLDMAS : GMAO Cloud Mass Flux : kg/m2/s : SCALE_A6 or _A6 +! (6) DTRAIN : GMAO Detrainment flux : kg/m2/s : SCALE_A6 +! +! NOTES: +! (1) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2) Add CLDMAS to ND66 diagnostic as field #6, but with tracer index +! #7 (for compatibility with the existing GAMAP). (rvm, bmy, 9/8/00) +! (3) For GEOS-4/fvDAS, UWND, VWND, TMPU, SPHU are A-6 fields. Adjust +! the scale factors accordingly. Also delete KZZ. (bmy, 6/23/03) +! (4) Modified for GEOS-5 and GCAP (bmy, 6/9/05) +!****************************************************************************** +! + IF ( ND66 > 0 ) THEN + CATEGORY = 'DAO-3D-$' + +!!! (lzh, 11/01/2014, geos-fp) +#if defined( GEOS_FP ) + SCALE_ND66 = SCALE_A3 ! For GEOS-FP, ND66 is 3-hr time-avg data +#elif defined( MERRA ) + SCALE_ND66 = SCALE_A3 ! For MERRA, ND66 is 3-hr time-avg data +#else + SCALE_ND66 = SCALE_A6 ! Otherwise, ND66 is 6-hr time-avg data +#endif + + DO M = 1, TMAX(66) + N = TINDEX(66,M) + NN = N + + SELECT CASE ( N ) + + ! UWND, VWND + CASE ( 1,2 ) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#else +!! SCALEX = SCALE_A6 + SCALEX = SCALE_ND66 !! (lzh, 11/01/2014) +#endif + UNIT = 'm/s' + + ! TMPU + CASE ( 3 ) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#elif defined( GEOS_FP ) + SCALEX = SCALE_I3 ! T is an I3 field in GEOS-5.7.x !(lzh,11/01/2014) +#else + SCALEX = SCALE_A6 +#endif + UNIT = 'K' + + ! SPHU + CASE ( 4 ) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#elif defined( GEOS_FP ) + SCALEX = SCALE_I3 ! SPHU is an I3 field in GEOS-5.7.x +#else + SCALEX = SCALE_A6 +#endif + UNIT = 'g/kg' + + ! CLDMAS, DTRAIN + CASE( 5, 6 ) + !! SCALEX = SCALE_A6 + SCALEX = SCALE_ND66 ! geos-fp (lzh,11/01/2014) + UNIT = 'kg/m2/s' + + CASE DEFAULT + CYCLE + END SELECT + + ARRAY(:,:,1:LD66) = AD66(:,:,1:LD66,N) / SCALEX + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD66, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD66) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND67: GMAO surface fields +! +! # : Field : Description : Units : Scale factor +! ----------------------------------------------------------------------- +! (1 ) HFLUX : GMAO Sensible Heat Flux : W/m2 : SCALE_A3 +! (2 ) RADSWG : GMAO Insolation @ Surface : W/m2 : SCALE_A3 +! (3 ) PREACC : GMAO Accum Precip @ Surface : mm/day : SCALE_A3 +! (4 ) PRECON : GMAO Conv Precip @ Surface : mm/day : SCALE_A3 +! (5 ) TS : GMAO Surface Air Temperature : K : SCALE_A3 +! (6 ) RADSWT : GMAO Insolation @ Top of Atm : W/m2 : SCALE_A3 +! (7 ) USTAR : GMAO Friction Velocity : m/s : SCALE_A3 +! (8 ) Z0 : GMAO Roughness Height : m : SCALE_A3 +! (9 ) PBL : GMAO PBL depth : mb : SCALE_A3 +! (10) CLDFRC : GMAO Cloud Fraction : unitless : SCALE_A3 +! (11) U10M : GMAO U-wind @ 10 m : m/s : SCALE_A3 +! (12) V10M : GMAO V-wind @ 10 m : m/s : SCALE_A3 +! (13) PS-PBL : GMAO Boundary Layer Top Pressure : mb : SCALEDYN +! (14) ALBD : GMAO Surface Albedo : unitless : SCALE_I6 +! (15) PHIS : GMAO Geopotential Heights : m : SCALED +! (16) CLTOP : GMAO Cloud Top Height : levels : SCALE_A6 +! (17) TROPP : GMAO Tropopause pressure : mb : SCALE_I6 +! (18) SLP : GMAO Sea Level pressure : mb : SCALE_I6 +! (19) TSKIN : Ground/sea surface temp. : hPa : SCALE_A3 +! (20) PARDF : Photosyn active diffuse rad. : W/m2 : SCALE_A3 +! (21) PARDR : Photosyn active direct rad. : W/m2 : SCALE_A3 +! (22) GWET : Top soil wetness : unitless : SCALE_A3 +! +! NOTES: +! (1 ) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2 ) Now use AD67 allocatable array (bmy, 2/17/00) +! (3 ) Add TROPP as tracer #17 and SLP as tracer #18 (bmy, 10/11/00) +! (4 ) Now replace SCALE1 with SCALEDYN (bmy, 3/27/03) +! (5 ) Added TSKIN, PARDF, PARDR, GWET for GEOS-4 (bmy, 6/23/03) +! (6 ) Fix SCALEX for ALBEDO: use I6 for GEOS-3 only, and A3 for other +! models (phs, 9/3/08) +!****************************************************************************** +! + IF ( ND67 > 0 ) THEN + CATEGORY = 'DAO-FLDS' + +! (lzh, 11/01/2014) geos_fp +#if defined( MERRA ) + SCALE_ND67 = SCALE_A1 ! For MERRA, ND67 fields are hourly +#elif defined( GEOS_FP ) + SCALE_ND67 = SCALE_A1 ! For GEOS-FP, ND67 fields are hourly +#else + SCALE_ND67 = SCALE_A3 ! Otherwise, most ND67 fields are 3-hourly +#endif + + ! Binary punch file + DO M = 1, TMAX(67) + N = TINDEX(67,M) + NN = N + + SELECT CASE ( N ) + CASE ( 1, 2, 6 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'W/m2' + CASE ( 3, 4 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'mm/day' + CASE ( 5 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'K' + CASE ( 7, 11, 12 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'm/s' + CASE ( 8 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'm' + CASE ( 9 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'hPa' + CASE ( 10 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'unitless' + +#if defined( GCAP ) + ! CLDFRC is a 6-hr field in GCAP, GEOS-STRAT + ! (swu, bmy, 6/9/05) + SCALEX = SCALE_A6 +#endif + + CASE ( 13 ) + SCALEX = SCALEDYN + UNIT = 'hPa' + CASE ( 14 ) + ! Bug fix: For GEOS-3, ALBEDO is an I-6 field, but + ! for GEOS-4, GEOS-5, GCAP, it is an A-3 field. + ! (lyj, phs, bmy, 10/7/08) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#else + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 +#endif + UNIT = 'unitless' + CASE ( 15 ) + SCALEX = SCALED + UNIT = 'm' + CASE ( 16 ) +! SCALEX = SCALE_A6 +#if defined( MERRA ) || defined( GEOS_FP ) + SCALEX = SCALE_A3 ! MERRA/GEOS-FP CLDTOPS 3-hr avg'd +#else + SCALEX = SCALE_A6 ! Otherwise CLDTOPS is 6-hr time avg'd +#endif + UNIT = 'levels' + CASE ( 17 ) +! SCALEX = SCALE_I6 + SCALEX = SCALE_ND67 + UNIT = 'hPa' + CASE ( 18 ) +! SCALEX = SCALE_I6 +#if defined( MERRA ) || defined( GEOS_FP ) + SCALEX = SCALE_A1 ! MERRA/GEOS-FP SLP is hourly +#else + SCALEX = SCALE_I6 ! Otherwise SLP is 6-h inst. +#endif + UNIT = 'hPa' + CASE ( 19 ) +! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'K' + CASE ( 20 ) +! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'W/m2' + CASE ( 21 ) +! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'W/m2' + CASE ( 22 ) + SCALEX = SCALE_A3 + UNIT = 'unitless' + CASE DEFAULT + CYCLE + END SELECT + + ARRAY(:,:,1) = AD67(:,:,N) / SCALEX + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND68: Grid box diagnostics +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) BXHEIGHT : Grid box height : m : SCALEDYN +! (2) AD : Air mass in grid box : kg : SCALEDYN +! (3) AVGW : Mixing ratio of water vapor : v/v : SCALEDYN +! (4) N(AIR) : Number density of air : m^-3 : SCALEDYN +! +! NOTES: +! (1) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2) Now replaced SCALE1 with SCALEDYN (bmy, 2/24/03) +! (3) Bug fix: replace ND68 with LD68 in call to BPCH2 (swu, bmy, 6/9/05) +!****************************************************************************** +! + IF ( ND68 > 0 ) THEN + CATEGORY = 'BXHGHT-$' + UNIT = '' + + DO M = 1, TMAX(68) + N = TINDEX(68,M) + IF ( N > PD68 ) CYCLE + NN = N + + DO L = 1, LD68 + ARRAY(:,:,L) = AD68(:,:,L,N) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD68, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD68) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND69: Grid Box Surface Areas +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) DXYP : Surface area of grid box : m^2 : SCALED = 1.0 +! +! NOTES: +! (1) Only print DXYP for the first timestep, as it is an invariant field. +! (2) We don't need to add TRCOFFSET to N. This is not a CTM tracer. +! (3) Now use the AD69 dynamically allocatable array (bmy, 2/17/00) +!****************************************************************************** +! + IF ( ND69 > 0 ) THEN + CATEGORY = 'DXYP' + UNIT = 'm2' + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, AD69(:,:,1) ) + + ! Set ND69 = 0 so we won't print it out again + ND69 = 0 + ENDIF + + ! Echo output + WRITE( 6, '(a)' ) ' - DIAG3: Diagnostics written to bpch!' + + ! Return to calling program + END SUBROUTINE DIAG3 diff --git a/code/diag3.f~ b/code/diag3.f~ new file mode 100644 index 0000000..d2b5063 --- /dev/null +++ b/code/diag3.f~ @@ -0,0 +1,3535 @@ +! $Id: diag3.f,v 1.3 2012/03/01 22:00:26 daven Exp $ + SUBROUTINE DIAG3 +! +!****************************************************************************** +! Subroutine DIAG3 prints out diagnostics to the BINARY format punch file +! (bmy, bey, mgs, rvm, 5/27/99, 12/15/08) +! +! NOTES: +! (40) Bug fix: Save levels 1:LD13 for ND13 diagnostic for diagnostic +! categories "SO2-AC-$" and "SO2-EV-$". Now reference F90 module +! "tracerid_mod.f". Now reference NUMDEP from "drydep_mod.f". +! Now save anthro, biofuel, biomass NH3 in ND13; also fixed ND13 +! tracer numbers. For ND13, change scale factor from SCALESRCE to 1. +! Now references "wetscav_mod.f". Now also save true tracer numbers +! for ND38 and ND39 diagnostic. Now also write out biomass SO2. +! Now convert ND01, ND02, ND44 diagnostics for Rn/Pb/Be from kg to +! kg/s here. (bmy, 1/24/03) +! (41) Now save out natural NH3 in ND13 as "NH3-NATU" (rjp, bmy, 3/23/03) +! (42) Now replace DXYP(JREF) by routine GET_AREA_M2, GET_XOFFSET, and +! GET_YOFFSET of "grid_mod.f". Now references "time_mod.f". +! DIAGb, DIAGe are now local variables. Now remove obsolete statements +! IF ( LBPNCH > 0 ). Removed SCALE1, replaced with SCALEDYN. +! (bmy, 2/24/03) +! (43) Added TSKIN, PARDF, PARDR, GWET to ND67 diagnostic. For GEOS-4/fvDAS, +! UWND, VWND, TMPU, SPHU are A-6 fields. Adjust the ND66 scale factors +! accordingly. Delete KZZ from ND66. Updated comments. (bmy, 6/23/03) +! (44) Bug fix: use LD68 instead of ND68 in DO-loop to avoid out-of-bounds +! error. (bec, bmy, 7/15/03) +! (45) Now print out NTRACE drydep fluxes for tagged Ox. Also tagged Ox +! now saves drydep in molec/cm2/s. Now print out Kr85 prod/loss in +! ND03. (bmy, 8/20/03) +! (46) Now use actual tracer number for ND37 diagnostic. (bmy, 1/21/04) +! (47) Now loop over the actual # of soluble tracers for ND17, ND18. +! (bmy, 3/19/04) +! (48) Now use the actual tracer # for ND17 and ND18 diagnostics. +! Rearrange ND44 code for clarity. (bmy, 3/23/04) +! (49) Added ND06 (dust aerosol) and ND07 (carbon aerosol) diagnostics. +! Now scale online dust optical depths by SCALECHEM in ND21 diagnostic. +! (rjp, tdf, bmy, 4/5/04) +! (50) Added ND08 (seasalt aerosol) diagnostic (rjp, bec, bmy, 4/20/04) +! (51) Now save out SO2 from ships (if LSHIPSO2=T) (bec, bmy, 5/20/04) +! (52) Added NVOC source diagnostics for ND07 (rjp, bmy, 7/13/04) +! (53) Now reference "logical_mod.f", "tracer_mod.f", and "diag_pl_mod.f". +! Bug fix in write to DMS_BIOG. (bmy, 7/20/04) +! (54) Comment out ND27 for GEOS-4. It isn't working 100% right. If you +! examine the flux at 200 hPa, you get the same info. (bmy, 10/15/04) +! (55) Added biofuel SO4 to the bpch file under ND13. Bug fix: replace ND68 +! with LD68 in call to BPCH2 (auvray, bmy, 11/17/04) +! (56) Now save ND03 mercury diagnostic arrays to bpch file. Also updated +! ND44 for tagged Hg tracers (eck, bmy, 12/14/04) +! (57) Now print out extra ND21 diagnostics for crystalline sulfur tracers. +! Also now save total oceanic mass of Hg0 and Hg2. Now call +! WRITE_DIAG03 from "diag03_mod.f" (bmy, 1/21/05) +! (58) Now call WRITE_DIAG41 from "diag41_mod.f" (bmy, 2/17/05) +! (59) Add P(SO4s) to row 8 of ND05 diagnostic. Also remove special tracer +! numbers for the ND67 diagnostic. Now do not save CLDMAS for ND67 +! for GEOS-4, since GEOS-4 convection uses different met fields. +! (bec, bmy, 5/3/05) +! (60) Bug fix in ND68 diagnostic: use LD68 instead of ND68 in call to BPCH2. +! Now modified for GEOS-5 and GCAP met fields. Remove references to +! CO-OH param simulation. Also remove references to TRCOFFSET since +! that is always zero now. Now call GET_HALFPOLAR from "bpch2_mod.f" +! to get the HALFPOLAR value for GEOS or GCAP grids. (swu, bmy, 6/24/05) +! (61) References ND04, WRITE_DIAG04 from "diag04_mod.f". Also now updated +! ND30 diagnostic for land/water/ice flags. Also remove reference +! to LWI array. (bmy, 8/18/05) +! (62) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (63) Added MBO as tracer #5 in ND46 diagnostic (tmf, bmy, 10/20/05) +! (64) Removed duplicate variable declarations. Now remove restriction on +! printing out cloud mass flux in GEOS-4 for the ND66 diagnostic. +! (bmy, 3/14/06) +! (65) References ND56, WRITE_DIAG56 from "diag56_mod.f" (ltm, bmy, 5/5/06) +! (66) Now remove TRCOFFSET; it's obsolete. References ND42, WRITE_DIAG42 +! from "diag42_mod.f" (dkh, bmy, 5/22/06) +! (67) Updated ND36 diagnostic for CH3I (bmy, 7/25/06) +! (68) Remove support for GEOS-1 and GEOS-STRAT met fields (bmy, 8/4/06) +! (69) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (70) Now write diag 54 (time in the troposphere) if asked for (phs, 9/22/06) +! (71) Now use new time counters for ND43 & ND45, Also now average between +! 0 and 24 UT for ND47. Bug fix in ND36. (phs, bmy, 3/5/07) +! (72) Bug fix in ND65: use 3-D counter array (phs, bmy, 3/6/07) +! (73) Bug fix in ND07: now save out IDTSOA4 tracer. Modifications for H2/HD +! diagnostics (ND10, ND27, ND44) (tmf, phs, bmy, 9/18/07) +! (74) Now save out true pressure at 3-D level edges for ND31. Change ND31 +! diagnostic category name to "PEDGE-$". Bug fix in ND28 diagnostic to +! allow you to print out individual biomass tracers w/o having to print +! all of them. (bmy, dkh, 1/24/08) +! (75) Bug fix: Now divide ALBEDO in ND67 by SCALE_I6 for GEOS-3 met, but +! by SCALE_A3 for all other met types (phs, bmy, 10/7/08) +! (76) Fix ND65, ND47, and ozone case in ND45. Now only ND45 depends +! on LD45 (phs, 11/17/08) +! (77) Bug fix: Select the right index of AD34 to write. Pick the right +! tracer field from AD22 if only a subset of tracers are requested +! to be printed out. (ccc, 12/15/08) +! (78) Added ND52 for gamma(HO2) (jaegle, 02/26/09) +! (79) Updated test on ship emissions flag for AD13 (phs, 3/3/09) +! (80) Add AD07_SOAGM for dicarbonyl SOA formation (tmf, 3/6/09) +! (81) Add output in AD22 for dicarbonyl photolysis J values (tmf, 3/6/09) +! (82) Add output in AD46 for biogenic C2H4 emissions (tmf, 3/6/09) +! (87) Add diagnostics 19, 58 and 60 for methane. (kjw, 8/18/09, adj32_023) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE BIOMASS_MOD, ONLY : BIOTRCE, NBIOMAX + USE BIOFUEL_MOD, ONLY : NBFTRACE, BFTRACE + USE DIAG_MOD, ONLY : AD01, AD02, AD05 + USE DIAG_MOD, ONLY : AD06, AD07, AD07_BC + USE DIAG_MOD, ONLY : AD07_SOAGM + USE DIAG_MOD, ONLY : AD07_OC, AD07_HC, AD08 + USE DIAG_MOD, ONLY : AD09, AD09_em, AD11 + USE DIAG_MOD, ONLY : AD12, AD13_DMS, AD13_SO2_ac + USE DIAG_MOD, ONLY : AD13_SO2_an, AD13_SO2_bb, AD13_SO2_bf + USE DIAG_MOD, ONLY : AD13_SO2_ev, AD13_SO2_nv, AD13_SO4_an + USE DIAG_MOD, ONLY : AD13_SO4_bf, AD13_SO2_sh, AD13_NH3_an + USE DIAG_MOD, ONLY : AD13_NH3_na, AD13_NH3_bb, AD13_NH3_bf + USE DIAG_MOD, ONLY : CONVFLUP, TURBFLUP, AD16 + USE DIAG_MOD, ONLY : CT16, AD17, CT17 + USE DIAG_MOD, ONLY : AD18, CT18, AD21 + USE DIAG_MOD, ONLY : AD21_cr, AD22, LTJV + USE DIAG_MOD, ONLY : CTJV, MASSFLEW, MASSFLNS + USE DIAG_MOD, ONLY : MASSFLUP, AD28, AD29 + USE DIAG_MOD, ONLY : AD30, AD31 + USE DIAG_MOD, ONLY : AD32_ac, AD32_an, AD32_bb + USE DIAG_MOD, ONLY : AD32_bf, AD32_fe, AD32_li + USE DIAG_MOD, ONLY : AD32_so, AD32_ub, AD33 + USE DIAG_MOD, ONLY : AD32_SHIP, AD32_SHIP_COUNT + USE DIAG_MOD, ONLY : AD34, AD35, AD36 + USE DIAG_MOD, ONLY : AD36_SHIP, AD36_SHIP_COUNT + USE DIAG_MOD, ONLY : AD37, AD38, AD39 + USE DIAG_MOD, ONLY : AD43, LTNO + USE DIAG_MOD, ONLY : CTNO, LTOH, CTOH + USE DIAG_MOD, ONLY : LTHO2, CTHO2, LTNO2 + USE DIAG_MOD, ONLY : CTNO2, LTNO3, CTNO3 + USE DIAG_MOD, ONLY : AD44, AD45, LTOTH + USE DIAG_MOD, ONLY : CTOTH, AD46, AD47 + USE DIAG_MOD, ONLY : AD52 + USE DIAG_MOD, ONLY : AD54, CTO3, CTO3_24h + USE DIAG_MOD, ONLY : AD19, AD58, AD60 + USE DIAG_MOD, ONLY : AD55, AD66, AD67 + USE DIAG_MOD, ONLY : AD68, AD69 + USE DIAG_MOD, ONLY : AD10, AD10em + USE DIAG03_MOD, ONLY : ND03, WRITE_DIAG03 + USE DIAG04_MOD, ONLY : ND04, WRITE_DIAG04 + USE DIAG41_MOD, ONLY : ND41, WRITE_DIAG41 + USE DIAG42_MOD, ONLY : ND42, WRITE_DIAG42 + USE DIAG56_MOD, ONLY : ND56, WRITE_DIAG56 +! diag59 added, (lz,10/11/10) + USE DIAG59_MOD, ONLY : ND59, WRITE_DIAG59 + USE DIAG_PL_MOD, ONLY : AD65 + USE DRYDEP_MOD, ONLY : NUMDEP, NTRAIND + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_AREA_M2, GET_XOFFSET, GET_YOFFSET + USE LOGICAL_MOD, ONLY : LCARB, LCRYST, LDUST + USE LOGICAL_MOD, ONLY : LSHIPSO2, LSOA, LSSALT + USE LOGICAL_MOD, ONLY : LEDGARSHIP, LARCSHIP, LEMEPSHIP + USE LOGICAL_MOD, ONLY : LICOADSSHIP, LRCPSHIP + USE TIME_MOD, ONLY : GET_DIAGb, GET_DIAGe, GET_CT_A3 + USE TIME_MOD, ONLY : GET_CT_A6, GET_CT_CHEM, GET_CT_CONV + USE TIME_MOD, ONLY : GET_CT_DYN, GET_CT_EMIS, GET_CT_I6 + USE TIME_MOD, ONLY : GET_CT_A1, GET_CT_I3 !! (geosfp, lzh,11/01/2014) + USE TRACER_MOD, ONLY : N_TRACERS, STT, TRACER_MW_G + USE TRACER_MOD, ONLY : TRACER_NAME + USE TRACER_MOD, ONLY : ITS_AN_AEROSOL_SIM + USE TRACER_MOD, ONLY : ITS_A_CH3I_SIM + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : ITS_A_H2HD_SIM + USE TRACER_MOD, ONLY : ITS_A_MERCURY_SIM + USE TRACER_MOD, ONLY : ITS_A_RnPbBe_SIM + USE TRACER_MOD, ONLY : ITS_A_TAGOX_SIM + USE TRACERID_MOD, ONLY : IDTPB, IDTDST1, IDTDST2 + USE TRACERID_MOD, ONLY : IDTDST3, IDTDST4, IDTBCPI + USE TRACERID_MOD, ONLY : IDTOCPI, IDTALPH, IDTLIMO + USE TRACERID_MOD, ONLY : IDTSOA1, IDTSOA2, IDTSOA3 + USE TRACERID_MOD, ONLY : IDTSALA, IDTSALC, IDTDMS + USE TRACERID_MOD, ONLY : IDTSO2, IDTSO4, IDTNH3 + USE TRACERID_MOD, ONLY : IDTOX, IDTNOX, IDTHNO3 + USE TRACERID_MOD, ONLY : IDTISOP, IDTACET, IDTPRPE + USE TRACERID_MOD, ONLY : IDTH2, IDTHD + USE TRACERID_MOD, ONLY : NEMANTHRO , IDTSOA4 + USE TRACERID_MOD, ONLY : IDTSOAG, IDTSOAM + USE TRACERID_MOD, ONLY : IDTMONX, IDTMBO, IDTC2H4 + USE WETSCAV_MOD, ONLY : GET_WETDEP_NSOL + USE WETSCAV_MOD, ONLY : GET_WETDEP_IDWETD + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN" ! IFLX, LPAUSE +# include "CMN_DIAG" ! Diagnostic switches & arrays +# include "CMN_O3" ! FMOL, XNUMOL +# include "comode.h" ! IDEMS + + ! Local variables + INTEGER :: I, IREF, J, JREF, L, M, MM, MMB, LMAX + INTEGER :: N, NN, NMAX, NTEST + INTEGER :: IE, IN, IS, IW, ITEMP(3) + REAL*8 :: SCALE_TMP(IIPAR,JJPAR) + REAL*8 :: SCALE_I6, SCALE_A6, SCALE_A3, SCALED + + !! (geosfp, lzh, 11/01/2014) + REAL*8 :: SCALE_I3, SCALE_A1 + REAL*8 :: SCALE_ND66, SCALE_ND67 + + REAL*8 :: SCALEDYN, SCALECONV, SCALESRCE, SCALECHEM + REAL*8 :: SCALEX, SECONDS, PMASS, PRESSX + REAL*8 :: FDTT, AREA_M2, DIAGb, DIAGe + + ! For binary punch file, version 2.0 + CHARACTER (LEN=40) :: CATEGORY + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR+1) + REAL*4 :: LONRES, LATRES + INTEGER :: IFIRST, JFIRST, LFIRST + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180 = 1 + CHARACTER (LEN=20) :: MODELNAME + CHARACTER (LEN=40) :: UNIT + CHARACTER (LEN=40) :: RESERVED = '' +! +!****************************************************************************** +! DIAG3 begins here! +! +! Define scale factors for division. +! Add a small number (e.g. 1d-32) to prevent division by zero errors. +!****************************************************************************** +! + ! Now use counter variables from "time_mod.f" (bmy, 3/27/03) + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + SECONDS = ( DIAGe - DIAGb ) * 3600d0 + SCALED = 1d0 + SCALEDYN = DBLE( GET_CT_DYN() ) + 1d-32 + SCALECONV = DBLE( GET_CT_CONV() ) + 1d-32 + SCALESRCE = DBLE( GET_CT_EMIS() ) + 1d-32 + SCALECHEM = DBLE( GET_CT_CHEM() ) + 1d-32 + SCALE_A3 = DBLE( GET_CT_A3() ) + 1d-32 + SCALE_A6 = DBLE( GET_CT_A6() ) + 1d-32 + SCALE_I6 = DBLE( GET_CT_I6() ) + 1d-32 + !! (lzh, 11/01/2014) geosfp + SCALE_A1 = DBLE( GET_CT_A1() ) + 1d-32 + SCALE_I3 = DBLE( GET_CT_I3() ) + 1d-32 +! +!****************************************************************************** +! Setup for binary punch file: +! +! IFIRST, JFIRST, LFIRST = I, J, L indices of the starting grid box +! LONRES = DISIZE, cast to REAL*4 +! LATRES = DJSIZE, cast to REAL*4 +!****************************************************************************** +! + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LFIRST = 1 + LONRES = DISIZE + LATRES = DJSIZE + + ! Get the proper model name and HALFPOLAR setting for the bpch file + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() +! +!****************************************************************************** +! ND01: Rn, Pb, Be emissions (Category: "RN--SRCE") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) Rn222 : Emissions of 222Rn : kg/s : SCALESRCE +! (2) Pb210 : Emissions of 210Pb : kg/s : SCALECHEM +! (3) Be7 : Emissions of 7Be : kg/s : SCALESRCE +! +! and Rn, Pb, Be lost to radioactive decay (Category: "RN-DECAY") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) Rn222 : Loss of 222Rn : kg/s : SCALECHEM +! (2) Pb210 : Loss of 210Pb : kg/s : SCALECHEM +! (3) Be7 : Loss of 7Be : kg/s : SCALECHEM +!****************************************************************************** +! + IF ( ND01 > 0 ) THEN + CATEGORY = 'RN--SRCE' + UNIT = 'kg/s' + + DO M = 1, TMAX(1) + N = TINDEX(1,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! Pb "emission" comes from chemical decay of Rn, which happens + ! in the chemistry routine, so use SCALECHEM (bmy, 1/27/03) + IF ( N == IDTPB ) THEN + SCALEX = SCALECHEM + ELSE + SCALEX = SCALESRCE + ENDIF + + ! Divide by # of emission timesteps + DO L = 1, LD01 + ARRAY(:,:,L) = AD01(:,:,L,N) / SCALEX + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD01, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD01) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND02: Rn, Pb, Be lost to radioactive decay (Category: "RN-DECAY") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) Rn222 : Loss of 222Rn : kg/s : SCALECHEM +! (2) Pb210 : Loss of 210Pb : kg/s : SCALECHEM +! (3) Be7 : Loss of 7Be : kg/s : SCALECHEM +!****************************************************************************** +! + IF ( ND02 > 0 ) THEN + CATEGORY = 'RN-DECAY' + UNIT = 'kg/s' + + DO M = 1, TMAX(2) + N = TINDEX(2,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! Divide by # of chemistry timesteps + DO L = 1, LD02 + ARRAY(:,:,L) = AD02(:,:,L,N) / SCALECHEM + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD02, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD02) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND03: Diagnostics from Hg0/Hg2/HgP offline simulation (eck, bmy, 1/20/05) +!****************************************************************************** +! + IF ( ND03 > 0 ) CALL WRITE_DIAG03 +! +!****************************************************************************** +! ND04: Diagnostics from CO2 simulation (pns, bmy, 7/26/05) +!****************************************************************************** +! + IF ( ND04 > 0 ) CALL WRITE_DIAG04 +! +!****************************************************************************** +! ND05: Production/Loss for coupled fullchem/aerosol runs (NSRCX==3) or +! offline sulfate chemistry runs (NSRCX==10). +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1 ) SO2dms : P(SO2) from DMS + OH : kg S : SCALEX +! (2 ) SO2no3 : P(SO2) from DMS + NO3 : kg S : SCALEX +! (3 ) SO2 : Total P(SO2) : kg S : SCALEX +! (4 ) MSAdms : P(MSA) from DMS : kg S : SCALEX +! (5 ) SO4gas : P(SO4) gas phase : kg S : SCALEX +! (6 ) SO4aq : P(SO4) aqueous phase : kg S : SCALEX +! (7 ) PSO4 : Total P(SO4) : kg S : SCALEX +! (8 ) PSO4s : Total P(SO4 from seasalt) : kg S : SCALEX +! (9 ) LOH : L(OH) by DMS : kg OH : SCALEX +! (10) LNO3 : L(NO3) by DMS : kg NO3 : SCALEX +!****************************************************************************** +! + IF ( ND05 > 0 ) THEN + CATEGORY = 'PL-SUL=$' + + DO M = 1, TMAX(5) + N = TINDEX(5,M) + + ! Tracers 9, 10 are OH, NO3 + ! and are in [kg] instead of [kg S] + IF ( N < 9 ) THEN + UNIT = 'kg S' + ELSE + UNIT = 'kg' + ENDIF + + NN = N + SCALEX = 1.d0 + + DO L = 1, LD05 + ARRAY(:,:,L) = AD05(:,:,L,N) / SCALEX + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD05, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD05) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND06: Dust aerosol emissions +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) DUST : Soil dust (4 different classes) : kg : 1 +!****************************************************************************** +! + IF ( ND06 > 0 .and. LDUST ) THEN + + ! Category & unit string + UNIT = 'kg' + CATEGORY = 'DUSTSRCE' + + ! Loop over # of dust bins + DO N = 1, NDSTBIN + + ! At present we have 4 dust bins + IF ( N == 1 ) NN = IDTDST1 + IF ( N == 2 ) NN = IDTDST2 + IF ( N == 3 ) NN = IDTDST3 + IF ( N == 4 ) NN = IDTDST4 + + ! Save dust into ARRAY + ARRAY(:,:,1) = AD06(:,:,N) + + ! Write to BPCH file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND07: Emissions of BC and OC aerosols +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) Carbon : Carbonaceous aerosols : kg : 1 +!****************************************************************************** +! + IF ( ND07 > 0 .and. LCARB ) THEN + + ! Unit + UNIT = 'kg' + + !------------------- + ! BC ANTHRO source + !------------------- + CATEGORY = 'BC-ANTH' + N = IDTBCPI + ARRAY(:,:,1) = AD07(:,:,1) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------- + ! BC BIOMASS source + !------------------- + CATEGORY = 'BC-BIOB' + N = IDTBCPI + ARRAY(:,:,1) = AD07(:,:,2) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------- + ! BC BIOFUEL source + !------------------- + CATEGORY = 'BC-BIOF' + N = IDTBCPI + ARRAY(:,:,1) = AD07(:,:,3) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! H-philic BC from H-phobic BC + !------------------------------ + CATEGORY = 'PL-BC=$' + N = IDTBCPI + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_BC(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + !------------------------------ + ! OC ANTHRO source + !------------------------------ + CATEGORY = 'OC-ANTH' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,4) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! OC BIOMASS source + !------------------------------ + CATEGORY = 'OC-BIOB' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,5) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! OC BIOFUEL source + !------------------------------ + CATEGORY = 'OC-BIOF' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,6) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! OC BIOGENIC source + !------------------------------ + CATEGORY = 'OC-BIOG' + N = IDTOCPI + ARRAY(:,:,1) = AD07(:,:,7) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !------------------------------ + ! H-philic OC from H-phobic OC + !------------------------------ + CATEGORY = 'PL-OC=$' + N = IDTOCPI + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_OC(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + ! Only save extra SOA diagnostics if LSOA=T + IF ( LSOA ) THEN + + !------------------------------ + ! NVOC SOURCE diagnostics + !------------------------------ + DO N = 8, 12 + + SELECT CASE ( N ) + + ! ALPH + CASE ( 8 ) + CATEGORY = 'OC-ALPH' + NN = IDTALPH + + ! LIMO + CASE ( 9 ) + CATEGORY = 'OC-LIMO' + NN = IDTLIMO + + ! TERP + CASE ( 10 ) + CATEGORY = 'OC-TERP' + NN = IDTLIMO + 1 + + ! ALCO + CASE ( 11 ) + CATEGORY = 'OC-ALCO' + NN = IDTLIMO + 2 + + ! SESQ + CASE ( 12 ) + CATEGORY = 'OC-SESQ' + NN = IDTLIMO + 3 + + END SELECT + + ARRAY(:,:,1) = AD07(:,:,N) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + + !----------------------------------------------- + ! SOA Production from NVOC oxidation [kg] + ! 1:ALPH+LIMO+TERP, 2:ALCO, 3:SESQ, 4:ISOP + !----------------------------------------------- + CATEGORY = 'PL-OC=$' + + DO N = 1, 4 + + IF ( N == 1 ) NN = IDTSOA1 + IF ( N == 2 ) NN = IDTSOA2 + IF ( N == 3 ) NN = IDTSOA3 + IF ( N == 4 ) NN = IDTSOA4 ! (tmf, bmy, 3/20/07) + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_HC(:,:,L,N) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + ENDDO + + !----------------------------------------------- + ! SOA Production from GLYX and MGLY [kg] + ! 1: SOAG <- GLYX; 2: SOAM <- MGLY IN AEROSOL + ! 3: SOAG <- GLYX; 4: SOAM <- MGLY INCLOUD + ! (tmf, 1/7/09) + ! Test if SOAG and SOAM tracers are valid before + ! saving them. (ccc, 1/7/09) + !----------------------------------------------- + IF ( IDTSOAG /= 0 .AND. IDTSOAM /= 0 ) THEN + CATEGORY = 'SOAGM=$' + + DO N = 1, 4 + + IF ( N == 1 ) NN = 91 + IF ( N == 2 ) NN = 92 + IF ( N == 3 ) NN = 93 + IF ( N == 4 ) NN = 94 + + DO L = 1, LD07 + ARRAY(:,:,L) = AD07_SOAGM(:,:,L,N) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD07, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD07) ) + + ENDDO + ENDIF + ENDIF + ENDIF +! +!****************************************************************************** +! ND08: Sea salt aerosol emissions +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) SALA : Accumulation mode seasalt : kg : 1 +! (2) SALC : Coarse mode seasalt : kg : 1 +!****************************************************************************** +! + IF ( ND08 > 0 .and. LSSALT ) THEN + + ! Category & unit string + UNIT = 'kg' + CATEGORY = 'SALTSRCE' + + ! Loop over seasalt tracers + DO N = 1, 2 + + ! At present we have 2 seasalts + IF ( N == 1 ) NN = IDTSALA + IF ( N == 2 ) NN = IDTSALC + + ! Save seasalts into ARRAY + ARRAY(:,:,1) = AD08(:,:,N) + + ! Write to BPCH file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND09: HCN/CH3CN sources/sinks (Categories: "HCN-PL-$", "HCN-SRCE") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1:N) sink : Loss of tagged tracer to OH : kg +! (N+1) HCNbb : HCN from biomass burning : molec/cm2/s : SCALESRCE +! (N+2) CH3CNbb : CH3CN from biomass burning : molec/cm2/s : SCALESRCE +! (N+3) HCNdf : HCN from domestic fossil fuel : molec/cm2/s : SCALESRCE +! (N+4) CH3CNdf : CH3CN from domestic fossil fuel : molec/cm2/s : SCALESRCE +! (N+5) HCNoc : HCN loss to ocean uptake : molec/cm2/s : SCALECHEM +! (N+6) CH3CNoc : CH3CN loss to ocean uptake : molec/cm2/s : SCALECHEM +!****************************************************************************** +! + IF ( ND09 > 0 ) THEN + + ! Binary punch file + DO M = 1, TMAX(9) + N = TINDEX(9,M) + IF ( N > N_TRACERS+6 ) CYCLE + + ! Test tracer number + IF ( N <= N_TRACERS ) THEN + + !--------------------------- + ! HCN/CH3CN sinks + !--------------------------- + CATEGORY = 'HCN-PL-$' + UNIT = 'kg' + NN = N + + DO L = 1, LD09 + ARRAY(:,:,L) = AD09(:,:,L,N) + ENDDO + + ! Save to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD09, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD09) ) + + ELSE + + !--------------------------- + ! HCN/CH3CN sources + !--------------------------- + CATEGORY = 'HCN-SRCE' + UNIT = 'molec/cm2/s' + NN = N - N_TRACERS + + ! Pick proper scale + IF ( NN <= 4 ) THEN + SCALEX = SCALESRCE + ELSE + SCALEX = SCALECHEM + ENDIF + + ! Scale data + ARRAY(:,:,1) = AD09_em(:,:,NN) / SCALEX + + ! Write to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND10: H2/HD source diagnostics, prod and loss (phs, 9/18/07) +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) H2oh : H2 Loss by OH : mol/cm3/s : SCALECHEM +! (2 ) H2iso : H2 Prod from isoprene : mol/cm3/s : SCALECHEM +! (3 ) H2ch4 : H2 Prod from CH4 : mol/cm3/s : SCALECHEM +! (4 ) H2ch3oh: H2 Prod from CH3OH : mol/cm3/s : SCALECHEM +! (5 ) H2mono : H2 Prod from monoprene : mol/cm3/s : SCALECHEM +! (6 ) H2acet : H2 Prod from acetone : mol/cm3/s : SCALECHEM +! (7 ) H2o1d : H2 Loss by strat O1D : mol/cm3/s : SCALECHEM +! +! (8 ) HDoh : H2 Loss by OH : mol/cm3/s : SCALECHEM +! (9 ) HDiso : H2 Prod from isoprene : mol/cm3/s : SCALECHEM +! (10) HDch4 : H2 Prod from CH4 : mol/cm3/s : SCALECHEM +! (11) HDch3oh: H2 Prod from CH3OH : mol/cm3/s : SCALECHEM +! (12) HDmono : H2 Prod from monoprene : mol/cm3/s : SCALECHEM +! (13) HDacet : H2 Prod from acetone : mol/cm3/s : SCALECHEM +! (14) HDo1d : H2 Loss by strat O1D : mol/cm3/s : SCALECHEM +! +! (15) ALPHA : OH k rates kHD/kH2 ratio: unitless : SCALECHEM +! +! (16) H2anth : H2 from Anthro Sources : mol/cm2/s : SCALESRCE +! (17) H2bb : H2 from Biomass Burning : mol/cm2/s : SCALESRCE +! (18) H2bf : H2 from Biofuel Burning : mol/cm2/s : SCALESRCE +! (19) H2ocean: H2 from Ocean : mol/cm2/s : SCALESRCE +! (19) HDocean: HD from Ocean : mol/cm2/s : SCALESRCE +! +! NOTES: +! (1 ) Non zero only if ND10>0 and it is a H2/HD offline simulation +! (2 ) +!****************************************************************************** +! + IF ( ND10 > 0 ) THEN + DO M = 1, TMAX(10) + N = TINDEX(10,M) + IF ( N > PD10 ) CYCLE + + ! Test tracer number (NEMISS=5, see "ndxx_setup.f" ) + IF ( N <= ( PD10 - 5 ) ) THEN + + !--------------------------- + ! H2/HD Prod-Loss + !--------------------------- + CATEGORY = 'PL-H2HD-' + UNIT = 'molec/cm3/s' + NN = N + + DO L = 1, LD10 + ARRAY(:,:,L) = AD10(:,:,L,N) / SCALECHEM + ENDDO + + ! Save to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD10, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD10) ) + + ELSE + + !--------------------------- + ! H2/HD sources + !--------------------------- + CATEGORY = 'H2HD-SRC' + UNIT = 'molec/cm2/s' + NN = N - 15 + + ! Scale data + ARRAY(:,:,1) = AD10em(:,:,NN) / SCALESRCE + + ! Write to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND11: Acetone source & sink diagnostic (Category: "ACETSRCE") +! +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1) ACETmo : Acetone source from MONOTERPENES : at C/cm2/s : SCALESRCE +! (2) ACETmb : Acetone source from METHYL BUTENOL : at C/cm2/s : SCALESRCE +! (3) ACETbg : Acetone source from DIRECT EMISSION: at C/cm2/s : SCALESRCE +! (4) ACETdl : Acetone source from DRY LEAF MATTER: at C/cm2/s : SCALESRCE +! (5) ACETgr : Acetone source from GRASSLANDS : at C/cm2/s : SCALESRCE +! (6) ACETop : Acetone source from OCEANS : at C/cm2/s : SCALESRCE +! (7) ACETol : Acetone sink from OCEANS : at C/cm2/s : SCALECHEM +!****************************************************************************** +! + IF ( ND11 > 0 ) THEN + CATEGORY = 'ACETSRCE' + UNIT = 'atoms C/cm2/s' + + DO M = 1, TMAX(11) + N = TINDEX(11,M) + IF ( N > PD11 ) CYCLE + NN = N + + ! Acetone ocean sink is on the chemistry timestep + ! but acetone sources are all on the emission timestep + IF ( N == 7 ) THEN + SCALEX = SCALECHEM + ELSE + SCALEX = SCALESRCE + ENDIF + + ARRAY(:,:,1) = AD11(:,:,N) / SCALEX + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND12: distribution of suface emissions in the boundry layer: [fraction] +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) EMDIS-BL : Fraction of BL occupied by level L : unitless : SCALECHEM +!****************************************************************************** +! + IF ( ND12 > 0 ) THEN + UNIT = 'unitless' + CATEGORY = 'EMDIS-BL' + + DO L = 1, LD12 + ARRAY(:,:,L) = AD12(:,:,L) / SCALECHEM + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLTROP, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD12) ) + ENDIF +! +!****************************************************************************** +! ND13: Sulfur emissions (for DMS/SO2/SO4/MSA/NH3/NH4/NIT chemistry) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) DMS-BIOG : Biogenic DMS emission : kg S : 1 +! (2 ) SO2-AC-$ : Aircraft SO2 emission : kg S : 1 +! (3 ) SO2-AN-$ : Anthropogenic SO2 emission : kg S : 1 +! (4 ) SO2-BIOB : Biomass SO2 emission : kg S : 1 +! (5 ) SO2-BIOF : Biofuel SO2 emission : kg S : 1 +! (6 ) SO2-NV-$ : Non-eruptive volcano SO2 em. : kg S : 1 +! (7 ) SO2-EV-$ : Eruptive volcano SO2 emissions : kg S : 1 +! (8 ) SO4-AN-$ : Anthropogenic SO4 emission : kg S : 1 +! (9 ) NH3-ANTH : Anthropogenic NH3 emission : kg NH3 : 1 +! (10) NH3-NATU : Natural source NH3 emission : kg NH3 : 1 +! (11) NH3-BIOB : Biomass burning NH3 emission : kg NH3 : 1 +! (12) NH3-BIOF : Biofuel burning NH3 emission : kg NH3 : 1 +!****************************************************************************** +! + IF ( ND13 > 0 .and. + & ( ITS_A_FULLCHEM_SIM() .or. ITS_AN_AEROSOL_SIM() ) ) THEN + UNIT = 'kg S' + + !============================================================== + ! Biogenic DMS + !============================================================== + CATEGORY = 'DMS-BIOG' + ARRAY(:,:,1) = AD13_DMS(:,:) + N = IDTDMS + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Aircraft SO2 + !============================================================== + CATEGORY = 'SO2-AC-$' + N = IDTSO2 + + DO L = 1, LD13 + ARRAY(:,:,L) = AD13_SO2_ac(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD13, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD13) ) + + !============================================================== + ! Anthropogenic SO2 + !============================================================== + CATEGORY = 'SO2-AN-$' + N = IDTSO2 + + DO L = 1, NOXEXTENT + ARRAY(:,:,L) = AD13_SO2_an(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 2, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:2) ) + + + + + !============================================================== + ! Biomass SO2 + !============================================================== + CATEGORY = 'SO2-BIOB' + ARRAY(:,:,1) = AD13_SO2_bb(:,:) + N = IDTSO2 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + + !============================================================== + ! Biofuel SO2 + !============================================================== + CATEGORY = 'SO2-BIOF' + ARRAY(:,:,1) = AD13_SO2_bf(:,:) + N = IDTSO2 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Eruptive volcano SO2 + !============================================================== + CATEGORY = 'SO2-EV-$' + N = IDTSO2 + + DO L = 1, LD13 + ARRAY(:,:,L) = AD13_SO2_ev(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD13, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD13) ) + + !============================================================== + ! Non-eruptive volcano SO2 + !============================================================== + CATEGORY = 'SO2-NV-$' + N = IDTSO2 + + DO L = 1, LD13 + ARRAY(:,:,L) = AD13_SO2_nv(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD13, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD13) ) + + + !============================================================== + ! Ship SO2 bec (5/17/04) + ! New test on logical flag (phs, 3/2/09) + !============================================================== + ! Add ICOADSSHIP (cklee, 6/30/09) + ! Add RCP + IF ( LSHIPSO2 .OR. LEDGARSHIP .OR. LARCSHIP .OR. + $ LEMEPSHIP .OR. LICOADSSHIP .OR. LRCPSHIP ) THEN + + CATEGORY = 'SO2-SHIP' + ARRAY(:,:,1) = AD13_SO2_sh(:,:) + N = IDTSO2 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF + + !============================================================== + ! Anthropogenic SO4 + !============================================================== + CATEGORY = 'SO4-AN-$' + N = IDTSO4 + + ! Fix loop to make compatible with NEI2008 + ! DO L = 1, NOXEXTENT + DO L = 1, 2 + ARRAY(:,:,L) = AD13_SO4_an(:,:,L) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 2, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:2) ) + + !============================================================== + ! Biofuel SO4 + !============================================================== + CATEGORY = 'SO4-BIOF' + ARRAY(:,:,1) = AD13_SO4_bf(:,:) + N = IDTSO4 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + + !============================================================== + ! Anthropogenic NH3 + !============================================================== + UNIT = 'kg' + CATEGORY = 'NH3-ANTH' + ARRAY(:,:,1) = AD13_NH3_an(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Natural source NH3 + !============================================================== + CATEGORY = 'NH3-NATU' + ARRAY(:,:,1) = AD13_NH3_na(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Biomass NH3 + !============================================================== + CATEGORY = 'NH3-BIOB' + ARRAY(:,:,1) = AD13_NH3_bb(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Biofuel NH3 + !============================================================== + CATEGORY = 'NH3-BIOF' + ARRAY(:,:,1) = AD13_NH3_bf(:,:) + N = IDTNH3 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF +! +!****************************************************************************** +! ND14: Upward mass flux from wet convection (NFCLDMX) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) CONVFLUP : Upward mass flux from wet conv : kg/s : SCALECONV +! +! NOTES: +! (1) Bug fix -- only write LD14 levels to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND14 > 0 ) THEN + CATEGORY = 'CV-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(14) + N = TINDEX(14,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1:LD14) = CONVFLUP(:,:,1:LD14,N) / SCALECONV + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD14, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD14) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND15: Upward mass flux from boundary layer mixing (TURBDAY) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) TURBFLUX : Upward mass flux from BL mixing : kg/s : SCALECONV +! +! NOTES: +! (1) Bug fix -- only write LD15 levels to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND15 > 0 ) THEN + CATEGORY = 'TURBMC-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(15) + N = TINDEX(15,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1:LD15) = TURBFLUP(:,:,1:LD15,N) / SCALECONV + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD15, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD15) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND16: Fraction of grid box experiencing LS or convective precipitation +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WD-FLS-$ : LS precip fraction : unitless : CT16(:,:,:,1) +! (2) WD-FCV-$ : Convective precip fraction : unitless : CT16(:,:,:,2) +!****************************************************************************** +! + IF ( ND16 > 0 ) THEN + + ! Large-scale area of precipitation + CATEGORY = 'WD-FRC-$' + UNIT = 'unitless' + + DO M = 1, TMAX(16) + N = TINDEX(16,M) + IF ( N > PD16 ) CYCLE + NN = N + + DO L = 1, LD16 + SCALE_TMP(:,:) = FLOAT( CT16(:,:,L,N) ) + 1d-20 + ARRAY(:,:,L) = AD16(:,:,L,N) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD16, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD16) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND17: Fraction of tracer lost rainout in LS and convective precip +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WD-LSR-$ : Rainout fraction/LS Precip : unitless : CT17(:,:,:,1) +! (2) WD-CVR-$ : Rainout fraction/conv precip : unitless : CT17(:,:,:,2) +! +! NOTES: +! (1) Now loop over all soluble tracers (bmy, 3/19/04) +! (2) Now use actual tracer number (bmy, 3/23/04) +!****************************************************************************** +! + IF ( ND17 > 0 ) THEN + UNIT = 'unitless' + + ! Get max # of soluble tracers for this simulation + NMAX = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, NMAX + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(17) ) + MMB = TINDEX(17,MM) + MM = MM + 1 + ENDDO + + IF ( MMB /= NN ) CYCLE + + ! Large-scale rainout/washout fractions + CATEGORY = 'WD-LSR-$' + + DO L = 1, LD17 + SCALE_TMP(:,:) = FLOAT( CT17(:,:,L,1) ) + 1d-20 + ARRAY(:,:,L) = AD17(:,:,L,N,1) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD17, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD17) ) + + + ! Convective rainout/washout fractions + CATEGORY = 'WD-CVR-$' + + DO L = 1, LD17 + SCALE_TMP(:,:) = FLOAT( CT17(:,:,L,2) ) + 1d-20 + ARRAY(:,:,L) = AD17(:,:,L,N,2) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD17, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD17) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND18: Fraction of tracer lost to washout in LS or convective precip +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WD-LSW-$ : Washout fraction/LS precip : unitless : CT18(:,:,:,1) +! (2) WD-CVW-$ : Washout fraction/conv precip : unitless : CT18(:,:,:,2) +! +! NOTES: +! (1) Now loop over all soluble tracers (bmy, 3/19/04) +! (2) Now use actual tracer number (bmy, 3/23/04) +!****************************************************************************** +! + IF ( ND18 > 0 ) THEN + UNIT = 'unitless' + + ! Get max # of soluble tracers for this simulation + NMAX = GET_WETDEP_NSOL() + + DO N = 1, NMAX + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(18) ) + MMB = TINDEX(18,MM) + MM = MM + 1 + ENDDO + + IF ( MMB /= NN ) CYCLE + + ! Large-scale rainout/washout fractions + CATEGORY = 'WD-LSW-$' + + DO L = 1, LD18 + SCALE_TMP(:,:) = FLOAT( CT18(:,:,L,1) ) + 1d-20 + ARRAY(:,:,L) = AD18(:,:,L,N,1) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD18, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD18) ) + + + ! Convective washout fractions + CATEGORY = 'WD-CVW-$' + + DO L = 1, LD18 + SCALE_TMP(:,:) = FLOAT( CT18(:,:,L,2) ) + 1d-20 + ARRAY(:,:,L) = AD18(:,:,L,N,2) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD18, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD18) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND19: CH4 loss +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) CH4-LOSS : CH4 removing by OH : kg CH4 : 1 +!****************************************************************************** +! + IF ( ND19 > 0 ) THEN + + UNIT = 'kg' + + !============================================================== + ! CH4 Loss + !============================================================== + CATEGORY = 'CH4-LOSS' + N = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLPAR, IFIRST, + & JFIRST, LFIRST, AD19(:,:,:) ) + + ENDIF +! +!****************************************************************************** +! ND21: Optical depth diagnostics +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) OPTD Cloud Optical Depth : unitless : SCALECHEM +! (2 ) CLMO Max Overlap Cloud Fraction (GEOS1,S): unitless : SCALECHEM +! or CLDF 3-D Total Cloud fraction (GEOS3,4): unitless : SCALECHEM +! (3 ) CLRO Random Overlap Cloud Fraction : unitless : SCALECHEM +! (4 ) OPD Mineral Dust Optical Depth (400 nm) : unitless : none +! (5 ) SD Mineral Dust Surface Area : cm2/cm3 : none +! (6 ) OPSO4 Sulfate Optical Depth (400 nm) : unitless : SCALECHEM +! (7 ) HGSO4 Hygroscopic growth of SO4 : unitless : SCALECHEM +! (8 ) SSO4 Sulfate Surface Area : cm2/cm3 : SCALECHEM +! (9 ) OPBC Black Carbon Optical Depth (400 nm) : unitless : SCALECHEM +! (10) HGBC Hygroscopic growth of BC : unitless : SCALECHEM +! (11) SBC Black Carbon Surface Area : cm2/cm3 : SCALECHEM +! (12) OPOC Organic C Optical Depth (400 nm) : unitless : SCALECHEM +! (13) HGOC Hygroscopic growth of OC : unitless : SCALECHEM +! (14) SOC Organic Carbon Surface Area : cm2/cm3 : SCALECHEM +! (15) OPSSa Sea Salt (accum) Opt Depth (400 nm) : unitless : SCALECHEM +! (16) HGSSa Hygroscopic growth of SSa : unitless : SCALECHEM +! (17) SSSa Sea Salt (accum) Surface Area : cm2/cm3 : SCALECHEM +! (18) OPSSc Sea Salt (coarse) Opt Depth(400 nm) : unitless : SCALECHEM +! (19) HGSSc Hygroscopic growth of SSc : unitless : SCALECHEM +! (20) SSSc Sea Salt (coarse) Surface Area : cm2/cm3 : SCALECHEM +! +! NOTES: +! (1 ) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2 ) Don't divide monthly mean AOD by SCALECHEM (rvm, bmy, 12/8/00) +! (3 ) Use SCALE_A6 for GEOS-2, GEOS-3 fields, since optical depths are read +! in from disk every 6 hours. Use SCALECHEM for GEOS-1, GEOS-STRAT +! fields, since optical depths are computed every chemistry timestep. +! Use SCALEDYN for CO-OH parameterization simulation. (bmy, 4/23/01) +! (4 ) Now GEOS-2, GEOS-3 use SCALECHEM for ND21 (bmy, 8/13/01) +! (5 ) Updated tracers for new aerosols from Mian Chin (rvm, bmy, 3/1/02) +! (6 ) Now scale online dust fields by SCALECHEM (bmy, 4/9/04) +! (7 ) Also save out extra diagnostics for cryst sulfur tracers (bmy, 1/5/05) +!****************************************************************************** +! + IF ( ND21 > 0 ) THEN + CATEGORY = 'OD-MAP-$' + + ! ND21 is updated every chem timestep + SCALEX = SCALECHEM + + DO M = 1, TMAX(21) + N = TINDEX(21,M) + IF ( N > PD21 ) CYCLE + NN = N + + ! Select proper unit string (cf list above) + SELECT CASE( N ) + CASE ( 5, 8, 11, 14, 17, 20 ) + UNIT = 'cm2/cm3' + CASE DEFAULT + UNIT = 'unitless' + END SELECT + + IF ( N > 3 .AND. N < 6 ) THEN + + ! Online or offline dust fields? + IF ( LDUST ) THEN + + ! If LDUST=T, then we are using online dust fields, + ! so we must scale by the chemistry timestep. (4/9/04) + ARRAY(:,:,1:LD21) = AD21(:,:,1:LD21,N) / SCALEX + + ELSE + + ! If LDUST=F, then we are using offline monthly-mean + ! dust fields. These don't have to be scaled by + ! the chemistry timestep. (bmy, 4/9/04) + ARRAY(:,:,1:LD21) = AD21(:,:,1:LD21,N) + + ENDIF + + ELSE + + ! For all other types of optical depths, we need + ! to scale by the chemistry timestep (bmy, 4/9/04) + ARRAY(:,:,1:LD21) = AD21(:,:,1:LD21,N) / SCALEX + + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD21, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD21) ) + ENDDO + + !============================================================== + ! If we are using the crystalline sulfate tracers (LCRYST=T), + ! then also save out the extra ND21 diagnostics: + ! + ! #21: Opt depth for HYSTERESIS CASE [unitless] + ! #22: Opt depth for SOLID CASE [unitless] + ! #23: Opt depth for LIQUID CASE [unitless] + ! #24: Opt depth HYSTERESIS - Opt depth SOLID [unitless] + ! #25: Opt depth HYSTERESIS - Opt depth LIQUID [unitless] + ! #26: Radiative forcing [W/m2 ] + !============================================================== + IF ( LCRYST ) THEN + + ! Category + CATEGORY = 'OD-MAP-$' + + ! Loop over extra + DO N = 1, 6 + + ! Define unit string + IF ( N == 6 ) THEN + UNIT = 'W/m2' + ELSE + UNIT = 'unitless' + ENDIF + + ! Scale by chemistry timestep + ARRAY(:,:,1) = AD21_cr(:,:,N) / SCALECHEM + + ! Save to BPCH file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N+PD21, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF + ENDIF +! +!****************************************************************************** +! ND22: J-value diagnostics +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) JNO2 : NO2 J-Value : s-1 : SCALE_JV +! (2 ) JHNO3 : HNO3 J-Value : s-1 : SCALE_JV +! (3 ) JH2O2 : H2O2 J-Value : s-1 : SCALE_JV +! (4 ) JCH2O : CH2O J-Value : s-1 : SCALE_JV +! (5 ) JO3 : O3 J-Value : s-1 : SCALE_JV +! (6 ) POH : OH-source from O3 photolysis : s-1 : SCALE_JV +! (7 ) JGLYX : GLYX J-Value : s-1 : SCALE +! (8 ) JMGLY : MGLY J-Value : s-1 : SCALE +! (71 ) JCH3I : CH3I J-value (s^-1) : s-1 : SCALE_JV +! (81 ) JHCN : HCN J-value (s^-1) : s-1 : SCALE_JV +! +! NOTES: +! (1) We must add TRCOFFSET for CH3I and HCN runs, so that GAMAP can +! recognize those photo rates as distinct from the NO2, HNO3, +! H2O2, CH2O, O3, and POH photo rates. +! (2) Pick the right tracer field from AD22 if only a subset of tracers +! are requested to be printed out. (ccc, 12/15/08) +! (3) Add GLYX and MGLY tracers (tmf, 3/6/09) +!****************************************************************************** +! + IF ( ND22 > 0 ) THEN + CATEGORY = 'JV-MAP-$' + SCALE_TMP = FLOAT( CTJV ) + 1d-20 + UNIT = 's-1' + + DO M = 1, TMAX(22) + N = TINDEX(22,M) + !----------------------------------------------------------------- + ! Prior to 12/15/08: + !IF ( N > PD22 ) CYCLE + !----------------------------------------------------------------- + NN = N + + !----------------------------------------------------------------- + ! NOTE: We can no longer select "all" in "input.geos", but we + ! must specify the tracer #'s for ND22 explicitly: + ! + ! Fullchem: CH3I HCN + ! 1 = NOx 1 = CH3I 1 = HCN + ! 7 = HNO3 + ! 8 = H2O2 + ! 20 = CH2O + ! 55 = GLYX + ! 56 = MGLY + ! N_TRACERS+1 = O3 & OH + ! + ! (ccc, bmy, 12/15/08) + !----------------------------------------------------------------- + IF ( NN >= N_TRACERS+1 ) THEN + MM = 5 ! Write 'O3' and 'OH' + ELSE + SELECT CASE ( TRIM( TRACER_NAME(NN) ) ) + CASE ( 'NOx', 'HCN', 'CH3I' ) + MM = 1 + CASE ( 'HNO3' ) + MM = 2 + CASE ( 'H2O2' ) + MM = 3 + CASE ( 'CH2O' ) + MM = 4 + CASE ( 'GLYX' ) + MM = 7 + CASE ( 'MGLY' ) + MM = 8 + CASE DEFAULT + MM = 0 + END SELECT + ENDIF + + ! Skip if not a valid index + IF ( MM == 0 ) CYCLE + + DO L = 1, LD22 + !--------------------------------------------------------------- + ! Prior to 12/15/08: + !ARRAY(:,:,L) = AD22(:,:,L,N) / SCALE_TMP(:,:) + !--------------------------------------------------------------- + ARRAY(:,:,L) = AD22(:,:,L,MM) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, MM, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD22, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD22) ) + + ! If we have just written out O3, then write out OH + ! (ccc, bmy, 12/15/08) + IF ( MM == 5 ) THEN + MMB = 6 + DO L = 1, LD22 + ARRAY(:,:,L) = AD22(:,:,L,MMB) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, MMB, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD22, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD22) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND24: Eastward mass flux from transport (TPCORE, XTP) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) MASSFLEW : Eastward mass flux - transport : kg/s : SCALEDYN +! +! NOTES: +! (1) MASSFLEW is REAL*8...store to ARRAY, which is REAL*4 +! before sending to BPCH or IJSCAL (bey, bmy, 4/23/99) +! (2) Now only write LD24 levels out to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND24 > 0 ) THEN + CATEGORY = 'EW-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(24) + N = TINDEX(24,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! (dkh, 02/09/12, adj32_022) + !ARRAY(:,:,1:LD24) = MASSFLEW(:,:,1:LD24,N) / SCALEDYN + ARRAY(:,:,1:LD24) = MASSFLEW(:,:,LLPAR:LLPAR-LD24+1:-1,N) + & / SCALEDYN + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD24, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD24) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND25: Northward mass flux from transport (TPCORE, YTP) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) MASSFLNS : Northward mass flux - transport : kg/s : SCALEDYN +! +! NOTES: +! (1) MASSFLNS is REAL*8...store to ARRAY, which is REAL*4 +! before sending to BPCH or IJSCAL (bey, bmy, 4/23/99) +! (2) Now only write LD25 levels out to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND25 > 0 ) THEN + CATEGORY = 'NS-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(25) + N = TINDEX(25,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! (dkh, 02/09/12, adj32_022) + !ARRAY(:,:,1:LD25) = MASSFLNS(:,:,1:LD25,N) / SCALEDYN + ARRAY(:,:,1:LD25) = MASSFLNS(:,:,LLPAR:LLPAR-LD25+1:-1,N) + & / SCALEDYN + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD25, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD25) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND26: Upward mass flux from transport (TPCORE, FZPPM) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) MASSFLUP : Upward mass flux - transport : kg/s : SCALEDYN +! +! NOTES: +! (1) MASSFLNS is REAL*8...store to ARRAY, which is REAL*4 +! before sending to BPCH or IJSCAL (bey, bmy, 4/23/99) +! (2) Now only write LD26 levels to the bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND26 > 0 ) THEN + CATEGORY = 'UP-FLX-$' + UNIT = 'kg/s' + + DO M = 1, TMAX(26) + N = TINDEX(26,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ! (dkh, 02/09/12, adj32_022) + !ARRAY(:,:,1:LD26) = MASSFLUP(:,:,1:LD26,N) / SCALEDYN + ARRAY(:,:,1:LD26) = MASSFLUP(:,:,LLPAR:LLPAR-LD26+1:-1,N) + & / SCALEDYN + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD26, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD26) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND27: Cross-tropopause Stratospheric Influx of Ox +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) : Ox : Ox from the stratosphere : kg/s : SCALEDYN +! +! NOTES: +! (1) Only print out if we are doing a NOx-Ox-HC run (NSRCX == 3) +! or a single tracer Ox run (NSRCX == 6). (bey, bmy, 11/10/99) +! (2) Now consider the cross-tropopause stratospheric influx of ozone, +! which, in some grid boxes, includes horizontal influxes as well as +! up(down)ward flux. (qli, 1/5/2000) +! (3) Now error check for N > NTRACE (bmy, 10/23/01) +! (4) NOTE: There is a problem with for ND27 with GEOS-4. Djj says that +! the downward flux at the 200 hPa level should be more or less the +! same as the ND27 diagnostic. (bmy, 10/15/04) +! (5) Now provides stratrospheric flux of H2/HD if it is a H2/HD simulation +! (lyj, phs, 9/18/07) +!****************************************************************************** +! +#if !defined( GEOS_4 ) + IF ( ND27 > 0 .and. IDTOX > 0 ) then + IF ( ( IDTOX > 0 .and. + & ( ITS_A_FULLCHEM_SIM() .or. ITS_A_TAGOX_SIM() ) ) .OR. + & ( ITS_A_H2HD_SIM() ) ) THEN + + CATEGORY = 'STRT-FLX' + UNIT = 'kg/s' + + ! Full chemistry -- compute NOx, Ox, HNO3 fluxes + ! H2/HD -- compute H2, HD fluxes + ! Single tracer Ox -- compute Ox flux only, hardwire + ! to tracer = 1 (bmy, 2/7/00) + IF ( ITS_A_FULLCHEM_SIM() ) THEN + ITEMP = (/ IDTNOX, IDTOX, IDTHNO3 /) + ELSE IF ( ITS_A_H2HD_SIM() ) THEN + ITEMP = (/ IDTH2, IDTHD, 0 /) + ELSE + ITEMP = (/ 1, 0, 0 /) + ENDIF + + ! Loop over tracers + DO M = 1, 3 + N = ITEMP(M) + IF ( N == 0 ) CYCLE + IF ( N > N_TRACERS ) CYCLE + + ! Loop over grid boxes + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Get the level of the tropopause + L = LPAUSE(I,J) + + ! Initialize integer flags + IS = 0 + IN = 0 + IW = 0 + IE = 0 + + ! Set integer flags based on the value of each bit of IFLX + IF ( BTEST( IFLX(I,J), 0 ) ) IS = 1 + IF ( BTEST( IFLX(I,J), 1 ) ) IN = 1 + IF ( BTEST( IFLX(I,J), 2 ) ) IW = 1 + IF ( BTEST( IFLX(I,J), 3 ) ) IE = 1 + + ! Add fluxes from the top, south, and west + ARRAY(I,J,1) = MASSFLUP(I,J,L,N) + + & ( MASSFLNS(I,J,L,N) * IS ) + + & ( MASSFLEW(I,J,L,N) * IW ) + + ! Add fluxes from the north + ! (take poles into account !) + IF ( J < JJPAR ) THEN + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLNS(I,J+1,L,N) * IN ) + ELSE + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLNS(I, 1,L,N) * IN ) + ENDIF + + ! Add fluxes from the east + !(wrap around dateline if necessary) + IF ( I < IIPAR ) THEN + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLEW(I+1,J,L,N) * IE ) + ELSE + ARRAY(I,J,1) = ARRAY(I,J,1) - + & ( MASSFLEW( 1,J,L,N) * IE ) + ENDIF + ENDDO + ENDDO + + UNIT = 'kg/s' + NN = N + + ARRAY(:,:,1) = ARRAY(:,:,1) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, PD27, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF + ENDIF +#endif +! +!****************************************************************************** +! ND28: Biomass burning diagnostic +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) NOx : NOx : molec NOx /cm2/s : SCALESRCE +! (4 ) CO : CO : molec CO /cm2/s : SCALESRCE +! (9 ) ACET : Acetone : atoms C /cm2/s : SCALESRCE +! (10) MEK : Ketones(>C3) : atoms C /cm2/s : SCALESRCE +! (11) ALD2 : Acetaldehyde : atoms C /cm2/s : SCALESRCE +! (18) PRPE : Propene : atoms C /cm2/s : SCALESRCE +! (19) C3H8 : Propane : atoms C /cm2/s : SCALESRCE +! (20) C2HO : Formaldehyde : molec CH2O/cm2/s : SCALESRCE +! (21) C2H6 : Ethane : atoms C /cm2/s : SCALESRCE +! (26) SO2 : Sulfur dioxide : molec SO2 /cm2/s : SCALESRCE +! (30) NH3 : Ammonia : molec NH3 /cm2/s : SCALESRCE +! (34) BCPO : Black carbon : atoms C /cm2/s : SCALESRCE +! (35) OCPO : Organic carbon : atoms C /cm2/s : SCALESRCE +! +! NOTES: +! (1) Use the F90 intrinsic "ANY" function to make sure that N +! corresponds to actual biomass burning tracers (bmy, 4/8/99) +! (2) ND28 now uses allocatable array AD28 instead of AIJ. (bmy, 3/16/00) +! (3) Now write biofuel burning tracers to the punch file in the same order +! as they are listed in "diag.dat". (bmy, 4/17/01) +!****************************************************************************** +! + IF ( ND28 > 0 ) THEN + CATEGORY = 'BIOBSRCE' + UNIT = '' + + DO M = 1, TMAX(28) + N = TINDEX(28,M) + IF ( .not. ANY( BIOTRCE == N ) ) CYCLE + NN = N + + DO MM = 1, NBIOMAX + IF ( BIOTRCE(MM) == NN ) THEN + MMB = MM + EXIT + ENDIF + ENDDO + + ARRAY(:,:,1) = AD28(:,:,MMB) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + ENDIF +! +!****************************************************************************** +! ND29: CO source diagnostics +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) COanth : CO from Anthro Sources : mol/cm2/s : SCALESRCE +! (2) CObb : CO from Biomass Burning : mol/cm2/s : SCALESRCE +! (3) CObf : CO from Biofuel Burning : mol/cm2/s : SCALESRCE +! (4) COmeth : CO from Methanol : mol/cm2/s : SCALESRCE +! (5) COmono : CO from Monoterpenes : mol/cm2/s : SCALESRCE +! +! NOTES: +! (1) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2) ND29 now uses allocatable array AD29 instead of AIJ. (bmy, 3/16/00) +! (3) Added CO-sources from isoprene and monoterpenes (bnd, bmy, 1/2/01) +!****************************************************************************** +! + IF ( ND29 > 0 ) THEN + CATEGORY ='CO--SRCE' + UNIT = 'mol/cm2/s' + + DO M = 1, TMAX(29) + N = TINDEX(29,M) + IF ( N > PD29 ) CYCLE + NN = N + + ARRAY(:,:,1) = AD29(:,:,N) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND30: Land map diagnostic +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) LWI : GMAO Land-Water indices : unitless : SCALED +! +! NOTES: +! (1) Values are: 0=water; 1=land; 2=ice (bmy, 8/18/05) +!****************************************************************************** +! + IF ( ND30 > 0 ) THEN + CATEGORY = 'LANDMAP' + UNIT = 'unitless' + + ARRAY(:,:,1) = AD30(:,:) / SCALEDYN + NN = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF +! +!****************************************************************************** +! ND31: Surface pressure diagnostic +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) Pedge : Pressure at bot edge of level L : mb : SCALEDYN +! +! NOTES: +! (1) The ASCII punch file was using SCALE2 instead of SCALE1. +! This has now been fixed. (hyl, bmy, 12/21/99). +! (2) Now use AD31 dynamically allocatable array (bmy, 2/17/00) +! (3) Bug fix: write out 1 level to the bpch file (bmy, 12/7/00) +! (4) Now remove SCALE1, replace with SCALEDYN (bmy, 2/24/03) +! (5) Now save out true pressure at level edges. Now (bmy, 5/8/07) +!****************************************************************************** +! + IF ( ND31 > 0 ) THEN + CATEGORY = 'PEDGE-$' + UNIT = 'mb' + ARRAY(:,:,1:LD31) = AD31(:,:,1:LD31) / SCALEDYN + NN = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD31, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD31) ) + ENDIF +! +!****************************************************************************** +! ND32: NOx source diagnostic +! +! Levels : Field : Units : Scale Factor +! ------------------------------------------------------------------------- +! 1 - LLTROP : Aircraft NOx : molec/cm2/s : SCALESRCE +! 1 - NOXEXTENT : Anthropogenic NOx : molec/cm2/s : SCALESRCE +! Surface : Biomass Burning NOx : molec/cm2/s : SCALESRCE +! Surface : Biofuel Burning NOx : molec/cm2/s : SCALESRCE +! Surface : Fertilizer NOx : molec/cm2/s : SCALESRCE +! 1 - LLCONVM : Lightning NOx : molec/cm2/s : SCALESRCE +! Surface : Soil NOx : molec/cm2/s : SCALESRCE +! Above TP : NOx from upper boundary: molec/cm2/s : SCALEDYN +! +! Print out all of the types of NOx, for all levels. +! +! NOTES: +! (1) Only print out ND32 if for an O3 chemistry run ( NSRCX == 3 ), +! and if NOx is a defined tracer ( IDTNOX > 0 ). (bmy, 5/26/99) +! (2) ND32 now uses allocatable arrays instead of AIJ. (bmy 3/16/00) +! (3) Added biofuel burning to ND32 diagnostic (bmy, 9/12/00) +!****************************************************************************** +! + IF ( ND32 > 0 .and. IDTNOX > 0 .and. ITS_A_FULLCHEM_SIM() ) THEN + + ! All categories of NOx are in molec/cm2/s + UNIT = 'molec/cm2/s' + + !============================================================== + ! Aircraft NOx + !============================================================== + CATEGORY = 'NOX-AC-$' + + DO L = 1, LLTROP + ARRAY(:,:,L) = AD32_ac(:,:,L) / SCALESRCE + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLTROP, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LLTROP) ) + + !============================================================== + ! Anthropogenic NOx + !============================================================== + CATEGORY = 'NOX-AN-$' + + ! Add ship NOx to layer 1 + ! We scale by AD32_ship_count because the ship emission diagnostic + ! is recorded every CHEMISTRY timestep when using INSTANT PBL mixing + ! and every CONVECTION timestep when using NON-LOCAL PBL mixing + IF ( AD32_SHIP_COUNT >= 1 ) THEN + ARRAY(:,:,1) = AD32_an(:,:,1) / SCALESRCE + + & AD32_SHIP(:,:) / REAL( AD32_SHIP_COUNT ) + ARRAY(:,:,2:NOXEXTENT) = AD32_an(:,:,2:NOXEXTENT) / SCALESRCE + ELSE + ARRAY(:,:,1:NOXEXTENT) = AD32_an(:,:,1:NOXEXTENT) / SCALESRCE + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, NOXEXTENT, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:NOXEXTENT) ) + + !============================================================== + ! Biomass Burning NOx + !============================================================== + CATEGORY = 'NOX-BIOB' + ARRAY(:,:,1) = AD32_bb(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Binary punch file: NOx from Biofuel + !============================================================== + CATEGORY = 'NOX-BIOF' + ARRAY(:,:,1) = AD32_bf(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Fertilizer NOx + !============================================================== + CATEGORY = 'NOX-FERT' + ARRAY(:,:,1) = AD32_fe(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Lightning NOx + !============================================================== + CATEGORY = 'NOX-LI-$' + + DO L = 1, LLCONVM + ARRAY(:,:,L) = AD32_li(:,:,L) / SCALESRCE + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LLCONVM, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LLCONVM) ) + + !============================================================== + ! Soil NOx + !============================================================== + CATEGORY = 'NOX-SOIL' + ARRAY(:,:,1) = AD32_so(:,:) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + !============================================================== + ! Stratospheric NOx (boundary condition) + !============================================================== + CATEGORY = 'NOX-STRT' + ARRAY(:,:,1) = AD32_ub(:,:) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, IDTNOX, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDIF +! +!****************************************************************************** +! ND33: Atmospheric column sum of Tracer +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) COLUMN-T : Trop. Column Sum of Tracer : kg : SCALEDYN +! +! NOTES: +! (1) Now use dynamically allocatable array AD33 (bmy, 2/17/00) +! (2) Rename category to COLUMN-T, since this is a column sum of tracer over +! the entire atmosphere, not just the troposphere. (bmy, 4/3/02) +! (3) Now replace SCALE1 with SCALEDYN (bmy, 3/27/03) +!****************************************************************************** +! + IF ( ND33 > 0 ) THEN + CATEGORY = 'COLUMN-T' + UNIT = 'kg' + + DO M = 1, TMAX(33) + N = TINDEX(33,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1) = AD33(:,:,N) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND34: Biofuel burning diagnostic +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) NOx : NOx : molec NOx /cm2/s : SCALESRCE +! (4 ) CO : CO : molec CO /cm2/s : SCALESRCE +! (5 ) ALK4 : Alkanes(>C4) : atoms C /cm2/s : SCALESRCE +! (9 ) ACET : Acetone : atoms C /cm2/s : SCALESRCE +! (10) MEK : Metyl Ethyl Ketone : atoms C /cm2/s : SCALESRCE +! (11) ALD2 : Acetaldehyde : atoms C /cm2/s : SCALESRCE +! (18) PRPE : Alkenes(>=C3) : atoms C /cm2/s : SCALESRCE +! (19) C3H8 : Propane : atoms C /cm2/s : SCALESRCE +! (20) CH2O : Formaldehyde : molec CH2O/cm2/s : SCALESRCE +! (21) C2H6 : Ethane : atoms C /cm2/s : SCALESRCE +! +! NOTES: +! (1) Use the F90 intrinsic "ANY" function to make sure that N +! corresponds to actual biofuel burning tracers (bmy, 3/15/01) +! (3) Now write biofuel burning tracers to the punch file in the same order +! as they are listed in "diag.dat". (bmy, 4/17/01) +! (4) Use BFTRACE and NBFTRACE to get the right index for AD34. +! (ccc, 12/8/2008) +!****************************************************************************** +! + IF ( ND34 > 0 ) THEN + CATEGORY = 'BIOFSRCE' + UNIT = '' + + DO M = 1, TMAX(34) + N = TINDEX(34,M) + IF ( .not. ANY( BFTRACE == N ) ) CYCLE + NN = N + + DO MM = 1, NBFTRACE + IF ( BFTRACE(MM) == NN ) THEN + MMB = MM + EXIT + ENDIF + ENDDO + + ARRAY(:,:,1) = AD34(:,:,MMB) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND35: Tracer concentration at 500 mb +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) 500-AVRG : Tracer at 500 mb : v/v : SCALEDYN +! +! NOTES: +! (1) Now use dynamically allocatable array AD35 (bmy, 2/17/00) +! (2) Now replace SCALE1 with SCALEDYN (bmy, 2/24/03) +!****************************************************************************** +! + IF ( ND35 > 0 ) THEN + CATEGORY = '500-AVRG' + UNIT = '' + + DO M = 1, TMAX(35) + N = TINDEX(35,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + ARRAY(:,:,1) = AD35(:,:,N) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND36: Anthropogenic source diagnostic +! +! # Field : Description : Units : S. Factor +! --------------------------------------------------------------------------- +! (1 ) NOx : NOx : mol/cm2/s : SCALE3 +! (4 ) CO : CO : mol/cm2/s : SCALE3 +! (5 ) ALK4 : Alkanes(>C4) : atoms C/cm2/s : SCALE3 +! (9 ) ACET : Acetone : atoms C/cm2/s : SCALE3 +! (10) MEK : Ketones(>C3) : atoms C/cm2/s : SCALE3 +! (18) PRPE : Propene : atoms C/cm2/s : SCALE3 +! (19) C3H8 : Propane : atoms C/cm2/s : SCALE3 +! (21) C2H6 : Ethane : atoms C/cm2/s : SCALE3 +! (71) CH3Ioc : Methyl Iodide (oceanic source) : ng/m2/s : SCALE3 +! (72) CH3Ibb : Methyl Iodide (biomass burning) : ng/m2/s : SCALE3 +! (73) CH3Iwb : Methyl Iodide (wood burning) : ng/m2/s : SCALE3 +! (74) CH3Irc : Methyl Iodide (rice paddies) : ng/m2/s : SCALE3 +! (75) CH3Iwl : Methyl Iodide (wetlands) : ng/m2/s : SCALE3 +! +! NOTES: +! (1) ND36 is also used for CH3I emissions diagnostics when NSRCX=2. +! (2) For an O3 run (NSRCX = 3, the "default" run) make sure that the +! tracer number N matches an entry in the IDEMS emission index +! array (bmy, 4/9/99) +! (3) Write the tracers out to the punch file in the same order as +! they are listed in the IDEMS array. Thus, we have to re-assign +! N = IDEMS(M) after we test to make sure it is a valid tracer +! number (bmy, 4/16/99) +! (4) For a CH3I run, make sure that the tracer number N is not larger +! than NTRACE (bmy, 4/9/99) +! (5) ND36 now uses the AD36 array instead of AIJ. (bmy, 3/16/00) +! (6) Rewritten for clarity; also fixed for CH3I (bmy, 7/25/06) +! (7) Bug fix: given the tracer number, now search for entry in IDEMS +! to jive with historical baggage (bmy, 3/6/07) +!****************************************************************************** +! + IF ( ND36 > 0 ) THEN + + ! Loop over # of tracers + DO M = 1, TMAX(36) + + ! Get the tracer # from input.geos + N = TINDEX(36,M) + + IF ( ITS_A_CH3I_SIM() ) THEN + + !-------------------------------------------------------- + ! For CH3I simulation only + !-------------------------------------------------------- + CATEGORY = 'CH3ISRCE' + UNIT = 'ng/m2/s' + IF ( N > NEMANTHRO ) CYCLE + + ! Tracer number + NN = N + + ! Index for AD36 array + MM = M + + ELSE + + !-------------------------------------------------------- + ! For full-chemistry. Note, due to historical baggage, + ! the order of the tracers in AD36 array corresponds to + ! the order as given in IDEMS. Therefore, for the given + ! tracer number N, we must find the corresponding entry + ! in IDEMS. (bmy, 3/5/07) + !-------------------------------------------------------- + CATEGORY = 'ANTHSRCE' + UNIT = '' + + ! reset these + MM = 0 + NN = 0 + + ! Given the tracer number N, find the proper entry in the + ! IDEMS array and select that for output (bmy, 3/5/07) + DO NMAX = 1, NEMANTHRO + IF ( N == IDEMS(NMAX) ) THEN + MM = NMAX + NN = N + EXIT + ENDIF + ENDDO + + ! We haven't found a match, skip to next tracer + IF ( MM == 0 ) CYCLE + + ENDIF + + ! Divide by seconds for AD36 and by AD36_SHIP_COUNT for AD36_SHIP + ! We scale by AD32_ship_count because the ship emission diagnostic + ! is recorded every CHEMISTRY timestep when using INSTANT PBL mixing + ! and every CONVECTION timestep when using NON-LOCAL PBL mixing + IF ( AD36_SHIP_COUNT >= 1 ) THEN + ARRAY(:,:,1) = AD36(:,:,MM) / SECONDS + + & AD36_SHIP(:,:,MM) / REAL( AD36_SHIP_COUNT ) + ELSE + ARRAY(:,:,1) = AD36(:,:,MM) / SECONDS + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND37: Fraction of tracer scavenged in convective cloud updrafts +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WETCVF-$ : Scavenging fraction : unitless : SCALECONV +!****************************************************************************** +! + IF ( ND37 > 0 ) THEN + CATEGORY = 'MC-FRC-$' + UNIT = 'unitless' + + ! Get actual # of soluble tracers + NMAX = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, NMAX + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(37) ) + MMB = TINDEX(37,MM) + MM = MM + 1 + ENDDO + + IF ( MMB /= NN ) CYCLE + + DO L = 1, LD37 + ARRAY(:,:,L) = AD37(:,:,L,N) / SCALECONV + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD37, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD37) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND38: Rainout loss of tracer in convective updrafts +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WETDCV-$ : Rainout loss of tracer : kg/s : SCALECONV +! +! NOTES: +! (1) Now write only LD38 levels to bpch file (bmy, 12/7/00) +!****************************************************************************** +! + IF ( ND38 > 0 ) THEN + CATEGORY = 'WETDCV-$' + UNIT = 'kg/s' + + ! Get actual # of soluble tracers + M = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, M + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(38) ) + MMB = TINDEX(38,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Divide by # of convective timesteps + DO L = 1, LD38 + ARRAY(:,:,L) = AD38(:,:,L,N) / SCALECONV + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD38, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD38) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND39: Rainout loss of tracer in large scale rains +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) WETDLS-$ : Large-scale loss of tracer : kg/s : SCALEDYN +!****************************************************************************** +! + IF ( ND39 > 0 ) THEN + CATEGORY = 'WETDLS-$' + UNIT = 'kg/s' + + ! Get actual # of soluble tracers + M = GET_WETDEP_NSOL() + + ! Loop over soluble tracers + DO N = 1, M + + ! Tracer number + NN = GET_WETDEP_IDWETD( N ) + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(39) ) + MMB = TINDEX(39,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Divide by # of wetdep (= dynamic) timesteps + DO L = 1, LD39 + ARRAY(:,:,L) = AD39(:,:,L,N) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD39, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD39) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND41: Afternoon boundary layer heights +!****************************************************************************** +! + IF ( ND41 > 0 ) CALL WRITE_DIAG41 +! +!****************************************************************************** +! ND42: SOA concentrations [ug/m3] +!****************************************************************************** +! + IF ( ND42 > 0 ) CALL WRITE_DIAG42 +! +!****************************************************************************** +! ND42: Free diagnostic as of 11/24/99 +! +! ND43: Chemical production of OH and NO +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) OH : OH Chemical Diagnostic : mol/cm3 : CTOH +! (2) NO : NO Chemical Diagnostic : v/v : CTNO +! (3) HO2 : HO2 Chemical Diagnostic : v/v : CTHO2 +! (4) NO2 : NO2 Chemical Diagnostic : v/v : CTNO2 +! (5) NO3 : NO3 Chemical Diagnostic : v/v : CTNO3 +! +! NOTES: +! (1) Print output for either a NOx-Ox-HC run (NSRCX == 3), or a CO run +! with parameterized OH (NSRCX== 5). (bmy, 4/17/00) +! (2) Add parentheses in IF test since .AND. has higher precedence +! than .OR. (jsw, bmy, 12/5/00) +! (3) Added HO2, NO2 to ND43 (rvm, bmy, 2/27/02) +! (4) Added NO3 to ND43 (bmy, 1/16/03) +! (5) Now uses 3D counters (phs, 1/24/07) +! (6) Now assume that LD43 can't be higher than LD45 (phs, 1/24/07) +! (7) Check that CTxx are not zero, instead of adding 1e-20 (phs, 11/13/07) +!****************************************************************************** +! + IF ( ND43 > 0 .and. ITS_A_FULLCHEM_SIM() ) THEN + + CATEGORY = 'CHEM-L=$' + + DO M = 1, TMAX(43) + N = TINDEX(43,M) + NN = N + + ! default units + UNIT = 'v/v' + + + SELECT CASE ( N ) + + ! OH + CASE ( 1 ) + WHERE( CTOH /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTOH ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + UNIT = 'molec/cm3' + + ! NO + CASE ( 2 ) + WHERE( CTNO /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTNO ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + + ! HO2 (rvm, bmy, 2/27/02) + CASE ( 3 ) + WHERE( CTHO2 /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTHO2 ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + + ! NO2 (rvm, bmy, 2/27/02) + CASE ( 4 ) + WHERE( CTNO2 /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTNO2 ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + !PRINT *, "AD43", ARRAY(:,:,1:ND43) + PRINT *, "N", N + !PRINT *, "CTNO2", FLOAT(CTNO2) + + + ! NO3 (rjp, bmy, 1/16/03) + CASE ( 5 ) + WHERE( CTNO3 /= 0 ) + ARRAY(:,:,1:LD43) = AD43(:,:,1:LD43,N) / + $ FLOAT( CTNO3 ) + ELSEWHERE + ARRAY(:,:,1:LD43) = 0. + ENDWHERE + + + CASE DEFAULT + CYCLE + + END SELECT + + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD43, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD43) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND44: Drydep flux (molec/cm2/s) and velocity (cm/s) diagnostics +! +! # : Field : Quantity : Units : Scale factor +! ------------------------------------------------------------------------- +! (1 ) : DRYD-FLX : drydep fluxes : molec/cm2/s or kg/s : SCALECHEM +! (2 ) : DRYD-VEL : drydep velocities : cm/s : SCALECHEM +! +! NOTES: +! (1 ) Remove diagnostics for wetdep HNO3, H2O2 from ND44. +! (2 ) For NSRCX == 1 (Rn-Pb-Be), save the actual tracer number +! instead of the dry deposition index. Add TRCOFFSET to N. +! (3 ) For NSRCX == 6 (single tracer Ox), drydep fluxes are in kg/s. +! (4 ) ND44 now uses allocatable array AD44 instead of AIJ. (bmy, 3/16/00) +! (5 ) Add code from amf for multi-tracer Ox (bmy, 7/3/01) +! (6 ) Now divide by SCALECHEM since DRYFLX is only called after the +! chemistry routines for all relevant simulations (bmy, 1/27/03) +! (7 ) Now print out NTRACE drydep fluxes for tagged Ox. Also tagged Ox +! now saves drydep in molec/cm2/s. (bmy, 8/19/03) +! (8 ) Rearrange ND44 code for clarity (bmy, 3/24/04) +! (9 ) Add code for H2/HD simulation (phs, 5/8/07) +!****************************************************************************** +! + IF ( ND44 > 0 ) THEN + + !============================================================== + ! Drydep fluxes + !============================================================== + + ! Category name + CATEGORY = 'DRYD-FLX' + + ! # of drydep flux tracers + IF ( ITS_A_TAGOX_SIM() .or. ITS_A_MERCURY_SIM() ) THEN + M = N_TRACERS + ELSE + M = NUMDEP + ENDIF + + ! Loop over drydep tracers + DO N = 1, M + + IF ( ITS_A_RnPbBe_SIM() .or. ITS_A_H2HD_SIM() ) THEN + + ! Radon or H2/HD + UNIT = 'kg/s' + NN = NTRAIND(N) + + ELSE IF ( ITS_A_TAGOX_SIM() .or. ITS_A_MERCURY_SIM() ) THEN + + ! Tagged Ox or Tagged Hg + UNIT = 'molec/cm2/s' + NN = N + + ELSE + + ! Other simulations + UNIT = 'molec/cm2/s' + NN = NTRAIND(N) + + ENDIF + + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(44) ) + MMB = TINDEX(44,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Save into ARRAY + ARRAY(:,:,1) = ( AD44(:,:,N,1) / SCALECHEM ) + + ! Write to file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + + !============================================================== + ! Drydep velocities + !============================================================== + + ! Category and Unit + CATEGORY = 'DRYD-VEL' + UNIT = 'cm/s' + + ! # of drydep velocity tracers + IF ( ITS_A_TAGOX_SIM() ) THEN + M = 1 + ELSE IF ( ITS_A_MERCURY_SIM() ) THEN + M = 2 + ELSE + M = NUMDEP + ENDIF + + ! Loop over drydep tracers + DO N = 1, M + + NN = NTRAIND(N) + ! To output only the species asked in input.geos + ! (ccc, 5/15/09) + MM = 1 + MMB = 0 + DO WHILE ( MMB /= NN .AND. MM <= TMAX(44) ) + MMB = TINDEX(44,MM) + MM = MM + 1 + ENDDO + + ! IF ( MMB /= NN ) CYCLE ! comment out(lz,05/29/13) + + ! Tracer number plus GAMAP offset + ARRAY(:,:,1) = AD44(:,:,N,2) / SCALESRCE + + ! Write to file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + ENDIF +! +!****************************************************************************** +! ND45: Tracer Mixing Ratio (v/v) for Levels L = 1, LD45 +! averaged between hours OTH_HR1 and OTH_HR2 +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) IJ-AVG-$ : Tracer mixing ratio : v/v : CTOTH +! +! NOTES: +! (1) For NSRCX == 3 (NOx-Ox-HC run), store pure O3 with index NTRACE+1. +! (2) Now store pure O3 as NNPAR+1 (now tracer #32). (bmy, 1/10/03) +! (3) Now uses CTO3 instead of CTOH for pure O3 (phs, 1/24/07) +! (4) Better handling of O3 case (phs, 11/17/08) +!****************************************************************************** +! + IF ( ND45 > 0 ) THEN + CATEGORY = 'IJ-AVG-$' + SCALE_TMP = FLOAT( CTOTH ) + 1d-20 + UNIT = '' + + DO M = 1, TMAX(45) + N = TINDEX(45,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + DO L = 1, LD45 + ARRAY(:,:,L) = AD45(:,:,L,N) / SCALE_TMP(:,:) + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD45, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD45) ) + + ! Store pure O3 as NNPAR+1 (bmy, 1/10/03) + IF ( ITS_A_FULLCHEM_SIM() .and. NN == IDTOX ) THEN + + WHERE( CTO3 /= 0 ) + ARRAY(:,:,1:LD45) = AD45(:,:,1:LD45,N_TRACERS+1) / + $ FLOAT( CTO3 ) + ELSEWHERE + ARRAY(:,:,1:LD45) = 0. + ENDWHERE + + NN = N_TRACERS + 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD45, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD45) ) + ENDIF + ENDDO + ENDIF +! +!****************************************************************************** +! ND46: Biogenic source diagnostic +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) ISOP : Isoprene : atoms C/cm2/s : SCALE3 +! (2) ACET : Acetone : atoms C/cm2/s : SCALE3 +! (3) PRPE : Propene : atoms C/cm2/s : SCALE3 +! (4) MONOT : Monoterpenes : atoms C/cm2/s : SCALE3 +! (5) MBO : Methyl Butenol : atoms C/cm2/s : SCALE3 +! (6) C2H4 : Ethene : atoms C/cm2/s : SCALE3 +! +! NOTES: +! (1) ND46 now uses allocatable array AD46 instead of AIJ (bmy, 3/16/00) +! (2) Also write out PRPE for CO-OH run (NSRCX == 5), regardless of +! the setting of IDTPRPE. This is to print out monterpene +! diagnostics. (bnd, bmy, 4/18/00) +! (3) Added monoterpenes as tracer #4. This requires updated versions +! of "tracerinfo.dat" and "diaginfo.dat" for GAMAP. (bmy, 1/2/01) +! (4) Added MBO as tracer #5. (tmf, bmy, 10/20/05) +! (5) Added C2H4 as tracer #6. (tmf, 1/20/09) +!****************************************************************************** +! + IF ( ND46 > 0 ) THEN + CATEGORY = 'BIOGSRCE' + UNIT = '' + + DO M = 1, TMAX(46) + N = TINDEX(46,M) + IF ( N > PD46 ) CYCLE + NN = N + + ! Skip if ISOP, ACET, PRPE are not tracers + IF ( N == 1 .and. IDTISOP == 0 ) CYCLE + IF ( N == 2 .and. IDTACET == 0 ) CYCLE + IF ( N == 3 .and. IDTPRPE == 0 ) CYCLE + IF ( N == 6 .and. IDTC2H4 == 0 ) CYCLE + + ARRAY(:,:,1) = AD46(:,:,N) / SCALESRCE + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND47: Tracer Mixing Ratio (v/v) for Levels L = 1, LD47 +! *always* averaged between 0000 and 2400 Local time. +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) IJ-24H-$ : 24h avg Tracer mixing ratio : v/v : SCALEDYN +! +! NOTES: +! (1) For NSRCX == 3 (NOx-Ox-HC run), store pure O3 with index NTRACE+1. +! (2) Now store pure O3 as NNPAR+1 (now tracer #32). (bmy, 1/10/03) +! (3) Now replace SCALE1 with SCALEDYN +! (4) Now averaged between 0 and 24 UT. Replace SCALEDYN with CTOH and +! CTO3 (phs, 1/24/07) +! (5) Revert to SCALEDYN for all species, except O3, which uses new +! CTO3_24h counter (phs, 11/17/08) +!****************************************************************************** +! + IF ( ND47 > 0 ) THEN + CATEGORY = 'IJ-24H-$' + UNIT = '' + + DO M = 1, TMAX(47) + N = TINDEX(47,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + DO L = 1, LD47 + ARRAY(:,:,L) = AD47(:,:,L,N) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD47, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD47) ) + + ! Store pure O3 as NNPAR+1 (bmy, 1/10/03) + IF ( ITS_A_FULLCHEM_SIM() .and. NN == IDTOX ) THEN + + WHERE( CTO3_24h(:,:,1:LD47) /= 0 ) + ARRAY(:,:,1:LD47) = AD47(:,:,1:LD47,N_TRACERS+1) / + $ FLOAT( CTO3_24h(:,:,1:LD47) ) + ELSEWHERE + ARRAY(:,:,1:LD47) = 0. + ENDWHERE + + NN = N_TRACERS + 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD47, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD47) ) + ENDIF + ENDDO + ENDIF + +!****************************************************************************** +! ND52: gamma HO2 and aerosol radius (jaegle 02/26/09) +! # Category +! # : Field : Description : Units : Scale factor +! ---------------------------------------------------------------------------- +! (1): GAMMAHO2 : Uptake coef for HO2 : unitless : SCALECHEM +! +!****************************************************************************** + IF ( ND52 > 0 ) THEN + CATEGORY = 'GAMMA' + UNIT = 'unitless' + + DO L = 1, LD52 + ARRAY(:,:,L) = AD52(:,:,L) / SCALECHEM + ENDDO + + ! Save to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD52, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD52) ) + + ENDIF + + +! +!****************************************************************************** +! ND54: Time-in-the-Troposphere diagnostic +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) TIME-TPS : Time spend in troposphere : fraction : SCALEDYN +!****************************************************************************** +! + IF ( ND54 > 0 ) THEN + CATEGORY = 'TIME-TPS' + UNIT = 'unitless' + + DO L = 1, LD54 + ARRAY(:,:,L) = AD54(:,:,L) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD54, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD54) ) + ENDIF +! +!****************************************************************************** +! ND55: Tropopause diagnostics +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) TP-LEVEL : Tropopause level : unitless : SCALEDYN +! (2) TP-HGHT : Tropopause height : km : SCALEDYN +! (3) TP-PRESS : Tropopause pressure : mb : SCALEDYN +!****************************************************************************** +! + IF ( ND55 > 0 ) THEN + CATEGORY = 'TR-PAUSE' + + DO M = 1, TMAX(55) + N = TINDEX(55,M) + IF ( N > PD55 ) CYCLE + NN = N + + ! Pick the appropriate unit string + SELECT CASE ( N ) + CASE ( 1 ) + UNIT = 'unitless' + CASE ( 2 ) + UNIT = 'km' + CASE ( 3 ) + UNIT = 'mb' + END SELECT + + ARRAY(:,:,1) = AD55(:,:,N) / SCALEDYN + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND56: Lightning flash rate diagnostics (ltm, bmy, 5/5/06)) +!****************************************************************************** +! + IF ( ND56 > 0 ) CALL WRITE_DIAG56 +! +!****************************************************************************** +! ND58: CH4 Emission Diagnostics +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1 ) CH4-TOT : CH4 Emissions total(w/o sab): kg : 1 +! (2 ) CH4-GAO : CH4 Emissions gas & oil : kg : 1 +! (3 ) CH4-COL : CH4 Emissions coal : kg : 1 +! (4 ) CH4-LIV : CH4 Emissions livestock : kg : 1 +! (5 ) CH4-WST : CH4 Emissions waste : kg : 1 +! (6 ) CH4-BFL : CH4 Emissions biofuel : kg : 1 +! (7 ) CH4-RIC : CH4 Emissions rice : kg : 1 +! (8 ) CH4-OTA : CH4 Emissions other anthro : kg : 1 +! (9 ) CH4-BBN : CH4 Emissions bioburn : kg : 1 +! (10) CH4-WTL : CH4 Emissions wetlands : kg : 1 +! (11) CH4-SAB : CH4 Emissions soil abs : kg : 1 +! (12) CH4-OTN : CH4 Emissions other natural : kg : 1 +!****************************************************************************** +! + IF ( ND58 > 0 ) THEN + CATEGORY = 'CH4-EMIS' + + DO M = 1, TMAX(58) + N = TINDEX(58,M) + IF ( N > PD58 ) CYCLE + NN = N + + UNIT = 'kg' + + ARRAY(:,:,1) = AD58(:,:,N) + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND59: NH3 concentrations [ug/m3] (diag59 added, lz,10/11/10) +!****************************************************************************** +! + IF ( ND59 > 0 ) CALL WRITE_DIAG59 +! +!****************************************************************************** +! ND60: Wetland fraction +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) WET-FRAC : WETLAND FRACTION : unitless : 1 +!****************************************************************************** +! + IF ( ND60 > 0 ) THEN + + UNIT = 'unitless' + CATEGORY = 'WET-FRAC' + ARRAY(:,:,1) = AD60(:,:) + N = 1 + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDIF +! +!***************************************************************************** +! ND62: I-J Instantaneous Column Maps for Tracers (molec/cm^2) +! +! The unit conversion is as follows: +! +! STT (kg) | 6.022e23 molec | mole | 1000 g | 1 | m^2 +! ---------+----------------+----------+--------+-------------+---------- +! | mole | MOLWT g | kg | AREA_M2 m^2 | 10^4 cm^2 +! +! +! which is equivalent to +! +! ( STT * 6.022e22 ) / ( MOLWT * AREA_M2 ) +!***************************************************************************** +! + IF ( ND62 > 0 ) THEN + CATEGORY = 'INST-MAP' + + DO M = 1, TMAX(62) + N = TINDEX(62,M) + IF ( N > N_TRACERS ) CYCLE + NN = N + + DO J = 1, JJPAR + + ! Grid box surface area [cm2] + AREA_M2 = GET_AREA_M2( J ) + + DO I = 1, IIPAR + ARRAY(I,J,1) = ( SUM( STT(I,J,:,N) ) * 6.022d22 ) + & / ( TRACER_MW_G(N) * AREA_M2 ) + ENDDO + ENDDO + + ! Write the proper unit string + IF ( TRACER_MW_G(N) > 12d0 ) THEN + UNIT = 'molec/cm2' + ELSE + UNIT = 'atoms C/cm2' + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + + ENDDO + ENDIF +! +!****************************************************************************** +! ND65: Production/Loss of specified chemical families +! +! # : Field : Description : Units : Scale Factor +! --------------------------------------------------------------------------- +! (1) PORL-L=$ : Chemical family P-L rates : mol/cm3/s : SCALECHEM +! +! NOTES: +! (1 ) Make sure the units for NSRCX == 6 (single tracer O3) P-L +! coincide with those in "chemo3.f". +! (2 ) ND65 now uses allocatable array AD65 instead of AIJ. (bmy, 3/16/00) +! (3 ) Add L(CH3I) to the ND65 diagnostic -- do not take the average +! but instead compute the total sum of L(CH3I) (nad, bmy, 3/20/01) +! (4 ) Add updates for multi-tracer Ox run from amf (bmy, 7/3/01) +! (5 ) Now account for time in troposphere for full chemistry. It is +! assumed that LD45 >= LD65 in using CTO3 (phs, 3/6/07) +! (6 ) Do not use CTO3 anymore, but the new CTO3_24h, which is the 3D +! tropospheric chemistry counter (phs, 11/17/08) +!****************************************************************************** +! + IF ( ND65 > 0 ) THEN + CATEGORY = 'PORL-L=$' + + ! Loop over ND65 families + DO N = 1, NFAMILIES + + ! Don't add TRCOFFSET for single tracer Ox + ! Also select proper unit string + IF ( ITS_A_CH3I_SIM() ) THEN + NN = N + UNIT = 'kg/s' + + DO L = 1, LD65 + ARRAY(:,:,L) = AD65(:,:,L,N) + ENDDO + + ELSE IF ( ITS_A_TAGOX_SIM() ) THEN + NN = N + UNIT = 'kg/s' + + WHERE( CTO3_24h(:,:,1:LD65) /= 0 ) + ARRAY(:,:,1:LD65) = AD65(:,:,1:LD65,N) / + $ FLOAT( CTO3_24h(:,:,1:LD65) ) + ELSEWHERE + ARRAY(:,:,1:LD65) = 0. + ENDWHERE + + ELSE IF ( ITS_AN_AEROSOL_SIM() ) THEN + NN = N + UNIT = 'mol/cm3/s' + + DO L = 1, LD65 + ARRAY(:,:,L) = AD65(:,:,L,N) / SCALECHEM + ENDDO + + ELSE + NN = N + UNIT = 'mol/cm3/s' + + WHERE( CTO3_24h(:,:,1:LD65) /= 0 ) + ARRAY(:,:,1:LD65) = AD65(:,:,1:LD65,N) / + $ FLOAT( CTO3_24h(:,:,1:LD65) ) + ELSEWHERE + ARRAY(:,:,1:LD65) = 0. + ENDWHERE + + ENDIF + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD65, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD65) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND66: GMAO 3-D fields +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) UWND : GMAO Zonal Winds : m/s : SCALE_I6 or _A6 +! (2) VWND : GMAO Meridional Winds : m/s : SCALE_I6 or _A6 +! (3) TMPU : GMAO Temperatures : K : SCALE_I6 or _A6 +! (4) SPHU : GMAO Specific Humidity : g/kg : SCALE_I6 or _A6 +! (5) CLDMAS : GMAO Cloud Mass Flux : kg/m2/s : SCALE_A6 or _A6 +! (6) DTRAIN : GMAO Detrainment flux : kg/m2/s : SCALE_A6 +! +! NOTES: +! (1) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2) Add CLDMAS to ND66 diagnostic as field #6, but with tracer index +! #7 (for compatibility with the existing GAMAP). (rvm, bmy, 9/8/00) +! (3) For GEOS-4/fvDAS, UWND, VWND, TMPU, SPHU are A-6 fields. Adjust +! the scale factors accordingly. Also delete KZZ. (bmy, 6/23/03) +! (4) Modified for GEOS-5 and GCAP (bmy, 6/9/05) +!****************************************************************************** +! + IF ( ND66 > 0 ) THEN + CATEGORY = 'DAO-3D-$' + +!!! (lzh, 11/01/2014, geos-fp) +#if defined( GEOS_FP ) + SCALE_ND66 = SCALE_A3 ! For GEOS-FP, ND66 is 3-hr time-avg data +#elif defined( MERRA ) + SCALE_ND66 = SCALE_A3 ! For MERRA, ND66 is 3-hr time-avg data +#else + SCALE_ND66 = SCALE_A6 ! Otherwise, ND66 is 6-hr time-avg data +#endif + + DO M = 1, TMAX(66) + N = TINDEX(66,M) + NN = N + + SELECT CASE ( N ) + + ! UWND, VWND + CASE ( 1,2 ) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#else +!! SCALEX = SCALE_A6 + SCALEX = SCALE_ND66 !! (lzh, 11/01/2014) +#endif + UNIT = 'm/s' + + ! TMPU + CASE ( 3 ) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#elif defined( GEOS_FP ) + SCALEX = SCALE_I3 ! T is an I3 field in GEOS-5.7.x !(lzh,11/01/2014) +#else + SCALEX = SCALE_A6 +#endif + UNIT = 'K' + + ! SPHU + CASE ( 4 ) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#elif defined( GEOS_FP ) + SCALEX = SCALE_I3 ! SPHU is an I3 field in GEOS-5.7.x +#else + SCALEX = SCALE_A6 +#endif + UNIT = 'g/kg' + + ! CLDMAS, DTRAIN + CASE( 5, 6 ) + !! SCALEX = SCALE_A6 + SCALEX = SCALE_ND66 ! geos-fp (lzh,11/01/2014) + UNIT = 'kg/m2/s' + + CASE DEFAULT + CYCLE + END SELECT + + ARRAY(:,:,1:LD66) = AD66(:,:,1:LD66,N) / SCALEX + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD66, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD66) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND67: GMAO surface fields +! +! # : Field : Description : Units : Scale factor +! ----------------------------------------------------------------------- +! (1 ) HFLUX : GMAO Sensible Heat Flux : W/m2 : SCALE_A3 +! (2 ) RADSWG : GMAO Insolation @ Surface : W/m2 : SCALE_A3 +! (3 ) PREACC : GMAO Accum Precip @ Surface : mm/day : SCALE_A3 +! (4 ) PRECON : GMAO Conv Precip @ Surface : mm/day : SCALE_A3 +! (5 ) TS : GMAO Surface Air Temperature : K : SCALE_A3 +! (6 ) RADSWT : GMAO Insolation @ Top of Atm : W/m2 : SCALE_A3 +! (7 ) USTAR : GMAO Friction Velocity : m/s : SCALE_A3 +! (8 ) Z0 : GMAO Roughness Height : m : SCALE_A3 +! (9 ) PBL : GMAO PBL depth : mb : SCALE_A3 +! (10) CLDFRC : GMAO Cloud Fraction : unitless : SCALE_A3 +! (11) U10M : GMAO U-wind @ 10 m : m/s : SCALE_A3 +! (12) V10M : GMAO V-wind @ 10 m : m/s : SCALE_A3 +! (13) PS-PBL : GMAO Boundary Layer Top Pressure : mb : SCALEDYN +! (14) ALBD : GMAO Surface Albedo : unitless : SCALE_I6 +! (15) PHIS : GMAO Geopotential Heights : m : SCALED +! (16) CLTOP : GMAO Cloud Top Height : levels : SCALE_A6 +! (17) TROPP : GMAO Tropopause pressure : mb : SCALE_I6 +! (18) SLP : GMAO Sea Level pressure : mb : SCALE_I6 +! (19) TSKIN : Ground/sea surface temp. : hPa : SCALE_A3 +! (20) PARDF : Photosyn active diffuse rad. : W/m2 : SCALE_A3 +! (21) PARDR : Photosyn active direct rad. : W/m2 : SCALE_A3 +! (22) GWET : Top soil wetness : unitless : SCALE_A3 +! +! NOTES: +! (1 ) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2 ) Now use AD67 allocatable array (bmy, 2/17/00) +! (3 ) Add TROPP as tracer #17 and SLP as tracer #18 (bmy, 10/11/00) +! (4 ) Now replace SCALE1 with SCALEDYN (bmy, 3/27/03) +! (5 ) Added TSKIN, PARDF, PARDR, GWET for GEOS-4 (bmy, 6/23/03) +! (6 ) Fix SCALEX for ALBEDO: use I6 for GEOS-3 only, and A3 for other +! models (phs, 9/3/08) +!****************************************************************************** +! + IF ( ND67 > 0 ) THEN + CATEGORY = 'DAO-FLDS' + +! (lzh, 11/01/2014) geos_fp +#if defined( MERRA ) + SCALE_ND67 = SCALE_A1 ! For MERRA, ND67 fields are hourly +#elif defined( GEOS_FP ) + SCALE_ND67 = SCALE_A1 ! For GEOS-FP, ND67 fields are hourly +#else + SCALE_ND67 = SCALE_A3 ! Otherwise, most ND67 fields are 3-hourly +#endif + + ! Binary punch file + DO M = 1, TMAX(67) + N = TINDEX(67,M) + NN = N + + SELECT CASE ( N ) + CASE ( 1, 2, 6 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'W/m2' + CASE ( 3, 4 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'mm/day' + CASE ( 5 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'K' + CASE ( 7, 11, 12 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'm/s' + CASE ( 8 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'm' + CASE ( 9 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'hPa' + CASE ( 10 ) + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'unitless' + +#if defined( GCAP ) + ! CLDFRC is a 6-hr field in GCAP, GEOS-STRAT + ! (swu, bmy, 6/9/05) + SCALEX = SCALE_A6 +#endif + + CASE ( 13 ) + SCALEX = SCALEDYN + UNIT = 'hPa' + CASE ( 14 ) + ! Bug fix: For GEOS-3, ALBEDO is an I-6 field, but + ! for GEOS-4, GEOS-5, GCAP, it is an A-3 field. + ! (lyj, phs, bmy, 10/7/08) +#if defined( GEOS_3 ) + SCALEX = SCALE_I6 +#else + !! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 +#endif + UNIT = 'unitless' + CASE ( 15 ) + SCALEX = SCALED + UNIT = 'm' + CASE ( 16 ) +! SCALEX = SCALE_A6 +#if defined( MERRA ) || defined( GEOS_FP ) + SCALEX = SCALE_A3 ! MERRA/GEOS-FP CLDTOPS 3-hr avg'd +#else + SCALEX = SCALE_A6 ! Otherwise CLDTOPS is 6-hr time avg'd +#endif + UNIT = 'levels' + CASE ( 17 ) +! SCALEX = SCALE_I6 + SCALEX = SCALE_ND67 + UNIT = 'hPa' + CASE ( 18 ) +! SCALEX = SCALE_I6 +#if defined( MERRA ) || defined( GEOS_FP ) + SCALEX = SCALE_A1 ! MERRA/GEOS-FP SLP is hourly +#else + SCALEX = SCALE_I6 ! Otherwise SLP is 6-h inst. +#endif + UNIT = 'hPa' + CASE ( 19 ) +! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'K' + CASE ( 20 ) +! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'W/m2' + CASE ( 21 ) +! SCALEX = SCALE_A3 + SCALEX = SCALE_ND67 + UNIT = 'W/m2' + CASE ( 22 ) + SCALEX = SCALE_A3 + UNIT = 'unitless' + CASE DEFAULT + CYCLE + END SELECT + + ARRAY(:,:,1) = AD67(:,:,N) / SCALEX + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND68: Grid box diagnostics +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) BXHEIGHT : Grid box height : m : SCALEDYN +! (2) AD : Air mass in grid box : kg : SCALEDYN +! (3) AVGW : Mixing ratio of water vapor : v/v : SCALEDYN +! (4) N(AIR) : Number density of air : m^-3 : SCALEDYN +! +! NOTES: +! (1) We don't need to add TRCOFFSET to N. These are not CTM tracers. +! (2) Now replaced SCALE1 with SCALEDYN (bmy, 2/24/03) +! (3) Bug fix: replace ND68 with LD68 in call to BPCH2 (swu, bmy, 6/9/05) +!****************************************************************************** +! + IF ( ND68 > 0 ) THEN + CATEGORY = 'BXHGHT-$' + UNIT = '' + + DO M = 1, TMAX(68) + N = TINDEX(68,M) + IF ( N > PD68 ) CYCLE + NN = N + + DO L = 1, LD68 + ARRAY(:,:,L) = AD68(:,:,L,N) / SCALEDYN + ENDDO + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, NN, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD68, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD68) ) + ENDDO + ENDIF +! +!****************************************************************************** +! ND69: Grid Box Surface Areas +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) DXYP : Surface area of grid box : m^2 : SCALED = 1.0 +! +! NOTES: +! (1) Only print DXYP for the first timestep, as it is an invariant field. +! (2) We don't need to add TRCOFFSET to N. This is not a CTM tracer. +! (3) Now use the AD69 dynamically allocatable array (bmy, 2/17/00) +!****************************************************************************** +! + IF ( ND69 > 0 ) THEN + CATEGORY = 'DXYP' + UNIT = 'm2' + + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, AD69(:,:,1) ) + + ! Set ND69 = 0 so we won't print it out again + ND69 = 0 + ENDIF + + ! Echo output + WRITE( 6, '(a)' ) ' - DIAG3: Diagnostics written to bpch!' + + ! Return to calling program + END SUBROUTINE DIAG3 diff --git a/code/diag41_mod.f b/code/diag41_mod.f new file mode 100644 index 0000000..3c1c841 --- /dev/null +++ b/code/diag41_mod.f @@ -0,0 +1,370 @@ +! $Id: diag41_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE DIAG41_MOD +! +!****************************************************************************** +! Module DIAG41_MOD contains arrays and routines for archiving the ND41 +! diagnostic -- Afternoon PBL heights. (bmy, 2/17/05, 9/5/06) +! +! Module Variables: +! ============================================================================ +! (1 ) AD41 (REAL*4 ) : Array for afternoon PBL height +! (2 ) GOOD_CT (INTEGER) : Counter of grid boxes where it's afternoon +! +! Module Routines: +! ============================================================================ +! (1 ) ZERO_DIAG41 : Sets all module arrays to zero +! (2 ) WRITE_DIAG41 : Writes data in module arrays to bpch file +! (3 ) DIAG41 : Archives afternoon PBL heights +! (4 ) INIT_DIAG41 : Allocates all module arrays +! (4 ) CLEANUP_DIAG41 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag41_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary pch file I/O +! (2 ) error_mod.f : Module w/ NaN and other error check routines +! (3 ) file_mod.f : Module w/ file unit numbers and error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (6 ) time_mod.f : Module w/ routines to compute date & time! +! +! NOTES: +! (1 ) Updated for GCAP grid (bmy, 6/28/05) +! (2 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (3 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag41_mod.f" + !================================================================= + + ! Make everything PUBLIC ... + PUBLIC + + ! ... except these routines + PRIVATE :: AD41 + PRIVATE :: GOOD_CT + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + INTEGER :: ND41 + INTEGER, PARAMETER :: PD41 = 2 + + ! Arrays + INTEGER, ALLOCATABLE :: GOOD_CT(:) + REAL*4, ALLOCATABLE :: AD41(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE ZERO_DIAG41 +! +!****************************************************************************** +! Subroutine ZERO_DIAG41 zeroes the ND41 diagnostic arrays (bmy, 2/17/05) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: I, J, N + + !================================================================= + ! ZERO_DIAG41 begins here! + !================================================================= + + ! Exit if ND41 is turned off + IF ( ND41 == 0 ) RETURN + + ! Zero GOOD_CT + DO I = 1, IIPAR + GOOD_CT(I) = 0 + ENDDO + + ! Zero AD41 +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, N ) + DO N = 1, PD41 + DO J = 1, JJPAR + DO I = 1, IIPAR + AD41(I,J,N) = 0e0 + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE ZERO_DIAG41 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG41 +! +!****************************************************************************** +! Subroutine WRITE_DIAG41 writes the ND41 diagnostic arrays to the binary +! punch file at the proper time. (bmy, 2/17/05, 10/3/05) +! +! ND41: Afternoon PBL depth (between 1200 and 1600 Local Time) +! +! # Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1) PBLDEPTH : Afternoon PBL heights : m : GOOD_CT +! +! NOTES: +! (1 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (2 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (3 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_HALFPOLAR, GET_MODELNAME + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : GET_CT_EMIS, GET_DIAGb, GET_DIAGe + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! TINDEX + + ! Local variables + INTEGER :: I, J, M, N + INTEGER :: CENTER180, HALFPOLAR, IFIRST + INTEGER :: JFIRST, LFIRST, LMAX + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR) + REAL*4 :: LONRES, LATRES, EPS + REAL*8 :: DIAGb, DIAGe, SCALE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY, RESERVED, UNIT + + !================================================================= + ! WRITE_DIAG41 begins here! + !================================================================= + + ! Exit if ND41 is turned off + IF ( ND41 == 0 ) RETURN + + ! Initialize + CATEGORY = 'PBLDEPTH' + CENTER180 = 1 + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + HALFPOLAR = GET_HALFPOLAR() + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LATRES = DJSIZE + LFIRST = 1 + LONRES = DISIZE + MODELNAME = GET_MODELNAME() + RESERVED = '' + EPS = 1d-32 + + !================================================================= + ! Write data to the bpch file + !================================================================= + + ! Loop over ND41 diagnostic tracers + DO M = 1, TMAX(41) + N = TINDEX(41,M) + IF ( N > PD41 ) CYCLE + + ! Select proper unit string + IF ( N == 1 ) UNIT = 'm' + IF ( N == 2 ) UNIT = 'level' + + ! Divide by # of afternoon boxes at each longitude + DO J = 1, JJPAR + DO I = 1, IIPAR + SCALE = DBLE( GOOD_CT(I) ) + EPS + ARRAY(I,J,1) = AD41(I,J,N) / SCALE + ENDDO + ENDDO + + ! Write to bpch file + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + + ! Return to calling program + END SUBROUTINE WRITE_DIAG41 + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG41 +! +!****************************************************************************** +! Subroutine DIAG41 produces monthly mean boundary layer height in meters +! between 1200-1600 local time for the U.S. geographical domain. +! (amf, swu, bmy, 11/18/99, 11/6/03) +! +! Input via "CMN" header file: +! =========================================================================== +! (1 ) XTRA2 : Height of PBL in boxes +! +! NOTES: +! (1 ) DIAG41 is written in Fixed-Format F90. +! (2 ) XTRA2 must be computed by turning TURBDAY on first. Also, +! XTRA2 is a global-size array, so use window offsets IREF, JREF +! to index it correctly. (bmy, 11/18/99) +! (3 ) Do a little rewriting so that the DO-loops get executed +! in the correct order (J first, then I). (bmy, 11/18/99) +! (4 ) AD41 is now declared allocatable in "diag_mod.f". (bmy, 12/6/99) +! (5 ) AFTTOT is now declared allocatable in "diag_mod.f". (bmy, 3/17/00) +! (6 ) Remove NYMD from the argument list -- it wasn't used (bmy, 6/22/00) +! (7 ) XTRA2(IREF,JREF,5) is now XTRA2(I,J). Also updated comments. +! (bmy, 9/25/01) +! (8 ) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (9 ) Now reference BXHEIGHT from "dao_mod.f". Also removed obsolete +! code. (bmy, 9/18/02) +! (10) Now use function GET_LOCALTIME from "dao_mod.f" (bmy, 2/11/03) +! (11) Bug fix in DO-loop for calculating local time (bmy, 7/9/03) +! (12) For GEOS-4, PBL depth is already in meters, so we only have to +! multiply that by the GOOD array. Also now references PBL array +! from "dao_mod.f". Bug fix: now use barometric law to compute PBL +! height in meters for GEOS-1, GEOS-STRAT, GEOS-3. This eliminates an +! overprediction of the PBL height. (swu, bmy, 11/6/03) +!****************************************************************************** +! + ! References to F90 modules + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE TIME_MOD, ONLY : GET_LOCALTIME + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: I, J, N, GOOD(IIPAR) + REAL*8 :: LT, PBLTOP + + !================================================================= + ! DIAG41 begins here! + !================================================================= + + !----------------------------------- + ! Find boxes where it is afternoon + !----------------------------------- + DO I = 1, IIPAR + + ! Local time + LT = GET_LOCALTIME( I ) + + ! Find points between 12 and 16 GMT + IF ( LT >= 12d0 .and. LT <= 16d0 ) THEN + GOOD(I) = 1 + ELSE + GOOD(I) = 0 + ENDIF + + ! Increment counter of afternoon boxes + GOOD_CT(I) = GOOD_CT(I) + GOOD(I) + ENDDO + + !----------------------------------- + ! Archive afternoon PBL heights + !----------------------------------- +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, N, PBLTOP ) + DO N = 1, PD41 + DO J = 1, JJPAR + DO I = 1, IIPAR + + IF ( N == 1 ) THEN + + ! Afternoon PBL top [m] + PBLTOP = GET_PBL_TOP_m( I, J ) * GOOD(I) + + ELSE IF ( N == 2 ) THEN + + ! Afternoon PBL top [model layers] + PBLTOP = GET_PBL_TOP_L( I, J ) * GOOD(I) + + ENDIF + + ! Store in AD41 array + AD41(I,J,N) = AD41(I,J,N) + PBLTOP + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DIAG41 + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG41 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG41 allocates all module arrays (bmy, 2/17/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DIAG41 begins here! + !================================================================= + + ! Exit if ND41 is turned off + IF ( ND41 == 0 ) RETURN + + ! Counter of afternoon pts + ALLOCATE( GOOD_CT( IIPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT' ) + + ! Diagnostic array + ALLOCATE( AD41( IIPAR, JJPAR, PD41 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD41' ) + + ! Zero arrays + CALL ZERO_DIAG41 + + ! Return to calling program + END SUBROUTINE INIT_DIAG41 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG41 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG41 deallocates all module arrays (bmy, 2/17/05) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG41 begins here! + !================================================================= + IF ( ALLOCATED( AD41 ) ) DEALLOCATE( AD41 ) + IF ( ALLOCATED( GOOD_CT ) ) DEALLOCATE( GOOD_CT ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG41 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG41_MOD diff --git a/code/diag42_mod.f b/code/diag42_mod.f new file mode 100644 index 0000000..f98dc39 --- /dev/null +++ b/code/diag42_mod.f @@ -0,0 +1,425 @@ +! $Id: diag42_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE DIAG42_MOD +! +!****************************************************************************** +! Module DIAG42_MOD contains arrays and routines for archiving the ND42 +! diagnostic -- secondary organic aerosols [ug/m3]. (dkh,bmy,5/22/06,3/29/07) +! +! Module Variables: +! ============================================================================ +! (1 ) AD42 (REAL*4) : Array for SOA concentrations [ug/m3] +! +! Module Routines: +! ============================================================================ +! (1 ) DIAG42 : Archives quantities for diagnostic +! (2 ) ZERO_DIAG42 : Sets all module arrays to zero +! (3 ) WRITE_DIAG42 : Writes data in module arrays to bpch file +! (4 ) INIT_DIAG42 : Allocates all module arrays +! (5 ) CLEANUP_DIAG42 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag03_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary pch file I/O +! (2 ) error_mod.f : Module w/ NaN and other error check routines +! (3 ) file_mod.f : Module w/ file unit numbers and error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (6 ) time_mod.f : Module w/ routines to compute date & time +! +! NOTES: +! (1 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (2 ) Now use ratio of 2.1 instead of 1.4 for SOA4 (dkh, bmy, 3/29/07) +! (3 ) Add diagnostics for SOAG and SOAM (tmf, 1/7/09) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag42_mod.f" + !================================================================= + + ! Make everything PUBLIC + PUBLIC + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + INTEGER :: ND42, LD42 + + ! Parameters + INTEGER, PARAMETER :: PD42 = 14 + + ! Arrays + REAL*4, ALLOCATABLE :: AD42(:,:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG42 +! +!****************************************************************************** +! Subroutine DIAG42 archives SOA concentrations [ug/m3] for the ND42 +! diagnostic. (dkh, bmy, 5/22/06, 3/29/07) +! +! NOTES: +! (1 ) Now use ratio of 2.1 instead of 1.4 for SOA4 (dkh, bmy, 3/29/07) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AIRVOL, T + !USE DIAG_MOD, ONLY : LTOTH + USE PRESSURE_MOD, ONLY : GET_PCENTER + USE TRACER_MOD, ONLY : STT + USE TRACERID_MOD, ONLY : IDTSOA1, IDTSOA2, IDTSOA3, IDTSOA4 + USE TRACERID_MOD, ONLY : IDTOCPI, IDTOCPO + USE TRACERID_MOD, ONLY : IDTSOAG, IDTSOAM + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! NDxx flags + + ! Local variables + INTEGER :: I, J, L + REAL*8 :: FACTOR, PRES + + ! Factor for computing standard volume + REAL*8, PARAMETER :: STD_VOL_FAC = 1013.25d0 / 273.15d0 + + !================================================================= + ! DIAG42 begins here! + !================================================================= + + ! Error check + IF ( IDTSOA1 == 0 ) RETURN + IF ( IDTSOA2 == 0 ) RETURN + IF ( IDTSOA3 == 0 ) RETURN + IF ( IDTSOA4 == 0 ) RETURN + IF ( IDTOCPO == 0 ) RETURN + IF ( IDTOCPI == 0 ) RETURN + + ! Loop over grid boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, FACTOR, PRES ) + DO L = 1, LD42 + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Conversion factor from [kg] --> [ug/m3] + ! (LTOTH=1 if between OTH_HR1 and OTH_HR2, LTOTH=0 otherwise) + !FACTOR = 1d9 / AIRVOL(I,J,L) * LTOTH(I,J) + + ! Conversion factor from [kg] --> [ug/m3] + FACTOR = 1d9 / AIRVOL(I,J,L) + + ! SOA1 [ug/m3] + AD42(I,J,L,1) = AD42(I,J,L,1) + + & ( STT(I,J,L,IDTSOA1) * FACTOR ) + + ! SOA2 [ug/m3] + AD42(I,J,L,2) = AD42(I,J,L,2) + + & ( STT(I,J,L,IDTSOA2) * FACTOR ) + + ! SOA3 [ug/m3] + AD42(I,J,L,3) = AD42(I,J,L,3) + + & ( STT(I,J,L,IDTSOA3) * FACTOR ) + + ! SOA4 [ug/m3] + AD42(I,J,L,4) = AD42(I,J,L,4) + + & ( STT(I,J,L,IDTSOA4) * FACTOR ) + + ! Sum of original 3 SOA types [ug/m3] + AD42(I,J,L,5) = AD42(I,J,L,5) + + & ( STT(I,J,L,IDTSOA1) + + & STT(I,J,L,IDTSOA2) + + & STT(I,J,L,IDTSOA3) ) * FACTOR + + ! Sum of SOA1 to SOA4 + AD42(I,J,L,6) = AD42(I,J,L,6) + + & ( STT(I,J,L,IDTSOA1) + + & STT(I,J,L,IDTSOA2) + + & STT(I,J,L,IDTSOA3) + + & STT(I,J,L,IDTSOA4) ) * FACTOR + + ! Sum of primary OC + SOA1 to SOA4 [ug C/m3] + ! Use higher ratio (2.1) of molecular weight of + ! organic mass per carbon mass accounting for non-carbon + ! components attached to OC [Turpin and Lim, 2001] + AD42(I,J,L,7) = AD42(I,J,L,7) + + & ( ( STT(I,J,L,IDTSOA1) + + & STT(I,J,L,IDTSOA2) + + & STT(I,J,L,IDTSOA3) + + & STT(I,J,L,IDTSOA4) ) / 2.1d0 + & + ( STT(I,J,L,IDTOCPO) + + & STT(I,J,L,IDTOCPI) ) ) * FACTOR + + ! Sum of PRIMARY OC + SOA1 to SOA4 [ug C/m3] at STP + PRES = GET_PCENTER( I, J, L ) + AD42(I,J,L,8) = AD42(I,J,L,7) * STD_VOL_FAC * T(I,J,L) / PRES + +!-------------------------------------------------------- +! Additional diagnostics for SOAG, SOAM (tmf, 12/8/07) +! Assume SOAG mass = GLYX mass, SOAM mass = MGLY mass +! Test if SOAG and SOAM are simulated (ccc, 12/18/08) +!-------------------------------------------------------- + IF ( IDTSOAG /= 0 .AND. IDTSOAM /=0 ) THEN + ! SOAG [ug total mass /m3] + AD42(I,J,L,9) = AD42(I,J,L,9) + + & ( STT(I,J,L,IDTSOAG) * 1.d0 * FACTOR ) + + ! SOAM [ug total mass /m3] + AD42(I,J,L,10) = AD42(I,J,L,10) + + & ( STT(I,J,L,IDTSOAM) * 1.d0 * FACTOR ) + + + ! Sum of SOA1 to SOA4, SOAG, SOAM (tmf, 1/31/07) + AD42(I,J,L,11) = AD42(I,J,L,11) + + & ( STT(I,J,L,IDTSOA1) + + & STT(I,J,L,IDTSOA2) + + & STT(I,J,L,IDTSOA3) + + & STT(I,J,L,IDTSOA4) + + & ( STT(I,J,L,IDTSOAG) * 1.d0 ) + + & ( STT(I,J,L,IDTSOAM) * 1.d0 )) * FACTOR + + ! Sum of SOA1 to SOA4, SOAG, SOAM in carbon (tmf, 1/31/07) + ! Except SOAG is 0.41 carbon, SOAM is 0.5 carbon + AD42(I,J,L,12) = AD42(I,J,L,12) + + & ( ( STT(I,J,L,IDTSOA1) + + & STT(I,J,L,IDTSOA2) + + & STT(I,J,L,IDTSOA3) + + & STT(I,J,L,IDTSOA4) ) / 2.1d0 + + & ( STT(I,J,L,IDTSOAG) * 0.41D0 ) + + & ( STT(I,J,L,IDTSOAM) * 0.50D0 ) + + & ( STT(I,J,L,IDTOCPO) + + & STT(I,J,L,IDTOCPI) ) ) * FACTOR + + ! Sum of SOA1 to SOA4, SOAG, SOAM at STP [ug/sm3 STP] (tmf, 1/31/07) + PRES = GET_PCENTER( I, J, L ) + AD42(I,J,L,13) = AD42(I,J,L,11) * STD_VOL_FAC * T(I,J,L) + & / PRES + + ! Sum of all OC [ug C/sm3] at STP (including SOAG, SOAM) + AD42(I,J,L,14) = AD42(I,J,L,12) * STD_VOL_FAC * T(I,J,L) + & / PRES + ENDIF + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DIAG42 + +!------------------------------------------------------------------------------ + + SUBROUTINE ZERO_DIAG42 +! +!****************************************************************************** +! Subroutine ZERO_DIAG42 zeroes the ND03 diagnostic arrays. +! (dkh, bmy, 5/22/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! ZERO_DIAG42 begins here! + !================================================================= + + ! Exit if ND42 is turned off + IF ( ND42 == 0 ) RETURN + + ! Zero arrays + AD42(:,:,:,:) = 0e0 + + ! Return to calling program + END SUBROUTINE ZERO_DIAG42 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG42 +! +!****************************************************************************** +! Subroutine WRITE_DIAG03 writes the ND03 diagnostic arrays to the binary +! punch file at the proper time. (bmy, 5/22/06, 9/5/06) +! +! # : Field : Description : Units : Scale factor +! ----------------------------------------------------------------------- +! (1 ) IJ-SOA-$ : SOA1 : ug/m3 : SCALE_OTH +! (2 ) IJ-SOA-$ : SOA2 : ug/m3 : SCALE_OTH +! (3 ) IJ-SOA-$ : SOA3 : ug/m3 : SCALE_OTH +! (4 ) IJ-SOA-$ : SOA4 : ug/m3 : SCALE_OTH +! (5 ) IJ-SOA-$ : SOA1 + SOA2 + SOA3 : ug/m3 : SCALE_OTH +! (6 ) IJ-SOA-$ : SOA1 + SOA2 + SOA3 + SOA4 : ug/m3 : SCALE_OTH +! (7 ) IJ-SOA-$ : Sum of all Org Carbon : ug C/m3 : SCALE_OTH +! (8 ) IJ-SOA-$ : Sum of all Org Carbon @ STP : ug C/sm3 : SCALE_OTH +! +! NOTES: +! (1 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_MODELNAME, GET_HALFPOLAR + !USE DIAG_MOD, ONLY : CTOTH + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : GET_CT_DYN, GET_DIAGb, GET_DIAGe + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! TINDEX + + ! Local variables + INTEGER :: CENTER180, HALFPOLAR + INTEGER :: L, M, N + INTEGER :: IFIRST, JFIRST, LFIRST + REAL*4 :: LONRES, LATRES + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR) + !REAL*8 :: SCALE(IIPAR,JJPAR) + REAL*8 :: SCALE + REAL*8 :: DIAGb, DIAGe + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: RESERVED + CHARACTER(LEN=40) :: UNIT + + !================================================================= + ! WRITE_DIAG42 begins here! + !================================================================= + + ! Exit if ND03 is turned off + IF ( ND42 == 0 ) RETURN + + ! Initialize + CENTER180 = 1 + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + HALFPOLAR = GET_HALFPOLAR() + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LATRES = DJSIZE + LFIRST = 1 + LONRES = DISIZE + MODELNAME = GET_MODELNAME() + RESERVED = '' + !SCALE = FLOAT( CTOTH ) + TINY( 1d0 ) + !SCALE = DBLE( GET_CT_DYN() ) + TINY( 1d0 ) + SCALE = DBLE( GET_CT_DYN() ) + TINY( 1e0 ) + + !================================================================= + ! Write data to the bpch file + !================================================================= + + ! Loop over ND03 diagnostic tracers + DO M = 1, TMAX(42) + + ! Define quantities + N = TINDEX(42,M) + CATEGORY = 'IJ-SOA-$' + + ! Pick proper unit + SELECT CASE ( N ) + CASE( 7 ) + UNIT = 'ug C/m3' + CASE( 8 ) + UNIT = 'ug C/sm3' + CASE( 12 ) + UNIT = 'ug C/m3' + CASE( 13 ) + UNIT = 'ug/sm3' + CASE( 14 ) + UNIT = 'ug C/sm3' + CASE DEFAULT + UNIT = 'ug/m3' + END SELECT + + ! Apply scale factor + DO L = 1, LD42 + !ARRAY(:,:,L) = AD42(:,:,L,N) / SCALE(:,:) + ARRAY(:,:,L) = AD42(:,:,L,N) / SCALE + ENDDO + + ! Write data to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD42, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD42) ) + ENDDO + + ! Return to calling program + END SUBROUTINE WRITE_DIAG42 + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG42 +! +!****************************************************************************** +! Subroutine INIT_DIAG42 allocates all module arrays (bmy, 5/22/06) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LSOA + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DIAG42 begins here! + !================================================================= + + ! Turn off ND42 if SOA tracers are not used + IF ( .not. LSOA ) THEN + ND42 = 0 + RETURN + ENDIF + + ! Exit if ND42 is turned off + IF ( ND42 == 0 ) RETURN + + ! Number of levels to save for this diagnostic + LD42 = MIN( ND42, LLPAR ) + + ! 2-D array ("LFLASH-$") + ALLOCATE( AD42( IIPAR, JJPAR, LD42, PD42 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD42' ) + + ! Zero arrays + CALL ZERO_DIAG42 + + ! Return to calling program + END SUBROUTINE INIT_DIAG42 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG42 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG42 deallocates all module arrays (bmy, 5/22/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG42 begins here! + !================================================================= + IF ( ALLOCATED( AD42 ) ) DEALLOCATE( AD42 ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG42 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG42_MOD diff --git a/code/diag48_mod.f b/code/diag48_mod.f new file mode 100644 index 0000000..5a1a9c1 --- /dev/null +++ b/code/diag48_mod.f @@ -0,0 +1,922 @@ +! $Id: diag48_mod.f,v 1.2 2009/11/18 07:09:33 daven Exp $ + MODULE DIAG48_MOD +! +!****************************************************************************** +! Module DIAG48_MOD contains variables and routines to save out 3-D +! timeseries output to disk (bmy, 7/20/04, 10/7/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_DIAG48 (LOGICAL ) : Switch to turn ND49 timeseries on/off +! (2 ) I0 (INTEGER ) : Lon offset between global & nested grid +! +! Module Routines: +! ============================================================================ +! (1 ) DIAG48 : Main driver routine +! (2 ) ITS_TIME_FOR_DIAG48 : Returns TRUE if it's time to save to disk +! (3 ) INIT_DIAG48 : Gets variable values from "input_mod.f" +! +! GEOS-CHEM modules referenced by "diag48_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) file_mod.f : Module w/ file unit numbers & error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (6 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (7 ) time_mod.f : Module w/ routines for computing time & date +! (8 ) tracer_mod.f : Module w/ GEOS-CHEM tracer array STT etc. +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND48 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D Cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box heights [m ] +! 94 : Relative humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Now save out cld frac and grid box heights (bmy, 4/20/05) +! (2 ) Remove TRCOFFSET because it's always zero. Now call GET_HALFPOLAR +! to get the value for GEOS or GCAP grids. (bmy, 6/28/05) +! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (4 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (5 ) Minor bug fixes in DIAG48 (cdh, bmy, 2/11/08) +! (6 ) Bug fix: replace "PS-PTOP" with "PEDGE-$" (phs, bmy, 10/7/08) +! (7 ) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 10/22/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag48_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG48 + PUBLIC :: ND48_MAX_STATIONS + + ! ... and these routines + PUBLIC :: CLEANUP_DIAG48 + PUBLIC :: DIAG48 + PUBLIC :: INIT_DIAG48 + PUBLIC :: ITS_TIME_FOR_DIAG48 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_DIAG48 + INTEGER, PARAMETER :: ND48_MAX_STATIONS=1000 + INTEGER :: ND48_FREQ + INTEGER :: ND48_N_STATIONS + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES + REAL*4 :: LATRES + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = 'ND48 station timeseries' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND48_OUTPUT_FILE + + ! Arrays + INTEGER, ALLOCATABLE :: ND48_I(:) + INTEGER, ALLOCATABLE :: ND48_J(:) + INTEGER, ALLOCATABLE :: ND48_L(:) + INTEGER, ALLOCATABLE :: ND48_N(:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG48 +! +!****************************************************************************** +! Subroutine DIAG48 saves station time series diagnostics to disk. +! (bmy, bey, amf, 6/1/99, 10/7/08) +! +! NOTES: +! (1 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (2 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D cloud +! fraction as tracer #79 and box height as tracer #93. Now remove +! reference to PBL from "dao_mod.f" (bmy, 4/20/05) +! (3 ) Remove references to TRCOFFSET because it's always zero. Now call +! GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag value for +! GEOS or GCAP grids. (bmy, 6/28/05) +! (4 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (5 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (6 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (7 ) Bug fix: unit for tracer #77 should be "layers". Also RH should be +! tracer #17 under "TIME-SER" category. (cdh, bmy, 2/11/08) +! (8 ) Bug fix: replace "PS-PTOP" with "PEDGE-$" (phs, bmy, 10/7/08) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2 + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, SLP + USE DAO_MOD, ONLY : T, UWND, VWND + USE ERROR_MOD, ONLY : ERROR_STOP + USE FILE_MOD, ONLY : IU_ND48 + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : GET_LOCALTIME, GET_NYMD + USE TIME_MOD, ONLY : GET_NHMS, GET_TAU + USE TIME_MOD, ONLY : EXPAND_DATE, ITS_A_NEW_DAY + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM, N_TRACERS + USE TRACER_MOD, ONLY : STT, TCVV + USE TRACER_MOD, ONLY : XNUMOLAIR + USE TRACERID_MOD, ONLY : IDTHNO3, IDTN2O5, IDTHNO4, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + +# include "cmn_fj.h" ! Size parameters + FAST-J stuff +# include "jv_cmn.h" ! ODAER, ODMDUST, QAA, QAA_OUT +# include "CMN_O3" ! XNUMOLAIR +# include "CMN_GCTM" ! SCALE_HEIGHT + + ! Local variables + LOGICAL, SAVE :: IS_CLDTOPS, IS_OPTD, IS_SEASALT, IS_SLP + LOGICAL, SAVE :: IS_FULLCHEM, IS_Ox, IS_NOx, IS_NOy + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: GMTRC, I, I0, J, J0, L, N, K, R, TMP, W + REAL*8 :: LT, TAU, Q(LLPAR), SCALEAODnm + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + + !================================================================= + ! DIAG48 begins here! + !================================================================= + + ! Get grid offsets + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + ! First-time initialization + IF ( FIRST ) THEN + + ! Set logical flags on first timestep + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_OPTD = ALLOCATED( OPTD ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOX > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + + ! Replace YYYYMMDD tokens in filename + FILENAME = TRIM( ND48_OUTPUT_FILE ) + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Open file for writing + CALL OPEN_ND48_FILE( FILENAME ) + + ! Reset first-time flag + FIRST = .FALSE. + ENDIF + + !================================================================= + ! Store station timeseries data in the Q array + !================================================================= + + ! Get TAU value + TAU = GET_TAU() + + ! Loop over each station + DO W = 1, ND48_N_STATIONS + + ! Get lon, lat, alt, tracer indices + I = ND48_I(W) + J = ND48_J(W) + K = ND48_L(W) + N = ND48_N(W) + + ! Get local time + LT = GET_LOCALTIME( I ) + + ! Initialize + Q(:) = 0 + + IF ( N <= N_TRACERS ) THEN + + !------------------------------------ + ! GEOS-CHEM tracers [v/v] + !------------------------------------ + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick the unit + GMTRC = N + + DO L = 1, K + Q(L) = STT(I,J,L,N) * TCVV(N) / AD(I,J,L) + ENDDO + + ELSE IF ( N == 89 .and. IS_Ox ) THEN + + !------------------------------------ + ! PURE O3 CONCENTRATION [v/v] + !------------------------------------ + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick the unit + GMTRC = N_TRACERS + 1 + + DO L = 1, K + Q(L) = STT(I,J,L,IDTOX) * TCVV(IDTOX) / + & AD(I,J,L) * FRACO3(I,J,L) + ENDDO + + ELSE IF ( N == 90 .and. IS_NOx ) THEN + + !------------------------------------ + ! NO CONCENTRATION [v/v] + !------------------------------------ + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick the unit + GMTRC = 9 + + DO L = 1, K + Q(L) = STT(I,J,L,IDTNOX) * TCVV(IDTNOX) * + & FRACNO(I,J,L) / AD(I,J,L) + ENDDO + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !------------------------------------- + ! NOy CONCENTRATION [v/v] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMTRC = 3 + + DO L = 1, K + + ! Initialize + Q(L) = 0d0 + + ! NOx + Q(L) = Q(L) + ( TCVV(IDTNOX) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + + ! PAN + Q(L) = Q(L) + ( TCVV(IDTPAN) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + Q(L) = Q(L) + ( TCVV(IDTHNO3) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + Q(L) = Q(L) + ( TCVV(IDTPMN) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + Q(L) = Q(L) + ( TCVV(IDTPPN) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + Q(L) = Q(L) + ( TCVV(IDTR4N2) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + Q(L) = Q(L) + ( 2d0 * TCVV(IDTN2O5) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + Q(L) = Q(L) + ( TCVV(IDTHNO4) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + ENDDO + + ELSE IF ( N == 74 .and. IS_FULLCHEM ) THEN + + !------------------------------------ + ! OH CONCENTRATION [molec/cm3] + !------------------------------------ + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMTRC = 2 + + DO L = 1, K + Q(L) = SAVEOH(I,J,L) + ENDDO + + + ELSE IF ( N == 75 .and. IS_FULLCHEM ) THEN + + !------------------------------------ + ! NO2 CONCENTRATION [molec/cm3] + !------------------------------------ + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick the unit + GMTRC = 19 + + DO L = 1, K + Q(L) = SAVENO2(I,J,L) + ENDDO + + ELSE IF ( N == 76 ) THEN + + !------------------------------------- + ! PBL HEIGHTS [m] + !------------------------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMTRC = 1 + + IF ( K == 1 ) THEN + Q(1) = GET_PBL_TOP_m( I, J ) + ENDIF + + ELSE IF ( N == 77 ) THEN + + !------------------------------------- + ! PBL HEIGHTS [layers] + !------------------------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMTRC = 2 + + IF ( K == 1 ) THEN + Q(1) = GET_PBL_TOP_L( I, J ) + ENDIF + + ELSE IF ( N == 78 ) THEN + + !------------------------------------- + ! AIR DENSITY [molec/cm3] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMTRC = 22 + + DO L = 1, K + Q(L) = AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 + ENDDO + + ELSE IF ( N == 79 ) THEN + + !------------------------------------- + ! CLOUD FRACTIONS [unitless] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMTRC = 19 + + DO L = 1, K + Q(L) = CLDF(L,I,J) + ENDDO + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !--------------------------------------- + ! COLUMN OPTICAL DEPTHS [unitless] + !--------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMTRC = 20 + + Q(1) = SUM( OPTD(:,I,J) ) + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !--------------------------------------- + ! CLOUD TOP HEIGHTS [hPa] + !--------------------------------------- + CATEGORY = 'TIME_SER' + UNIT = 'hPa' + GMTRC = 21 + + IF ( K == 1 ) THEN + Q(1) = GET_PEDGE( I, J, CLDTOPS(I,J) ) + ENDIF + + ELSE IF ( N == 82 ) THEN + + !--------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + !--------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMTRC = 6 + + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+R-1) / QAA(4,IND(1)+R-1) + + DO L = 1, K + Q(L) = ODAER(I,J,L,R) * SCALEAODnm + ENDDO + ENDDO + + ELSE IF ( N == 83 ) THEN + + !------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + !------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMTRC = 9 + + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + + DO L = 1, K + Q(L) = ODAER(I,J,L,NRH+R) * SCALEAODnm + ENDDO + ENDDO + + ELSE IF ( N == 84 ) THEN + + !----------------------------------- + ! ORGANIC CARBON AOD [unitless] + !----------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMTRC = 12 + + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + + DO L = 1, K + Q(L) = ODAER(I,J,L,2*NRH+R) * SCALEAODnm + ENDDO + ENDDO + + ELSE IF ( N == 85 ) THEN + + !------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + !------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMTRC = 15 + + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + + DO L = 1, K + Q(L) = ODAER(I,J,L,3*NRH+R) * SCALEAODnm + ENDDO + ENDDO + + ELSE IF ( N == 86 ) THEN + + !------------------------------------- + ! COARSE SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + !------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMTRC = 18 + + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + + DO L = 1, K + Q(L) = ODAER(I,J,L,4*NRH+R) * SCALEAODnm + ENDDO + ENDDO + + ELSE IF ( N == 87 ) THEN + + !----------------------------------- + ! TOTAL DUST OPT DEPTH [unitless] + !----------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMTRC = 4 + + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + + DO L = 1, K + !Q(L) = ODMDUST(I,J,L,R) + Q(L) = ODMDUST(I,J,L,R) + SCALEAODnm + ENDDO + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !----------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !----------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMTRC = 24 + + DO L = 1, K + Q(L) = ( STT(I,J,L,IDTSALA) + STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) + ENDDO + + ELSE IF ( N == 93 ) THEN + + !----------------------------------- + ! GRID BOX HEIGHTS [m] + !----------------------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMTRC = 1 + + DO L = 1, K + Q(L) = BXHEIGHT(I,J,L) + ENDDO + + ELSE IF ( N == 94 ) THEN + + !----------------------------------- + ! RELATIVE HUMIDITY [%] + !----------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMTRC = 17 + + DO L = 1, K + Q(L) = RH(I,J,L) + ENDDO + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !----------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !----------------------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMTRC = 21 + + IF ( K == 1 ) THEN + Q(1) = SLP(I,J) + ENDIF + + ELSE IF ( N == 96 ) THEN + + !----------------------------------- + ! ZONAL (U) WIND [M/S] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMTRC = 1 + + DO L = 1, K + Q(L) = UWND(I,J,L) + ENDDO + + ELSE IF ( N == 97 ) THEN + + !----------------------------------- + ! ZONAL (V) WIND [M/S] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMTRC = 2 + + DO L = 1, K + Q(L) = VWND(I,J,L) + ENDDO + + ELSE IF ( N == 98 ) THEN + + !----------------------------------- + ! PEDGE-$ (prs @ level edges) [hPa] + !----------------------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMTRC = 1 + + DO L = 1, K + Q(L) = GET_PEDGE(I,J,L) + ENDDO + + ELSE IF ( N == 99 ) THEN + + !----------------------------------- + ! TEMPERATURE [K] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'K' + GMTRC = 3 + + DO L = 1, K + Q(L) = T(I,J,L) + ENDDO + + ELSE + + ! Skip other tracers + CYCLE + + ENDIF + + !============================================================== + ! Write each station to a bpch file + !============================================================== + CALL BPCH2( IU_ND48, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, GMTRC, + & UNIT, TAU, TAU, RESERVED, + & 1, 1, K, I+I0, + & J+J0, 1, REAL( Q(1:K) ) ) + + ENDDO + + !================================================================= + ! Close the file at the proper time + !================================================================= +! IF ( ITS_TIME_TO_CLOSE_FILE() ) THEN +! +! ! Expand date tokens in the file name +! FILENAME = TRIM( ND49_OUTPUT_FILE ) +! CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) +! +! ! Echo info +! WRITE( 6, 120 ) TRIM( FILENAME ) +! 120 FORMAT( ' - DIAG49: Closing file : ', a ) +! +! ! Close file +! CLOSE( IU_ND49 ) +! ENDIF + + ! Flush the file once per day + IF ( ITS_A_NEW_DAY() ) CALL FLUSH( IU_ND48 ) + + ! Return to calling program + END SUBROUTINE DIAG48 + +!------------------------------------------------------------------------------ + + SUBROUTINE OPEN_ND48_FILE( FILENAME ) +! +!****************************************************************************** +! Subroutine OPEN_ND48_FILE opens a binary punch file (version 2.0) +! for writing GEOS-CHEM ND48 station timeseries data. (bmy, 7/30/02) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FILENAME (CHARACTER) : Name of the file to be opened +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE FILE_MOD, ONLY : IU_ND48, IOERROR + + ! Arguments + CHARACTER(LEN=*), INTENT(IN) :: FILENAME + + ! Local variables + INTEGER :: IOS + CHARACTER(LEN=40) :: FTI + CHARACTER(LEN=80) :: TITLE + + !================================================================= + ! OPEN_ND48_FOR_WRITE begins here! + !================================================================= + + ! Initialize + FTI = 'CTM bin 02 -- GEOS-CHEM station ts' + TITLE = 'GEOS-CHEM ND48 station timeseries diagnostic' + + ! Open file for output + OPEN( IU_ND48, FILE=TRIM( FILENAME ), STATUS='UNKNOWN', + & IOSTAT=IOS, FORM='UNFORMATTED', ACCESS='SEQUENTIAL' ) + + ! Error check + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_ND48, 'open_nd48_file:1' ) + + ! Write file type identifier + WRITE ( IU_ND48, IOSTAT=IOS ) FTI + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_ND48, 'open_nd48_file:2' ) + + ! Write top title + WRITE ( IU_ND48, IOSTAT=IOS ) TITLE + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_ND48, 'open_nd48_file:3' ) + + ! Return to calling program + END SUBROUTINE OPEN_ND48_FILE + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_DIAG48() RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_DIAG48 returns TRUE if it's time for the next +! timeseries data write. (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_ELAPSED_MIN + + ! Local variables + LOGICAL :: ITS_TIME + INTEGER :: XMIN + + !================================================================= + ! ITS_TIME_FOR_DIAG48 begins here! + !================================================================= + + ! Get elapsed minutes + XMIN = GET_ELAPSED_MIN() + + ! Is it time to save the next timeseries station? + ITS_TIME = ( DO_SAVE_DIAG48 .and. MOD( XMIN, ND48_FREQ ) == 0 ) + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_DIAG48 + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG48( DO_ND48, FREQ, N_STA, IARR, + & JARR, LARR, NARR, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG48 allocates and zeroes all module arrays (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND48 (LOGICAL ) : Switch to turn on ND49 timeseries diagnostic +! (2 ) FREQ (INTEGER ) : Frequency for saving to disk [min] +! (3 ) N_STA (INTEGER ) : Number of ND48 stations from "input_mod.f" +! (4 ) IARR (INTEGER ) : Array w/ ND48 lon indices from "input_mod.f" +! (5 ) JARR (INTEGER ) : Array w/ ND48 lat indices from "input_mod.f" +! (6 ) LARR (INTEGER ) : Array w/ ND48 alt indices from "input_mod.f" +! (7 ) NARR (INTEGER ) : Array w/ ND48 tracer indices from "input_mod.f" +! (8 ) FILE (CHAR*255) : ND48 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND48 + INTEGER, INTENT(IN) :: FREQ + INTEGER, INTENT(IN) :: N_STA + INTEGER, INTENT(IN) :: IARR(ND48_MAX_STATIONS) + INTEGER, INTENT(IN) :: JARR(ND48_MAX_STATIONS) + INTEGER, INTENT(IN) :: LARR(ND48_MAX_STATIONS) + INTEGER, INTENT(IN) :: NARR(ND48_MAX_STATIONS) + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + INTEGER :: AS, N + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG48 begins here! + !================================================================= + + ! Location string + LOCATION = 'INIT_DIAG48 ("diag48_mod.f")' + + !----------------------------- + ! Get values from input_mod.f + !----------------------------- + DO_SAVE_DIAG48 = DO_ND48 + ND48_FREQ = FREQ + ND48_N_STATIONS = N_STA + ND48_OUTPUT_FILE = TRIM( FILE ) + + ! Error check + IF ( ND48_N_STATIONS > ND48_MAX_STATIONS ) THEN + CALL ERROR_STOP( 'Too many ND48 stations!', LOCATION ) + ENDIF + + !------------------------------ + ! Allocate module arrays + !------------------------------ + ALLOCATE( ND48_I( ND48_N_STATIONS ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ND48_I' ) + + ALLOCATE( ND48_J( ND48_N_STATIONS ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ND48_J' ) + + ALLOCATE( ND48_L( ND48_N_STATIONS ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ND48_L' ) + + ALLOCATE( ND48_N( ND48_N_STATIONS ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ND48_N' ) + + !------------------------------- + ! Copy values & error check + !------------------------------- + DO N = 1, ND48_N_STATIONS + + ! Error check longitude + IF ( IARR(N) < 1 .or. IARR(N) > IIPAR ) THEN + CALL ERROR_STOP( 'Bad longitude index!', LOCATION ) + ELSE + ND48_I(N) = IARR(N) + ENDIF + + ! Error check latitude + IF ( JARR(N) < 1 .or. JARR(N) > JJPAR ) THEN + CALL ERROR_STOP( 'Bad latitude index!', LOCATION ) + ELSE + ND48_J(N) = JARR(N) + ENDIF + + ! Error check longitude + IF ( LARR(N) < 1 .or. LARR(N) > LLPAR ) THEN + CALL ERROR_STOP( 'Bad altitude index!', LOCATION ) + ELSE + ND48_L(N) = LARR(N) + ENDIF + + ! Tracer array + ND48_N(N) = NARR(N) + ENDDO + + !------------------------------- + ! For bpch file output + !------------------------------- + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Return to calling program + END SUBROUTINE INIT_DIAG48 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG48 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG48 deallocates all module arrays (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG48 begins here! + !================================================================= + IF ( ALLOCATED( ND48_I ) ) DEALLOCATE( ND48_I ) + IF ( ALLOCATED( ND48_J ) ) DEALLOCATE( ND48_J ) + IF ( ALLOCATED( ND48_L ) ) DEALLOCATE( ND48_L ) + IF ( ALLOCATED( ND48_N ) ) DEALLOCATE( ND48_N ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG48 + +!------------------------------------------------------------------------------ + + ! Return to calling program + END MODULE DIAG48_MOD diff --git a/code/diag49_mod.f b/code/diag49_mod.f new file mode 100644 index 0000000..aea03b9 --- /dev/null +++ b/code/diag49_mod.f @@ -0,0 +1,1359 @@ +! $Id: diag49_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE DIAG49_MOD +! +!****************************************************************************** +! Module DIAG49_MOD contains variables and routines to save out 3-D +! timeseries output to disk (bmy, 7/20/04, 10/7/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_DIAG49 (LOGICAL ) : Switch to turn ND49 timeseries on/off +! (2 ) I0 (INTEGER ) : Lon offset between global & nested grid +! (3 ) J0 (INTEGER ) : Lat offset between global & nested grid +! (4 ) IOFF (INTEGER ) : Offset between relative & absolute lon +! (5 ) JOFF (INTEGER ) : Offset between relative & absolute lat +! (6 ) LOFF (INTEGER ) : Offset between relative & absolute alt +! (7 ) ND49_IMIN (INTEGER ) : Minimum longitude index +! (8 ) ND49_IMAX (INTEGER ) : Maximum latitude index +! (9 ) ND49_JMIN (INTEGER ) : Minimum longitude index +! (10) ND49_JMAX (INTEGER ) : Maximum longitude index +! (11) ND49_LMIN (INTEGER ) : Minimum altitude index +! (12) ND49_LMAX (INTEGER ) : Maximum altitude index +! (13) ND49_FREQ (INTEGER ) : Frequency which to save to disk [min] +! (14) ND49_N_TRACERS (INTEGER ) : Number of tracers for ND49 timeseries +! (15) ND49_OUTPUT_FILE (CHAR*255) : Name of timeseries output file +! (16) ND49_TRACERS (INTEGER ) : Array w/ tracer #'s to save to disk +! (17) HALFPOLAR (INTEGER ) : Used for binary punch file write +! (18) CENTER180 (INTEGER ) : Used for binary punch file write +! (19) LONRES (REAL*4 ) : Used for binary punch file write +! (20) LATRES (REAL*4 ) : Used for binary punch file write +! (21) RESERVED (CHAR*40 ) : Used for binary punch file write +! (22) MODELNAME (CHAR*20 ) : Used for binary punch file write +! (23) TITLE (CHAR*80 ) : Used for binary punch file write +! +! Module Routines: +! ============================================================================ +! (1 ) DIAG49 : Main driver routine +! (2 ) ITS_TIME_TO_CLOSE_FILE : Returns TRUE if it's time to close ND49 file +! (3 ) ITS_TIME_FOR_DIAG49 : Returns TRUE if it's time to save to disk +! (4 ) GET_I : Converts relative longitude index to absolute +! (5 ) INIT_DIAG49 : Gets variable values from "input_mod.f" +! +! GEOS-CHEM modules referenced by "diag49_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) file_mod.f : Module w/ file unit numbers & error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (6 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (7 ) time_mod.f : Module w/ routines for computing time & date +! (8 ) tracer_mod.f : Module w/ GEOS-CHEM tracer array STT etc. +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND49 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box height [m ] +! 94 : Relative humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Bug fix: get I0, J0 properly for nested grids (bmy, 11/9/04) +! (2 ) Now references "pbl_mix_mod.f" (bmy, 2/16/05) +! (3 ) Now saves 3-D cld frac & grid box height (bmy, 4/20/05) +! (4 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (5 ) Bug fix: do not save SLP if it's not allocated (bmy, 8/2/05) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (8 ) Modified INIT_DIAG49 to save out transects (cdh, bmy, 11/30/06) +! (9 ) Bug fix: accumulate into Q(X,Y,K) for dust OD (qli, bmy, 4/30/07) +! (10) Minor bug fixes in DIAG49 (cdh, bmy, 2/11/08) +! (11) Bug fix: replace "PS-PTOP" with "PEDGE-$" +! (12) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 9/26/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag49_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG49 + + ! ... except these routines + PUBLIC :: DIAG49 + PUBLIC :: ITS_TIME_FOR_DIAG49 + PUBLIC :: INIT_DIAG49 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + LOGICAL :: DO_SAVE_DIAG49 + INTEGER :: IOFF, JOFF, LOFF + INTEGER :: I0, J0 + INTEGER :: ND49_N_TRACERS, ND49_TRACERS(134) + INTEGER :: ND49_IMIN, ND49_IMAX + INTEGER :: ND49_JMIN, ND49_JMAX + INTEGER :: ND49_LMIN, ND49_LMAX + INTEGER :: ND49_FREQ, ND49_NI + INTEGER :: ND49_NJ, ND49_NL + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES, LATRES + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = '' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND49_OUTPUT_FILE + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG49 +! +!****************************************************************************** +! Subroutine DIAG49 produces time series (instantaneous fields) for a +! geographical domain from the information read in timeseries.dat. Output +! will be in binary punch (BPCH) format. (bey, bmy, rvm, 4/9/99, 10/7/08) +! +! NOTES: +! (1 ) Now bundled into "diag49_mod.f". Now reference STT from +! "tracer_mod.f". Now scale aerosol & dust OD's to 400 nm. +! (bmy, rvm, aad, 7/9/04) +! (2 ) Updated tracer # for NO2 (bmy, 10/25/04) +! (3 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (4 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D cloud +! fraction as tracer #79 and box height as tracer #93. Now remove +! reference to PBL from "dao_mod.f"(bmy, 4/20/05) +! (5 ) Remove references to TRCOFFSET because it is always zero (bmy, 6/24/05) +! (6 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (7 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (8 ) Now references XNUMOLAIR from "tracer_mod.f". Bug fix: now must sum +! aerosol OD's over all RH bins. Also zero Q array. (bmy, 11/1/05) +! (9 ) Bug fix: accumulate into Q(X,Y,K) for dust OD (qli, bmy, 4/30/07) +! (10) Bug fix: UNIT should be "levels" for tracer 77. Also RH should be +! tracer #17 under "TIME-SER" category. (cdh, bmy, 2/11/08) +! (11) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : EMISS_ANTHR + USE BPCH2_MOD, ONLY : BPCH2, OPEN_BPCH2_FOR_WRITE + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, SLP + USE DAO_MOD, ONLY : T, UWND, VWND + USE FILE_MOD, ONLY : IU_ND49 + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : EXPAND_DATE + USE TIME_MOD, ONLY : GET_NYMD, GET_NHMS + USE TIME_MOD, ONLY : GET_TAU, GET_HOUR + USE TIME_MOD, ONLY : ITS_A_NEW_DAY, TIMESTAMP_STRING + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM, N_TRACERS + USE TRACER_MOD, ONLY : STT, TCVV + USE TRACER_MOD, ONLY : XNUMOLAIR + USE CHECKPT_MOD, ONLY : CHK_STT + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TRACERID_MOD, ONLY : IDTHNO3, IDTHNO4, IDTN2O5, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + USE TRACERID_MOD, ONLY : NEMANTHRO + +# include "cmn_fj.h" ! FAST-J stuff, includes CMN_SIZE +# include "jv_cmn.h" ! ODAER +# include "CMN_O3" ! Pure O3, SAVENO2 +# include "CMN_GCTM" ! XTRA2 +# include "comode.h" + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: IS_FULLCHEM, IS_NOx, IS_Ox + LOGICAL, SAVE :: IS_NOy, IS_CLDTOPS, IS_OPTD + LOGICAL, SAVE :: IS_SEASALT, IS_SLP + INTEGER :: IOS, GMTRC, GMNL, I, J, K, L + INTEGER :: N, R, H, W, X, Y + REAL*8 :: TAU, TMP, SCALEAODnm + REAL*8 :: Q( ND49_NI, ND49_NJ, ND49_NL ) + CHARACTER(LEN=16) :: STAMP + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + INTEGER :: NE, NN + + !================================================================= + ! DIAG49 begins here! + !================================================================= + + ! Set logical flags on first timestep + IF ( FIRST ) THEN + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_OPTD = ALLOCATED( OPTD ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOX > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + FIRST = .FALSE. + ENDIF + + !================================================================= + ! If it's a new day, open a new BPCH file and write file header + !================================================================= + IF ( ITS_A_NEW_DAY() ) THEN + + ! Expand date tokens in the file name + FILENAME = TRIM( ND49_OUTPUT_FILE ) + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - DIAG49: Opening file ', a ) + + ! Open bpch file and write top-of-file header + CALL OPEN_BPCH2_FOR_WRITE( IU_ND49, FILENAME, TITLE ) + ENDIF + + !================================================================= + ! Save tracers to timeseries file + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 110 ) STAMP + 110 FORMAT( ' - DIAG49: Saving timeseries at ', a ) + + ! Time for BPCH file + TAU = GET_TAU() + + ! Loop over tracers + DO W = 1, ND49_N_TRACERS + + ! ND49 tracer number + N = ND49_TRACERS(W) + + ! Zero summing array + Q = 0d0 + + ! Test by tracer number + IF ( N <= N_TRACERS ) THEN + + !------------------------------------- + ! GEOS-CHEM tracers [v/v] + !------------------------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = N + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = CHK_STT(I,J,L,N) * TCVV(N) / AD(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 89 .and. IS_Ox ) THEN + + !------------------------------------- + ! PURE O3 CONCENTRATION [v/v] + !------------------------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = N_TRACERS + 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = CHK_STT(I,J,L,IDTOX) * TCVV(IDTOX) / + & AD(I,J,L) * FRACO3(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 90 .and. IS_NOx ) THEN + + !------------------------------------- + ! NO CONCENTRATION [v/v] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = 9 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = STT(I,J,L,IDTNOX) * TCVV(IDTNOX) * + & FRACNO(I,J,L) / AD(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !-------------------------------------- + ! NOy CONCENTRATION [v/v] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND49_NL + GMTRC = 3 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K, TMP ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + + ! Temp variable for accumulation + TMP = 0d0 + + ! NOx + TMP = TMP + ( TCVV(IDTNOX) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + ! PAN + TMP = TMP + ( TCVV(IDTPAN) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + TMP = TMP + ( TCVV(IDTHNO3) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + TMP = TMP + ( TCVV(IDTPMN) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + TMP = TMP + ( TCVV(IDTPPN) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + TMP = TMP + ( TCVV(IDTR4N2) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + TMP = TMP + ( 2d0 * TCVV(IDTN2O5) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + TMP = TMP + ( TCVV(IDTHNO4) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + + ! Save afternoon points + Q(X,Y,K) = Q(X,Y,K) + TMP + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 74 .and. IS_FULLCHEM ) THEN + + !------------------------------------- + ! OH CONCENTRATION [molec/cm3] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND49_NL + GMTRC = 2 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = SAVEOH(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 75 .and. IS_FULLCHEM ) THEN + + !------------------------------------- + ! NO2 CONCENTRATION [molec/cm3] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = 25 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = SAVENO2(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 76 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [m] + !-------------------------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMNL = 1 + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y, TMP ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = GET_PBL_TOP_m( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 77 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [levels] + !-------------------------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMNL = 1 + GMTRC = 2 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = GET_PBL_TOP_L( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 78 ) THEN + + !-------------------------------------- + ! AIR DENSITY [molec/cm3] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND49_NL + GMTRC = 22 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 79 ) THEN + + !-------------------------------------- + ! 3-D CLOUD FRACTIONS [unitless] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 19 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = CLDF(K,I,J) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !-------------------------------------- + ! COLUMN OPTICAL DEPTHS [unitless] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = 1 + GMTRC = 20 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = SUM( OPTD(:,I,J) ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !-------------------------------------- + ! CLOUD TOP HEIGHTS [hPa] + !-------------------------------------- + CATEGORY = 'TIME_SER' + UNIT = 'hPa' + GMNL = ND49_NL + GMTRC = 21 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = GET_PEDGE( I, J, CLDTOPS(I,J) ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 82 ) THEN + + !-------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 6 + + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+R-1) / QAA(4,IND(1)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,R) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 83 ) THEN + + !-------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 9 + + DO R = 1, NRH + + ! Index for ODAER + H = NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 84 ) THEN + + !-------------------------------------- + ! ORGANIC CARBON AOD [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 12 + + DO R = 1, NRH + + ! Index for ODAER + H = 2*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 85 ) THEN + + !-------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 15 + + DO R = 1, NRH + + ! Index for ODAER + H = 3*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 86 ) THEN + + !-------------------------------------- + ! COARSE SEASALT AOD 400 nm [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 18 + + DO R = 1, NRH + + ! Index for ODAER + H = 4*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, R, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 87 ) THEN + + !----------------------------------- + ! TOTAL DUST OPT DEPTH [unitless] + !----------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 4 + + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ODMDUST(I,J,L,R) * SCALEAODnm + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !----------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !----------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND49_NL + GMTRC = 24 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = ( STT(I,J,L,IDTSALA) + STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 93 ) THEN + + !----------------------------------- + ! GRID BOX HEIGHT [m] + !----------------------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMNL = ND49_NL + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = BXHEIGHT(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 94 ) THEN + + !----------------------------------- + ! RELATIVE HUMIDITY [%] + !----------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMNL = ND49_NL + GMTRC = 17 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = RH(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !----------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !----------------------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = SLP(I,J) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 96 ) THEN + + !----------------------------------- + ! ZONAL (U) WIND [m/s] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND49_NL + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = UWND(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 97 ) THEN + + !----------------------------------- + ! ZONAL (V) WIND [m/s] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND49_NL + GMTRC = 2 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = VWND(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 98 ) THEN + + !----------------------------------- + ! PEDGE-$ (prs @ level edges) [hPa] + !----------------------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,L) = GET_PEDGE(I,J,K) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 99 ) THEN + + !----------------------------------- + ! TEMPERATURE [K] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'K' + GMNL = ND49_NL + GMTRC = 3 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = T(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !----------------------------------- + ! Add Anthropgenic NOX to ND49 + !(paulot,5/27/13) + ! [molec C/cm2/s] + !----------------------------------- + ELSEIF ( N .ge. 122 .and. N .le. 135 ) THEN + + DO NE = 1, NEMANTHRO + NN = IDEMS(NE) + IF ( NN == N - 121 ) THEN + + CATEGORY = 'ANTHSRCE' + UNIT = 'molec/cm2/s' + GMNL = 1 + GMTRC = N-121 ! should be NOX etc +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + ! CHECK NE not equal -1 + + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = EMISS_ANTHR( I , J , NE ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ENDIF + ENDDO + + ELSE + + ! Skip + CYCLE + + ENDIF + + !============================================================== + ! Save this data block to the ND49 timeseries file + !============================================================== + CALL BPCH2( IU_ND49, MODELNAME, LONRES, + & LATRES, HALFPOLAR, CENTER180, + & CATEGORY, GMTRC, UNIT, + & TAU, TAU, RESERVED, + & ND49_NI, ND49_NJ, GMNL, + & ND49_IMIN+I0, ND49_JMIN+J0, ND49_LMIN, + & REAL( Q(1:ND49_NI, 1:ND49_NJ, 1:GMNL) ) ) + ENDDO + + !================================================================= + ! Close the file at the proper time + !================================================================= + IF ( ITS_TIME_TO_CLOSE_FILE() ) THEN + + ! Expand date tokens in the file name + FILENAME = TRIM( ND49_OUTPUT_FILE ) + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 120 ) TRIM( FILENAME ) + 120 FORMAT( ' - DIAG49: Closing file : ', a ) + + ! Close file + CLOSE( IU_ND49 ) + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG49 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_TO_CLOSE_FILE() RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_TO_CLOSE_FILE returns TRUE if it's time to close the +! ND49 bpch file before the end of the day. (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: HR1, HR2 + + !================================================================= + ! ITS_TIME_TO_CLOSE_FILE begins here! + !================================================================= + + ! Current hour + HR1 = GET_HOUR() + ( GET_MINUTE() / 60d0 ) + + ! Hour at the next dynamic timestep + HR2 = HR1 + ( ND49_FREQ / 60d0 ) + + ! If the next dyn step is the start of a new day, return TRUE + ITS_TIME = ( INT( HR2 ) == 24 ) + + ! Return to calling program + END FUNCTION ITS_TIME_TO_CLOSE_FILE + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_DIAG49() RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_DIAG49 returns TRUE if ND49 is turned on and it is +! time to call DIAG49 -- or FALSE otherwise. (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_ELAPSED_MIN + + ! Local variables + INTEGER :: XMIN + LOGICAL :: ITS_TIME + + !================================================================= + ! ITS_TIME_FOR_DIAG49 begins here! + !================================================================= + + ! Time already elapsed in this run + XMIN = GET_ELAPSED_MIN() + + ! Is the elapsed time a multiple of ND49_FREQ? + ITS_TIME = ( DO_SAVE_DIAG49 .and. MOD( XMIN, ND49_FREQ ) == 0 ) + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_DIAG49 + +!------------------------------------------------------------------------------ + + FUNCTION GET_I( X ) RESULT( I ) +! +!****************************************************************************** +! Function GET_I returns the absolute longitude index (I), given the +! relative longitude index (X). (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (INTEGER) : Relative longitude index (used by Q) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: X + + ! Local variables + INTEGER :: I + + !================================================================= + ! GET_I begins here! + !================================================================= + + ! Add the offset to X to get I + I = IOFF + X + + ! Handle wrapping around the date line, if necessary + IF ( I > IIPAR ) I = I - IIPAR + + ! Return to calling program + END FUNCTION GET_I + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG49( DO_ND49, N_ND49, TRACERS, IMIN, + & IMAX, JMIN, JMAX, LMIN, + & LMAX, FREQ, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG49 allocates and zeroes all module arrays. +! It also gets values for module variables from "input_mod.f". +! (bmy, 7/20/04, 11/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND49 (LOGICAL ) : Switch to turn on ND49 timeseries diagnostic +! (2 ) N_ND50 (INTEGER ) : Number of ND49 read by "input_mod.f" +! (3 ) TRACERS (INTEGER ) : Array w/ ND49 tracer #'s read by "input_mod.f" +! (4 ) IMIN (INTEGER ) : Min longitude index read by "input_mod.f" +! (5 ) IMAX (INTEGER ) : Max longitude index read by "input_mod.f" +! (6 ) JMIN (INTEGER ) : Min latitude index read by "input_mod.f" +! (7 ) JMAX (INTEGER ) : Min latitude index read by "input_mod.f" +! (8 ) LMIN (INTEGER ) : Min level index read by "input_mod.f" +! (9 ) LMAX (INTEGER ) : Min level index read by "input_mod.f" +! (10) FREQ (INTEGER ) : Frequency for saving to disk [min] +! (11) FILE (CHAR*255) : ND49 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Now get I0 and J0 correctly for nested grid simulations (bmy, 11/9/04) +! (2 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (3 ) Now allow ND49_IMIN to be equal to ND49_IMAX and ND49_JMIN to be +! equal to ND49_JMAX. This will allow us to save out longitude +! or latitude transects. (cdh, bmy, 11/30/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, ITS_A_NESTED_GRID + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND49 + INTEGER, INTENT(IN) :: N_ND49, TRACERS(100) + INTEGER, INTENT(IN) :: IMIN, IMAX + INTEGER, INTENT(IN) :: JMIN, JMAX + INTEGER, INTENT(IN) :: LMIN, LMAX + INTEGER, INTENT(IN) :: FREQ + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG49 begins here! + !================================================================= + + ! Initialize + LOCATION = 'INIT_DIAG49 ("diag49_mod.f")' + ND49_TRACERS(:) = 0 + + ! Get values from "input_mod.f" + DO_SAVE_DIAG49 = DO_ND49 + ND49_N_TRACERS = N_ND49 + ND49_TRACERS(1:N_ND49) = TRACERS(1:N_ND49) + ND49_IMIN = IMIN + ND49_IMAX = IMAX + ND49_JMIN = JMIN + ND49_JMAX = JMAX + ND49_LMIN = LMIN + ND49_LMAX = LMAX + ND49_FREQ = FREQ + ND49_OUTPUT_FILE = FILE + + ! Return if we are not saving ND49 diagnostics + IF ( .not. DO_SAVE_DIAG49 ) RETURN + + !================================================================= + ! Compute lon, lat, alt extents and check for errors + !================================================================= + + ! Get grid offsets for error checking + IF ( ITS_A_NESTED_GRID() ) THEN + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + ELSE + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + ENDIF + + !----------- + ! Longitude + !----------- + + ! Error check ND49_IMIN + IF ( ND49_IMIN+I0 < 1 .or. ND49_IMIN+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_IMIN value!', LOCATION ) + ENDIF + + ! Error check ND49_IMAX + IF ( ND49_IMAX+I0 < 1 .or. ND49_IMAX+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_IMAX value!', LOCATION ) + ENDIF + + ! Compute longitude limits to write to disk + ! Also handle wrapping around the date line + IF ( ND49_IMAX >= ND49_IMIN ) THEN + ND49_NI = ( ND49_IMAX - ND49_IMIN ) + 1 + ELSE + ND49_NI = ( IIPAR - ND49_IMIN ) + 1 + ND49_IMAX + WRITE( 6, '(a)' ) 'We are wrapping over the date line!' + ENDIF + + ! Make sure that ND49_NI <= IIPAR + IF ( ND49_NI > IIPAR ) THEN + CALL ERROR_STOP( 'Too many longitudes!', LOCATION ) + ENDIF + + !----------- + ! Latitude + !----------- + + ! Error check JMIN_AREA + IF ( ND49_JMIN+J0 < 1 .or. ND49_JMIN+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_JMIN value!', LOCATION) + ENDIF + + ! Error check JMAX_AREA + IF ( ND49_JMAX+J0 < 1 .or.ND49_JMAX+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_JMAX value!', LOCATION) + ENDIF + + ! Compute latitude limits to write to disk (bey, bmy, 3/16/99) + IF ( ND49_JMAX >= ND49_JMIN ) THEN + ND49_NJ = ( ND49_JMAX - ND49_JMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND49_JMAX < ND49_JMIN!', LOCATION ) + ENDIF + + !----------- + ! Altitude + !----------- + + ! Error check ND49_LMIN, ND49_LMAX + IF ( ND49_LMIN < 1 .or. ND49_LMAX > LLPAR ) THEN + CALL ERROR_STOP( 'Bad ND49 altitude values!', LOCATION ) + ENDIF + + ! # of levels to save in ND49 timeseries + IF ( ND49_LMAX >= ND49_LMIN ) THEN + ND49_NL = ( ND49_LMAX - ND49_LMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND49_LMAX < ND49_LMIN!', LOCATION ) + ENDIF + + !----------- + ! Offsets + !----------- + IOFF = ND49_IMIN - 1 + JOFF = ND49_JMIN - 1 + LOFF = ND49_LMIN - 1 + + !----------- + ! For bpch + !----------- + TITLE = 'GEOS-CHEM DIAG49 instantaneous timeseries' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Reset grid offsets to global values for bpch write + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + ! Return to calling program + END SUBROUTINE INIT_DIAG49 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG49_MOD diff --git a/code/diag49_mod.f~ b/code/diag49_mod.f~ new file mode 100644 index 0000000..59b76d3 --- /dev/null +++ b/code/diag49_mod.f~ @@ -0,0 +1,1359 @@ +! $Id: diag49_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE DIAG49_MOD +! +!****************************************************************************** +! Module DIAG49_MOD contains variables and routines to save out 3-D +! timeseries output to disk (bmy, 7/20/04, 10/7/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_DIAG49 (LOGICAL ) : Switch to turn ND49 timeseries on/off +! (2 ) I0 (INTEGER ) : Lon offset between global & nested grid +! (3 ) J0 (INTEGER ) : Lat offset between global & nested grid +! (4 ) IOFF (INTEGER ) : Offset between relative & absolute lon +! (5 ) JOFF (INTEGER ) : Offset between relative & absolute lat +! (6 ) LOFF (INTEGER ) : Offset between relative & absolute alt +! (7 ) ND49_IMIN (INTEGER ) : Minimum longitude index +! (8 ) ND49_IMAX (INTEGER ) : Maximum latitude index +! (9 ) ND49_JMIN (INTEGER ) : Minimum longitude index +! (10) ND49_JMAX (INTEGER ) : Maximum longitude index +! (11) ND49_LMIN (INTEGER ) : Minimum altitude index +! (12) ND49_LMAX (INTEGER ) : Maximum altitude index +! (13) ND49_FREQ (INTEGER ) : Frequency which to save to disk [min] +! (14) ND49_N_TRACERS (INTEGER ) : Number of tracers for ND49 timeseries +! (15) ND49_OUTPUT_FILE (CHAR*255) : Name of timeseries output file +! (16) ND49_TRACERS (INTEGER ) : Array w/ tracer #'s to save to disk +! (17) HALFPOLAR (INTEGER ) : Used for binary punch file write +! (18) CENTER180 (INTEGER ) : Used for binary punch file write +! (19) LONRES (REAL*4 ) : Used for binary punch file write +! (20) LATRES (REAL*4 ) : Used for binary punch file write +! (21) RESERVED (CHAR*40 ) : Used for binary punch file write +! (22) MODELNAME (CHAR*20 ) : Used for binary punch file write +! (23) TITLE (CHAR*80 ) : Used for binary punch file write +! +! Module Routines: +! ============================================================================ +! (1 ) DIAG49 : Main driver routine +! (2 ) ITS_TIME_TO_CLOSE_FILE : Returns TRUE if it's time to close ND49 file +! (3 ) ITS_TIME_FOR_DIAG49 : Returns TRUE if it's time to save to disk +! (4 ) GET_I : Converts relative longitude index to absolute +! (5 ) INIT_DIAG49 : Gets variable values from "input_mod.f" +! +! GEOS-CHEM modules referenced by "diag49_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) file_mod.f : Module w/ file unit numbers & error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (6 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (7 ) time_mod.f : Module w/ routines for computing time & date +! (8 ) tracer_mod.f : Module w/ GEOS-CHEM tracer array STT etc. +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND49 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box height [m ] +! 94 : Relative humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Bug fix: get I0, J0 properly for nested grids (bmy, 11/9/04) +! (2 ) Now references "pbl_mix_mod.f" (bmy, 2/16/05) +! (3 ) Now saves 3-D cld frac & grid box height (bmy, 4/20/05) +! (4 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (5 ) Bug fix: do not save SLP if it's not allocated (bmy, 8/2/05) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (8 ) Modified INIT_DIAG49 to save out transects (cdh, bmy, 11/30/06) +! (9 ) Bug fix: accumulate into Q(X,Y,K) for dust OD (qli, bmy, 4/30/07) +! (10) Minor bug fixes in DIAG49 (cdh, bmy, 2/11/08) +! (11) Bug fix: replace "PS-PTOP" with "PEDGE-$" +! (12) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 9/26/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag49_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG49 + + ! ... except these routines + PUBLIC :: DIAG49 + PUBLIC :: ITS_TIME_FOR_DIAG49 + PUBLIC :: INIT_DIAG49 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + LOGICAL :: DO_SAVE_DIAG49 + INTEGER :: IOFF, JOFF, LOFF + INTEGER :: I0, J0 + INTEGER :: ND49_N_TRACERS, ND49_TRACERS(134) + INTEGER :: ND49_IMIN, ND49_IMAX + INTEGER :: ND49_JMIN, ND49_JMAX + INTEGER :: ND49_LMIN, ND49_LMAX + INTEGER :: ND49_FREQ, ND49_NI + INTEGER :: ND49_NJ, ND49_NL + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES, LATRES + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = '' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND49_OUTPUT_FILE + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG49 +! +!****************************************************************************** +! Subroutine DIAG49 produces time series (instantaneous fields) for a +! geographical domain from the information read in timeseries.dat. Output +! will be in binary punch (BPCH) format. (bey, bmy, rvm, 4/9/99, 10/7/08) +! +! NOTES: +! (1 ) Now bundled into "diag49_mod.f". Now reference STT from +! "tracer_mod.f". Now scale aerosol & dust OD's to 400 nm. +! (bmy, rvm, aad, 7/9/04) +! (2 ) Updated tracer # for NO2 (bmy, 10/25/04) +! (3 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (4 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D cloud +! fraction as tracer #79 and box height as tracer #93. Now remove +! reference to PBL from "dao_mod.f"(bmy, 4/20/05) +! (5 ) Remove references to TRCOFFSET because it is always zero (bmy, 6/24/05) +! (6 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (7 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (8 ) Now references XNUMOLAIR from "tracer_mod.f". Bug fix: now must sum +! aerosol OD's over all RH bins. Also zero Q array. (bmy, 11/1/05) +! (9 ) Bug fix: accumulate into Q(X,Y,K) for dust OD (qli, bmy, 4/30/07) +! (10) Bug fix: UNIT should be "levels" for tracer 77. Also RH should be +! tracer #17 under "TIME-SER" category. (cdh, bmy, 2/11/08) +! (11) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : EMISS_ANTHR + USE BPCH2_MOD, ONLY : BPCH2, OPEN_BPCH2_FOR_WRITE + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, SLP + USE DAO_MOD, ONLY : T, UWND, VWND + USE FILE_MOD, ONLY : IU_ND49 + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : EXPAND_DATE + USE TIME_MOD, ONLY : GET_NYMD, GET_NHMS + USE TIME_MOD, ONLY : GET_TAU, GET_HOUR + USE TIME_MOD, ONLY : ITS_A_NEW_DAY, TIMESTAMP_STRING + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM, N_TRACERS + USE TRACER_MOD, ONLY : STT, TCVV + USE TRACER_MOD, ONLY : XNUMOLAIR + USE CHECKPT_MOD, ONLY : CHK_STT + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TRACERID_MOD, ONLY : IDTHNO3, IDTHNO4, IDTN2O5, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + USE TRACERID_MOD, ONLY : NEMANTHRO + +# include "cmn_fj.h" ! FAST-J stuff, includes CMN_SIZE +# include "jv_cmn.h" ! ODAER +# include "CMN_O3" ! Pure O3, SAVENO2 +# include "CMN_GCTM" ! XTRA2 +# include "comode.h" + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: IS_FULLCHEM, IS_NOx, IS_Ox + LOGICAL, SAVE :: IS_NOy, IS_CLDTOPS, IS_OPTD + LOGICAL, SAVE :: IS_SEASALT, IS_SLP + INTEGER :: IOS, GMTRC, GMNL, I, J, K, L + INTEGER :: N, R, H, W, X, Y + REAL*8 :: TAU, TMP, SCALEAODnm + REAL*8 :: Q( ND49_NI, ND49_NJ, ND49_NL ) + CHARACTER(LEN=16) :: STAMP + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + INTEGER :: NE, NN + + !================================================================= + ! DIAG49 begins here! + !================================================================= + + ! Set logical flags on first timestep + IF ( FIRST ) THEN + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_OPTD = ALLOCATED( OPTD ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOX > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + FIRST = .FALSE. + ENDIF + + !================================================================= + ! If it's a new day, open a new BPCH file and write file header + !================================================================= + IF ( ITS_A_NEW_DAY() ) THEN + + ! Expand date tokens in the file name + FILENAME = TRIM( ND49_OUTPUT_FILE ) + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - DIAG49: Opening file ', a ) + + ! Open bpch file and write top-of-file header + CALL OPEN_BPCH2_FOR_WRITE( IU_ND49, FILENAME, TITLE ) + ENDIF + + !================================================================= + ! Save tracers to timeseries file + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 110 ) STAMP + 110 FORMAT( ' - DIAG49: Saving timeseries at ', a ) + + ! Time for BPCH file + TAU = GET_TAU() + + ! Loop over tracers + DO W = 1, ND49_N_TRACERS + + ! ND49 tracer number + N = ND49_TRACERS(W) + + ! Zero summing array + Q = 0d0 + + ! Test by tracer number + IF ( N <= N_TRACERS ) THEN + + !------------------------------------- + ! GEOS-CHEM tracers [v/v] + !------------------------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = N + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = CHK_STT(I,J,L,N) * TCVV(N) / AD(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 89 .and. IS_Ox ) THEN + + !------------------------------------- + ! PURE O3 CONCENTRATION [v/v] + !------------------------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = N_TRACERS + 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = STT(I,J,L,IDTOX) * TCVV(IDTOX) / + & AD(I,J,L) * FRACO3(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 90 .and. IS_NOx ) THEN + + !------------------------------------- + ! NO CONCENTRATION [v/v] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = 9 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = STT(I,J,L,IDTNOX) * TCVV(IDTNOX) * + & FRACNO(I,J,L) / AD(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !-------------------------------------- + ! NOy CONCENTRATION [v/v] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND49_NL + GMTRC = 3 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K, TMP ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + + ! Temp variable for accumulation + TMP = 0d0 + + ! NOx + TMP = TMP + ( TCVV(IDTNOX) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + ! PAN + TMP = TMP + ( TCVV(IDTPAN) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + TMP = TMP + ( TCVV(IDTHNO3) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + TMP = TMP + ( TCVV(IDTPMN) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + TMP = TMP + ( TCVV(IDTPPN) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + TMP = TMP + ( TCVV(IDTR4N2) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + TMP = TMP + ( 2d0 * TCVV(IDTN2O5) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + TMP = TMP + ( TCVV(IDTHNO4) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + + ! Save afternoon points + Q(X,Y,K) = Q(X,Y,K) + TMP + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 74 .and. IS_FULLCHEM ) THEN + + !------------------------------------- + ! OH CONCENTRATION [molec/cm3] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND49_NL + GMTRC = 2 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = SAVEOH(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 75 .and. IS_FULLCHEM ) THEN + + !------------------------------------- + ! NO2 CONCENTRATION [molec/cm3] + !------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick the unit + GMNL = ND49_NL + GMTRC = 25 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = SAVENO2(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 76 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [m] + !-------------------------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMNL = 1 + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y, TMP ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = GET_PBL_TOP_m( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 77 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [levels] + !-------------------------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMNL = 1 + GMTRC = 2 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = GET_PBL_TOP_L( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 78 ) THEN + + !-------------------------------------- + ! AIR DENSITY [molec/cm3] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND49_NL + GMTRC = 22 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 79 ) THEN + + !-------------------------------------- + ! 3-D CLOUD FRACTIONS [unitless] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 19 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = CLDF(K,I,J) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !-------------------------------------- + ! COLUMN OPTICAL DEPTHS [unitless] + !-------------------------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = 1 + GMTRC = 20 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = SUM( OPTD(:,I,J) ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !-------------------------------------- + ! CLOUD TOP HEIGHTS [hPa] + !-------------------------------------- + CATEGORY = 'TIME_SER' + UNIT = 'hPa' + GMNL = ND49_NL + GMTRC = 21 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = GET_PEDGE( I, J, CLDTOPS(I,J) ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 82 ) THEN + + !-------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 6 + + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+R-1) / QAA(4,IND(1)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,R) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 83 ) THEN + + !-------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 9 + + DO R = 1, NRH + + ! Index for ODAER + H = NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 84 ) THEN + + !-------------------------------------- + ! ORGANIC CARBON AOD [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 12 + + DO R = 1, NRH + + ! Index for ODAER + H = 2*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 85 ) THEN + + !-------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 15 + + DO R = 1, NRH + + ! Index for ODAER + H = 3*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 86 ) THEN + + !-------------------------------------- + ! COARSE SEASALT AOD 400 nm [unitless] + !-------------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 18 + + DO R = 1, NRH + + ! Index for ODAER + H = 4*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, R, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ( ODAER(I,J,L,H) * SCALEAODnm ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 87 ) THEN + + !----------------------------------- + ! TOTAL DUST OPT DEPTH [unitless] + !----------------------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND49_NL + GMTRC = 4 + + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = Q(X,Y,K) + ODMDUST(I,J,L,R) * SCALEAODnm + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !----------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !----------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND49_NL + GMTRC = 24 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = ( STT(I,J,L,IDTSALA) + STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 93 ) THEN + + !----------------------------------- + ! GRID BOX HEIGHT [m] + !----------------------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMNL = ND49_NL + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = BXHEIGHT(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 94 ) THEN + + !----------------------------------- + ! RELATIVE HUMIDITY [%] + !----------------------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMNL = ND49_NL + GMTRC = 17 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = RH(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !----------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !----------------------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = SLP(I,J) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 96 ) THEN + + !----------------------------------- + ! ZONAL (U) WIND [m/s] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND49_NL + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = UWND(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 97 ) THEN + + !----------------------------------- + ! ZONAL (V) WIND [m/s] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND49_NL + GMTRC = 2 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = VWND(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 98 ) THEN + + !----------------------------------- + ! PEDGE-$ (prs @ level edges) [hPa] + !----------------------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 1 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,L) = GET_PEDGE(I,J,K) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( N == 99 ) THEN + + !----------------------------------- + ! TEMPERATURE [K] + !----------------------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'K' + GMNL = ND49_NL + GMTRC = 3 + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, X, Y, K ) + DO K = 1, ND49_NL + L = LOFF + K + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,K) = T(I,J,L) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !----------------------------------- + ! Add Anthropgenic NOX to ND49 + !(paulot,5/27/13) + ! [molec C/cm2/s] + !----------------------------------- + ELSEIF ( N .ge. 122 .and. N .le. 135 ) THEN + + DO NE = 1, NEMANTHRO + NN = IDEMS(NE) + IF ( NN == N - 121 ) THEN + + CATEGORY = 'ANTHSRCE' + UNIT = 'molec/cm2/s' + GMNL = 1 + GMTRC = N-121 ! should be NOX etc +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, X, Y ) + ! CHECK NE not equal -1 + + DO Y = 1, ND49_NJ + J = JOFF + Y + DO X = 1, ND49_NI + I = GET_I( X ) + Q(X,Y,1) = EMISS_ANTHR( I , J , NE ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ENDIF + ENDDO + + ELSE + + ! Skip + CYCLE + + ENDIF + + !============================================================== + ! Save this data block to the ND49 timeseries file + !============================================================== + CALL BPCH2( IU_ND49, MODELNAME, LONRES, + & LATRES, HALFPOLAR, CENTER180, + & CATEGORY, GMTRC, UNIT, + & TAU, TAU, RESERVED, + & ND49_NI, ND49_NJ, GMNL, + & ND49_IMIN+I0, ND49_JMIN+J0, ND49_LMIN, + & REAL( Q(1:ND49_NI, 1:ND49_NJ, 1:GMNL) ) ) + ENDDO + + !================================================================= + ! Close the file at the proper time + !================================================================= + IF ( ITS_TIME_TO_CLOSE_FILE() ) THEN + + ! Expand date tokens in the file name + FILENAME = TRIM( ND49_OUTPUT_FILE ) + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 120 ) TRIM( FILENAME ) + 120 FORMAT( ' - DIAG49: Closing file : ', a ) + + ! Close file + CLOSE( IU_ND49 ) + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG49 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_TO_CLOSE_FILE() RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_TO_CLOSE_FILE returns TRUE if it's time to close the +! ND49 bpch file before the end of the day. (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: HR1, HR2 + + !================================================================= + ! ITS_TIME_TO_CLOSE_FILE begins here! + !================================================================= + + ! Current hour + HR1 = GET_HOUR() + ( GET_MINUTE() / 60d0 ) + + ! Hour at the next dynamic timestep + HR2 = HR1 + ( ND49_FREQ / 60d0 ) + + ! If the next dyn step is the start of a new day, return TRUE + ITS_TIME = ( INT( HR2 ) == 24 ) + + ! Return to calling program + END FUNCTION ITS_TIME_TO_CLOSE_FILE + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_DIAG49() RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_DIAG49 returns TRUE if ND49 is turned on and it is +! time to call DIAG49 -- or FALSE otherwise. (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_ELAPSED_MIN + + ! Local variables + INTEGER :: XMIN + LOGICAL :: ITS_TIME + + !================================================================= + ! ITS_TIME_FOR_DIAG49 begins here! + !================================================================= + + ! Time already elapsed in this run + XMIN = GET_ELAPSED_MIN() + + ! Is the elapsed time a multiple of ND49_FREQ? + ITS_TIME = ( DO_SAVE_DIAG49 .and. MOD( XMIN, ND49_FREQ ) == 0 ) + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_DIAG49 + +!------------------------------------------------------------------------------ + + FUNCTION GET_I( X ) RESULT( I ) +! +!****************************************************************************** +! Function GET_I returns the absolute longitude index (I), given the +! relative longitude index (X). (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (INTEGER) : Relative longitude index (used by Q) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: X + + ! Local variables + INTEGER :: I + + !================================================================= + ! GET_I begins here! + !================================================================= + + ! Add the offset to X to get I + I = IOFF + X + + ! Handle wrapping around the date line, if necessary + IF ( I > IIPAR ) I = I - IIPAR + + ! Return to calling program + END FUNCTION GET_I + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG49( DO_ND49, N_ND49, TRACERS, IMIN, + & IMAX, JMIN, JMAX, LMIN, + & LMAX, FREQ, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG49 allocates and zeroes all module arrays. +! It also gets values for module variables from "input_mod.f". +! (bmy, 7/20/04, 11/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND49 (LOGICAL ) : Switch to turn on ND49 timeseries diagnostic +! (2 ) N_ND50 (INTEGER ) : Number of ND49 read by "input_mod.f" +! (3 ) TRACERS (INTEGER ) : Array w/ ND49 tracer #'s read by "input_mod.f" +! (4 ) IMIN (INTEGER ) : Min longitude index read by "input_mod.f" +! (5 ) IMAX (INTEGER ) : Max longitude index read by "input_mod.f" +! (6 ) JMIN (INTEGER ) : Min latitude index read by "input_mod.f" +! (7 ) JMAX (INTEGER ) : Min latitude index read by "input_mod.f" +! (8 ) LMIN (INTEGER ) : Min level index read by "input_mod.f" +! (9 ) LMAX (INTEGER ) : Min level index read by "input_mod.f" +! (10) FREQ (INTEGER ) : Frequency for saving to disk [min] +! (11) FILE (CHAR*255) : ND49 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Now get I0 and J0 correctly for nested grid simulations (bmy, 11/9/04) +! (2 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (3 ) Now allow ND49_IMIN to be equal to ND49_IMAX and ND49_JMIN to be +! equal to ND49_JMAX. This will allow us to save out longitude +! or latitude transects. (cdh, bmy, 11/30/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, ITS_A_NESTED_GRID + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND49 + INTEGER, INTENT(IN) :: N_ND49, TRACERS(100) + INTEGER, INTENT(IN) :: IMIN, IMAX + INTEGER, INTENT(IN) :: JMIN, JMAX + INTEGER, INTENT(IN) :: LMIN, LMAX + INTEGER, INTENT(IN) :: FREQ + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG49 begins here! + !================================================================= + + ! Initialize + LOCATION = 'INIT_DIAG49 ("diag49_mod.f")' + ND49_TRACERS(:) = 0 + + ! Get values from "input_mod.f" + DO_SAVE_DIAG49 = DO_ND49 + ND49_N_TRACERS = N_ND49 + ND49_TRACERS(1:N_ND49) = TRACERS(1:N_ND49) + ND49_IMIN = IMIN + ND49_IMAX = IMAX + ND49_JMIN = JMIN + ND49_JMAX = JMAX + ND49_LMIN = LMIN + ND49_LMAX = LMAX + ND49_FREQ = FREQ + ND49_OUTPUT_FILE = FILE + + ! Return if we are not saving ND49 diagnostics + IF ( .not. DO_SAVE_DIAG49 ) RETURN + + !================================================================= + ! Compute lon, lat, alt extents and check for errors + !================================================================= + + ! Get grid offsets for error checking + IF ( ITS_A_NESTED_GRID() ) THEN + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + ELSE + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + ENDIF + + !----------- + ! Longitude + !----------- + + ! Error check ND49_IMIN + IF ( ND49_IMIN+I0 < 1 .or. ND49_IMIN+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_IMIN value!', LOCATION ) + ENDIF + + ! Error check ND49_IMAX + IF ( ND49_IMAX+I0 < 1 .or. ND49_IMAX+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_IMAX value!', LOCATION ) + ENDIF + + ! Compute longitude limits to write to disk + ! Also handle wrapping around the date line + IF ( ND49_IMAX >= ND49_IMIN ) THEN + ND49_NI = ( ND49_IMAX - ND49_IMIN ) + 1 + ELSE + ND49_NI = ( IIPAR - ND49_IMIN ) + 1 + ND49_IMAX + WRITE( 6, '(a)' ) 'We are wrapping over the date line!' + ENDIF + + ! Make sure that ND49_NI <= IIPAR + IF ( ND49_NI > IIPAR ) THEN + CALL ERROR_STOP( 'Too many longitudes!', LOCATION ) + ENDIF + + !----------- + ! Latitude + !----------- + + ! Error check JMIN_AREA + IF ( ND49_JMIN+J0 < 1 .or. ND49_JMIN+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_JMIN value!', LOCATION) + ENDIF + + ! Error check JMAX_AREA + IF ( ND49_JMAX+J0 < 1 .or.ND49_JMAX+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND49_JMAX value!', LOCATION) + ENDIF + + ! Compute latitude limits to write to disk (bey, bmy, 3/16/99) + IF ( ND49_JMAX >= ND49_JMIN ) THEN + ND49_NJ = ( ND49_JMAX - ND49_JMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND49_JMAX < ND49_JMIN!', LOCATION ) + ENDIF + + !----------- + ! Altitude + !----------- + + ! Error check ND49_LMIN, ND49_LMAX + IF ( ND49_LMIN < 1 .or. ND49_LMAX > LLPAR ) THEN + CALL ERROR_STOP( 'Bad ND49 altitude values!', LOCATION ) + ENDIF + + ! # of levels to save in ND49 timeseries + IF ( ND49_LMAX >= ND49_LMIN ) THEN + ND49_NL = ( ND49_LMAX - ND49_LMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND49_LMAX < ND49_LMIN!', LOCATION ) + ENDIF + + !----------- + ! Offsets + !----------- + IOFF = ND49_IMIN - 1 + JOFF = ND49_JMIN - 1 + LOFF = ND49_LMIN - 1 + + !----------- + ! For bpch + !----------- + TITLE = 'GEOS-CHEM DIAG49 instantaneous timeseries' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Reset grid offsets to global values for bpch write + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + ! Return to calling program + END SUBROUTINE INIT_DIAG49 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG49_MOD diff --git a/code/diag50_mod.f b/code/diag50_mod.f new file mode 100644 index 0000000..3618793 --- /dev/null +++ b/code/diag50_mod.f @@ -0,0 +1,1380 @@ +! $Id: diag50_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE DIAG50_MOD +! +!****************************************************************************** +! Module DIAG50_MOD contains variables and routines to generate 24-hour +! average timeseries data. (amf, bey, bdf, pip, bmy, 11/30/00, 10/7/08) +! +! Module Variables: +! ============================================================================ +! (1 ) COUNT (INTEGER ) : Counter of timesteps per day +! (2 ) COUNT_CHEM (INTEGER ) : Counter of chemistry timesteps per day +! (2b) COUNT_CHEM3D (INTEGER ) : Counter of fullchem steps under T-pause +! (3 ) DO_SAVE_DIAG50 (LOGICAL ) : Flag to turn on DIAG50 timseries +! (4 ) I0 (INTEGER ) : Lon offset between global & nested grid +! (5 ) J0 (INTEGER ) : Lat offset between global & nested grid +! (6 ) IOFF (INTEGER ) : Offset between relative & absolute lon +! (7 ) JOFF (INTEGER ) : Offset between relative & absolute lat +! (8 ) LOFF (INTEGER ) : Offset between relative & absolute alt +! (9 ) ND50_IMIN (INTEGER ) : Minimum lat index for DIAG50 region +! (10) ND50_IMAX (INTEGER ) : Maximum lat index for DIAG50 region +! (11) ND50_JMIN (INTEGER ) : Minimum lon index for DIAG50 region +! (12) ND50_JMAX (INTEGER ) : Maximum lon index for DIAG50 region +! (13) ND50_LMIN (INTEGER ) : Minimum alt index for DIAG50 region +! (14) ND50_LMAX (INTEGER ) : Minimum alt index for DIAG50 region +! (15) ND50_NI (INTEGER ) : Number of longitudes in DIAG50 region +! (16) ND50_NJ (INTEGER ) : Number of latitudes in DIAG50 region +! (17) ND50_NL (INTEGER ) : Number of levels in DIAG50 region +! (18) ND50_N_TRACERS (INTEGER ) : Number of tracers for DIAG50 +! (19) ND50_OUTPUT_FILE (CHAR*255) : Name of output file for timeseries data +! (20) ND50_TRACERS (INTEGER ) : Array of DIAG50 tracer numbers +! (21) Q (REAL*8 ) : Accumulator array for various quantities +! (22) TAU0 (REAL*8 ) : Starting TAU used to index the bpch file +! (23) TAU1 (REAL*8 ) : Ending TAU used to index the bpch file +! (24) HALFPOLAR (INTEGER ) : Used for bpch file output +! (25) CENTER180 (INTEGER ) : Used for bpch file output +! (26) LONRES (REAL*4 ) : Used for bpch file output +! (27) LATRES (REAL*4 ) : Used for bpch file output +! (28) MODELNAME (CHAR*20 ) : Used for bpch file output +! (29) RESERVED (CHAR*40 ) : Used for bpch file output +! +! Module Procedures: +! ============================================================================ +! (1 ) DIAG50 : Driver subroutine for 24hr timeseries +! (2 ) ACCUMULATE_DIAG50 : Accumulates data for later averaging +! (3 ) ITS_TIME_FOR_WRITE_DIAG50 : Returns T if it's time to write bpch file +! (4 ) WRITE_DIAG50 : Writes 24-hr averaged data to a bpch file +! (5 ) GET_I : Converts relative lon index to absolute +! (5 ) INIT_DIAG50 : Allocates and zeroes all module arrays +! (6 ) CLEANUP_DIAG50 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag50_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) error_mod.f : Module w/ NaN and other error check routines +! (4 ) file_mod.f : Module w/ file unit numbers and error checks +! (5 ) grid_mod.f : Module w/ horizontal grid information +! (6 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (7 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (8 ) time_mod.f : Module w/ routines to compute date & time +! (9 ) tracer_mod. : Module w/ GEOS-CHEM tracer array STT etc. +! (10) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND50 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D Cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box height [m ] +! 94 : Relative humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Rewritten for clarity and to save extra quantities (bmy, 7/20/04) +! (2 ) Added COUNT_CHEM to count the chemistry timesteps per day, since some +! quantities are only archived after a fullchem call (bmy, 10/25/04) +! (3 ) Bug fix: Now get I0 and J0 properly for nested grids (bmy, 11/9/04) +! (4 ) Now only archive AOD's once per chemistry timestep (bmy, 1/14/05) +! (5 ) Now references "pbl_mix_mod.f" (bmy, 2/16/05) +! (6 ) Now save cloud fractions & grid box heights (bmy, 4/20/05) +! (7 ) Remove TRCOFFSET since it's always zero. Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/24/05) +! (8 ) Bug fix: don't save SLP unless it is allocated (bmy, 8/2/05) +! (9 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (10) Modified INIT_DIAG49 to save out transects (cdh, bmy, 11/30/06) +! (11) Now use 3D timestep counter for full chem in the trop (phs, 1/24/07) +! (12) Renumber RH diagnostic in WRITE_DIAG50 (bmy, 2/11/08) +! (13) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, 10/7/08) +! (14) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 9/26/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag50_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG50 + + ! ... and these routines + PUBLIC :: CLEANUP_DIAG50 + PUBLIC :: DIAG50 + PUBLIC :: INIT_DIAG50 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_DIAG50 + INTEGER :: COUNT, COUNT_CHEM + INTEGER :: IOFF, JOFF + INTEGER :: LOFF, I0 + INTEGER :: J0, ND50_NI + INTEGER :: ND50_NJ, ND50_NL + INTEGER :: ND50_N_TRACERS, ND50_TRACERS(100) + INTEGER :: ND50_IMIN, ND50_IMAX + INTEGER :: ND50_JMIN, ND50_JMAX + INTEGER :: ND50_LMIN, ND50_LMAX + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES, LATRES + REAL*8 :: TAU0, TAU1 + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = '' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND50_OUTPUT_FILE + + ! Arrays + REAL*8, ALLOCATABLE :: Q(:,:,:,:) + INTEGER, ALLOCATABLE :: COUNT_CHEM3D(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG50 +! +!****************************************************************************** +! Subroutine DIAG50 generates 24hr average time series. Output is to +! binary punch file format. (amf, bey, bdf, pip, bmy, 11/15/99, 7/20/04) +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +!****************************************************************************** +! + !================================================================= + ! DIAG50 begins here! + !================================================================= + + ! Accumulate data over a 24-hr period in the Q array + CALL ACCUMULATE_DIAG50 + + ! Write data to disk at the end of the day + IF ( ITS_TIME_FOR_WRITE_DIAG50() ) CALL WRITE_DIAG50 + + ! Return to calling program + END SUBROUTINE DIAG50 + +!------------------------------------------------------------------------------ + + SUBROUTINE ACCUMULATE_DIAG50 +! +!****************************************************************************** +! Subroutine ACCUMULATE_DIAG50 accumulates tracers into the Q array. +! (bmy, 8/20/02, 1/24/07) +! +! NOTES: +! (1 ) Rewrote to remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. Now scale aerosol & dust +! optical depths to 400 nm. (rvm, aad, bmy, 7/20/04) +! (2 ) Now reference GET_ELAPSED_MIN and GET_TS_CHEM from "time_mod.f". +! Also now use extra counter COUNT_CHEM to count the number of +! chemistry timesteps since NO, NO2, OH, O3 only when a full-chemistry +! timestep happens. (bmy, 10/25/04) +! (3 ) Only archive AOD's when it is a chem timestep (bmy, 1/14/05) +! (4 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (5 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D +! cloud fraction as tracer #79 and box height as tracer #93. Now +! remove references to CLMOSW, CLROSW, and PBL from "dao_mod.f". +! (bmy, 4/20/05) +! (6 ) Remove references to TRCOFFSET because it's always zero (bmy, 6/24/05) +! (7 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (8 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (9 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (10) Now account for time spent in the trop for non-tracers (phs, 1/24/07) +!****************************************************************************** +! + ! Reference to F90 modules + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, T + USE DAO_MOD, ONLY : UWND, VWND, SLP + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : GET_ELAPSED_MIN, GET_TS_CHEM + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : STT, TCVV, ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : N_TRACERS + USE TRACER_MOD, ONLY : XNUMOLAIR + USE TRACERID_MOD, ONLY : IDTHNO3, IDTHNO4, IDTN2O5, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + +# include "cmn_fj.h" ! includes CMN_SIZE +# include "jv_cmn.h" ! ODAER +# include "CMN_O3" ! FRACO3, FRACNO, SAVEO3, SAVENO2, SAVEHO2, FRACNO2 +# include "CMN_GCTM" ! SCALE_HEIGHT + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: IS_FULLCHEM, IS_NOx, IS_Ox, IS_SEASALT + LOGICAL, SAVE :: IS_CLDTOPS, IS_NOy, IS_OPTD, IS_SLP + LOGICAL :: IS_CHEM + INTEGER :: H, I, J, K, L, M, N + INTEGER :: PBLINT, R, X, Y, W + REAL*8 :: C1, C2, PBLDEC, TEMPBL, TMP, SCALEAODnm + CHARACTER(LEN=16) :: STAMP + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + + !================================================================= + ! ACCUMULATE_DIAG50 begins here! + !================================================================= + + ! Set logical flags + IF ( FIRST ) THEN + IS_OPTD = ALLOCATED( OPTD ) + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOx > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + FIRST = .FALSE. + ENDIF + + ! Is it a chemistry timestep? + IS_CHEM = ( MOD( GET_ELAPSED_MIN(), GET_TS_CHEM() ) == 0 ) + + ! Echo time information to the screen + STAMP = TIMESTAMP_STRING() + WRITE( 6, 100 ) STAMP + 100 FORMAT( ' - DIAG50: Accumulation at ', a ) + + !================================================================= + ! Archive tracers into accumulating array Q + !================================================================= + + ! Increment counter + COUNT = COUNT + 1 + + ! Increment chemistry timestep counter + IF ( IS_CHEM ) COUNT_CHEM = COUNT_CHEM + 1 + + ! Also increment 3-D counter for boxes in the tropopause + IF ( IS_FULLCHEM .and. IS_CHEM ) THEN + + ! Loop over levels +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, I, J, L ) +!$OMP+SCHEDULE( DYNAMIC ) + DO K = 1, ND50_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND50_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND50_NI + I = GET_I( X ) + + ! Only increment if we are in the trop + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + COUNT_CHEM3D(X,Y,K) = COUNT_CHEM3D(X,Y,K) + 1 + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !----------------------- + ! Accumulate quantities + !----------------------- +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( W, N, X, Y, K, I, J, L, TMP, H, R, SCALEAODnm ) +!$OMP+SCHEDULE( DYNAMIC ) + DO W = 1, ND50_N_TRACERS + + ! ND50 Tracer number + N = ND50_TRACERS(W) + + ! Loop over levels + DO K = 1, ND50_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND50_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND50_NI + I = GET_I( X ) + + ! Archive by simulation + IF ( N <= N_TRACERS ) THEN + + !-------------------------------------- + ! GEOS-CHEM TRACERS [v/v] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,N) * TCVV(N) / AD(I,J,L) ) + + ELSE IF ( N == 89 .and. IS_Ox .and. IS_CHEM ) THEN + + !-------------------------------------- + ! PURE O3 CONCENTRATION [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTOX) * FRACO3(I,J,L) * + & TCVV(IDTOX) / AD(I,J,L) ) + + ELSE IF ( N == 90 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO CONCENTRATION [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) ) + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !-------------------------------------- + ! NOy CONCENTRATION [v/v] + !-------------------------------------- + + ! Temp variable for accumulation + TMP = 0d0 + + ! NOx + TMP = TMP + ( TCVV(IDTNOX) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + + ! PAN + TMP = TMP + ( TCVV(IDTPAN) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + TMP = TMP + ( TCVV(IDTHNO3) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + TMP = TMP + ( TCVV(IDTPMN) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + TMP = TMP + ( TCVV(IDTPPN) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + TMP = TMP + ( TCVV(IDTR4N2) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + TMP = TMP + ( 2d0 * TCVV(IDTN2O5) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + TMP = TMP + ( TCVV(IDTHNO4) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + + ! Accumulate into Q + Q(X,Y,K,W) = Q(X,Y,K,W) + TMP + + ELSE IF ( N == 74 .and. IS_FULLCHEM .and. IS_CHEM ) THEN + + !-------------------------------------- + ! OH CONCENTRATION [molec/cm3] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + SAVEOH(I,J,L) + + ELSE IF ( N == 75 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO2 CONCENTRATION [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO2(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) ) + + ELSE IF ( N == 76 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [m] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + GET_PBL_TOP_m( I, J ) + ENDIF + + ELSE IF ( N == 77 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [layers] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + GET_PBL_TOP_L( I, J ) + ENDIF + + ELSE IF ( N == 78 ) THEN + + !-------------------------------------- + ! AIR DENSITY [molec/cm3] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 ) + + ELSE IF ( N == 79 ) THEN + + !-------------------------------------- + ! 3_D CLOUD FRACTION [unitless] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + CLDF(L,I,J) + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !-------------------------------------- + ! COLUMN OPTICAL DEPTH [unitless] + !-------------------------------------- + Q(X,Y,1,W) = Q(X,Y,1,W) + OPTD(L,I,J) + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !-------------------------------------- + ! CLOUD TOP HEIGHTS [mb] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + GET_PEDGE(I,J,CLDTOPS(I,J)) + ENDIF + + ELSE IF ( N == 82 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+R-1) / QAA(4,IND(1)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + ODAER(I,J,L,R) * SCALEAODnm + ENDDO + + ELSE IF ( N == 83 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + ODAER(I,J,L,H) * SCALEAODnm + ENDDO + + ELSE IF ( N == 84 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ORG CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 2*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + ODAER(I,J,L,H) * SCALEAODnm + ENDDO + + ELSE IF ( N == 85 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 3*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + ODAER(I,J,L,H) * SCALEAODnm + ENDDO + + ELSE IF ( N == 86 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! COARSE SEASALT AOD 400 nm [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 4*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + ODAER(I,J,L,H) * SCALEAODnm + ENDDO + + ELSE IF ( N == 87 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! TOTAL DUST OPTD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + ODMDUST(I,J,L,R)*SCALEAODnm + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !-------------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTSALA) + + & STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) + + ELSE IF ( N == 93 ) THEN + + !-------------------------------------- + ! GRID BOX HEIGHTS [m] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + BXHEIGHT(I,J,L) + + ELSE IF ( N == 94 ) THEN + + !-------------------------------------- + ! RELATIVE HUMIDITY [%] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + RH(I,J,L) + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !-------------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + SLP(I,J) + ENDIF + + ELSE IF ( N == 96 ) THEN + + !-------------------------------------- + ! ZONAL (U) WIND [m/s] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + UWND(I,J,L) + + ELSE IF ( N == 97 ) THEN + + !-------------------------------------- + ! MERIDIONAL (V) WIND [m/s] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + VWND(I,J,L) + + ELSE IF ( N == 98 ) THEN + + !-------------------------------------- + ! SURFACE PRESSURE - PTOP [hPa] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + ( GET_PEDGE(I,J,K) - PTOP ) + ENDIF + + ELSE IF ( N == 99 ) THEN + + !-------------------------------------- + ! TEMPERATURE [K] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + T(I,J,L) + + ENDIF + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE ACCUMULATE_DIAG50 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_WRITE_DIAG50() RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_WRITE_DIAG51 returns TRUE if it's time to write +! the ND51 bpch file to disk. We test the time at the next dynamic timestep, +! so that we can close the file before the end of the run properly. +! (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE, GET_TS_DYN + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: HR1, HR2 + + !================================================================= + ! ITS_TIME_FOR_WRITE_DIAG50 begins here! + !================================================================= + + ! Current hour + HR1 = GET_HOUR() + ( GET_MINUTE() / 60d0 ) + + ! Hour at the next dynamic timestep + HR2 = HR1 + ( GET_TS_DYN() / 60d0 ) + + ! If the next dyn step is the start of a new day, return TRUE + ITS_TIME = ( INT( HR2 ) == 24 ) + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_WRITE_DIAG50 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG50 +! +!****************************************************************************** +! Subroutine WRITE_DIAG50 computes the 24-hr time-average of quantities +! and saves to bpch file format. (bmy, 12/1/00, 10/7/08) +! +! NOTES: +! (1 ) Rewrote to remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. (bmy, 7/20/04) +! (2 ) Now only archive NO, NO2, OH, O3 on every chemistry timestep (i.e. +! only when fullchem is called). Also remove reference to FIRST. +! (bmy, 10/25/04) +! (3 ) Now divide tracers 82-87 (i.e. various AOD's) by GOOD_CT_CHEM since +! these are only updated once per chemistry timestep (bmy, 1/14/05) +! (4 ) Now save grid box heights as tracer #93. Now save 3-D cloud fraction +! as tracer #79. (bmy, 4/20/05) +! (5 ) Remove references to TRCOFFSET because it's always zero (bmy, 6/24/05) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) DIVISOR is now a 3-D array. Now zero COUNT_CHEM3D. Now zero Q +! array with array assignment statement. (phs, 1/24/07) +! (8 ) RH should be tracer #17 under "TIME-SER" category (bmy, 2/11/08) +! (9 ) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, 10/7/08) +!****************************************************************************** +! + ! Reference to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_MODELNAME + USE BPCH2_MOD, ONLY : GET_HALFPOLAR, OPEN_BPCH2_FOR_WRITE + USE ERROR_MOD, ONLY : ALLOC_ERR + USE FILE_MOD, ONLY : IU_ND50 + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : EXPAND_DATE, GET_NYMD, GET_NHMS + USE TIME_MOD, ONLY : GET_TAU, GET_TS_DYN, TIMESTAMP_STRING + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size Parameters + + ! Local variables + INTEGER :: DIVISOR(ND50_NI,ND50_NJ,ND50_NL) + INTEGER :: I, J, L, W, N + INTEGER :: GMNL, GMTRC, IOS, X, Y, K + CHARACTER(LEN=16) :: STAMP + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! WRITE_DIAG50 begins here! + !================================================================= + + ! Replace time & date tokens in the filename + FILENAME = ND50_OUTPUT_FILE + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - DIAG50: Opening file ', a ) + + ! Open output file + CALL OPEN_BPCH2_FOR_WRITE( IU_ND50, FILENAME, TITLE ) + + ! Set ENDING TAU for this bpch write + TAU1 = GET_TAU() + + !================================================================= + ! Compute 24-hr average quantities for bpch file output + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 110 ) STAMP + 110 FORMAT( ' - DIAG50: Saving to disk at ', a ) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, W, DIVISOR ) + DO W = 1, ND50_N_TRACERS + + ! Pick the proper divisor, depending on whether or not the + ! species in question is archived only each chem timestep + SELECT CASE ( ND50_TRACERS(W) ) + CASE( 89, 90, 74, 75 ) + DIVISOR = COUNT_CHEM3D + CASE( 82:87 ) + DIVISOR = COUNT_CHEM + CASE DEFAULT + DIVISOR = COUNT + END SELECT + + ! Loop over grid boxes + DO K = 1, ND50_NL + DO Y = 1, ND50_NJ + DO X = 1, ND50_NI + + ! Avoid division by zero + IF ( DIVISOR(X,Y,K) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / DBLE( DIVISOR(X,Y,K) ) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !================================================================= + ! Write each tracer from "timeseries.dat" to the timeseries file + !================================================================= + DO W = 1, ND50_N_TRACERS + + ! ND50 tracer number + N = ND50_TRACERS(W) + + ! Save by simulation + IF ( N <= N_TRACERS ) THEN + + !--------------------- + ! GEOS-CHEM tracers + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND50_NL + GMTRC = N + + ELSE IF ( N == 89 ) THEN + + !--------------------- + ! Pure O3 + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND50_NL + GMTRC = N_TRACERS + 1 + + ELSE IF ( N == 90 ) THEN + + !--------------------- + ! Pure NO + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND50_NL + GMTRC = 9 + + ELSE IF ( N == 91 ) THEN + + !--------------------- + ! NOy + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND50_NL + GMTRC = 3 + + ELSE IF ( N == 74 ) THEN + + !--------------------- + ! OH + !--------------------- + CATEGORY = 'CHEM-L=$' + UNIT = 'molec/cm3' + GMNL = ND50_NL + GMTRC = 1 + + ELSE IF ( N == 75 ) THEN + + !--------------------- + ! NO2 + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' + GMNL = ND50_NL + GMTRC = 25 + + ELSE IF ( N == 76 ) THEN + + !--------------------- + ! PBL Height [m] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 77 ) THEN + + !--------------------- + ! PBL Height [layers] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMNL = 1 + GMTRC = 2 + + ELSE IF ( N == 78 ) THEN + + !--------------------- + ! Air Density + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND50_NL + GMTRC = 22 + + ELSE IF ( N == 79 ) THEN + + !--------------------- + ! 3-D Cloud fractions + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = ND50_NL + GMTRC = 19 + + ELSE IF ( N == 80 ) THEN + + !--------------------- + ! Column opt depths + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = 1 + GMTRC = 20 + + ELSE IF ( N == 81 ) THEN + + !--------------------- + ! Cloud top heights + !--------------------- + CATEGORY = 'TIME-SER' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 82 ) THEN + + !--------------------- + ! Sulfate AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND50_ NL + GMTRC = 6 + + ELSE IF ( N == 83 ) THEN + + !--------------------- + ! Black Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND50_NL + GMTRC = 9 + + ELSE IF ( N == 84 ) THEN + + !--------------------- + ! Organic Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND50_ NL + GMTRC = 12 + + ELSE IF ( N == 85 ) THEN + + !--------------------- + ! SS Accum AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND50_NL + GMTRC = 15 + + ELSE IF ( N == 86 ) THEN + + !--------------------- + ! SS Coarse AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND50_NL + GMTRC = 18 + + ELSE IF ( N == 87 ) THEN + + !--------------------- + ! Total dust OD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND50_NL + GMTRC = 4 + + ELSE IF ( N == 88 ) THEN + + !---------------------- + ! Total Seasalt + !---------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND50_NL + GMTRC = 24 + + ELSE IF ( N == 93 ) THEN + + !--------------------- + ! Grid box heights + !--------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMNL = ND50_NL + GMTRC = 1 + + ELSE IF ( N == 94 ) THEN + + !--------------------- + ! Relative humidity + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMNL = ND50_NL + GMTRC = 17 + + ELSE IF ( N == 95 ) THEN + + !--------------------- + ! Sea level prs [hPa] + !--------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 96 ) THEN + + !--------------------- + ! U-wind [m/s] + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND50_NL + GMTRC = 1 + + ELSE IF ( N == 97 ) THEN + + !--------------------- + ! V-wind [m/s] + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND50_NL + GMTRC = 2 + + ELSE IF ( N == 98 ) THEN + + !--------------------- + ! Psurface [hPa] + !--------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 99 ) THEN + + !--------------------- + ! Temperature + !--------------------- + CATEGORY = 'DAO-3D-$' + GMNL = ND50_NL + GMTRC = 3 + + ELSE + + ! Otherwise skip + CYCLE + + ENDIF + + !------------------------ + ! Save to bpch file + !------------------------ + CALL BPCH2( IU_ND50, MODELNAME, LONRES, + & LATRES, HALFPOLAR, CENTER180, + & CATEGORY, GMTRC, UNIT, + & TAU0, TAU1, RESERVED, + & ND50_NI, ND50_NJ, GMNL, + & ND50_IMIN+I0, ND50_JMIN+J0, ND50_LMIN, + & REAL( Q(1:ND50_NI, 1:ND50_NJ, 1:GMNL, W) ) ) + ENDDO + + ! Echo info + WRITE( 6, 120 ) TRIM( FILENAME ) + 120 FORMAT( ' - DIAG50: Closing file ', a ) + + ! Close file + CLOSE( IU_ND50 ) + + !================================================================= + ! Re-initialize quantities for the next diagnostic cycle + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 130 ) STAMP + 130 FORMAT( ' - DIAG50: Zeroing arrays at ', a ) + + ! Set STARTING TAU for the next bpch write + TAU0 = GET_TAU() + ( GET_TS_DYN() / 60d0 ) + + ! Zero counters + COUNT = 0 + COUNT_CHEM = 0 + COUNT_CHEM3D = 0 + + ! Zero accumulating array + Q = 0d0 + + ! Return to calling program + END SUBROUTINE WRITE_DIAG50 + +!------------------------------------------------------------------------------ + + FUNCTION GET_I( X ) RESULT( I ) +! +!****************************************************************************** +! Function GET_I returns the absolute longitude index (I), given the +! relative longitude index (X). (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (INTEGER) : Relative longitude index (used by Q) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: X + + ! Local variables + INTEGER :: I + + !================================================================= + ! GET_I begins here! + !================================================================= + + ! Add the offset to X to get I + I = IOFF + X + + ! Handle wrapping around the date line, if necessary + IF ( I > IIPAR ) I = I - IIPAR + + ! Return to calling program + END FUNCTION GET_I + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG50( DO_ND50, N_ND50, TRACERS, IMIN, IMAX, + & JMIN, JMAX, LMIN, LMAX, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG50 allocates and zeroes all module arrays. +! It also gets values for module variables from "input_mod.f". +! (bmy, 7/20/04, 1/24/07) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND50 (LOGICAL ) : Switch to turn on ND50 timeseries diagnostic +! (2 ) N_ND50 (INTEGER ) : Number of ND50 read by "input_mod.f" +! (3 ) TRACERS (INTEGER ) : Array w/ ND50 tracer #'s read by "input_mod.f" +! (4 ) IMIN (INTEGER ) : Min longitude index read by "input_mod.f" +! (5 ) IMAX (INTEGER ) : Max longitude index read by "input_mod.f" +! (6 ) JMIN (INTEGER ) : Min latitude index read by "input_mod.f" +! (7 ) JMAX (INTEGER ) : Min latitude index read by "input_mod.f" +! (8 ) LMIN (INTEGER ) : Min level index read by "input_mod.f" +! (9 ) LMAX (INTEGER ) : Min level index read by "input_mod.f" +! (11) FILE (CHAR*255) : ND50 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Now get I0 and J0 correctly for nested grid simulations (bmy, 11/9/04) +! (2 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (3 ) Now allow ND50_IMIN to be equal to ND50_IMAX and ND50_JMIN to be +! equal to ND50_JMAX. This will allow us to save out longitude +! or latitude transects. Now allocate COUNT_CHEM3D array. +! (cdh, phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, ITS_A_NESTED_GRID + USE TIME_MOD, ONLY : GET_TAUb + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND50 + INTEGER, INTENT(IN) :: N_ND50, TRACERS(100) + INTEGER, INTENT(IN) :: IMIN, IMAX + INTEGER, INTENT(IN) :: JMIN, JMAX + INTEGER, INTENT(IN) :: LMIN, LMAX + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + INTEGER :: AS + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG50 begins here! + !================================================================= + + ! Initialize + LOCATION = 'INIT_DIAG50 ("diag50_mod.f")' + ND50_TRACERS(:) = 0 + + ! Get values from "input_mod.f" + DO_SAVE_DIAG50 = DO_ND50 + ND50_N_TRACERS = N_ND50 + ND50_TRACERS(1:N_ND50) = TRACERS(1:N_ND50) + ND50_IMIN = IMIN + ND50_IMAX = IMAX + ND50_JMIN = JMIN + ND50_JMAX = JMAX + ND50_LMIN = LMIN + ND50_LMAX = LMAX + ND50_OUTPUT_FILE = TRIM( FILE ) + + ! Exit if ND50 is turned off + IF ( .not. DO_SAVE_DIAG50 ) RETURN + + !================================================================= + ! Error check longitude, latitude, altitude limits + !================================================================= + + ! Get grid offsets + IF ( ITS_A_NESTED_GRID() ) THEN + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + ELSE + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + ENDIF + + !----------- + ! Longitude + !----------- + + ! Error check ND50_IMIN + IF ( ND50_IMIN+I0 < 1 .or. ND50_IMIN+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND50_IMIN value!', LOCATION ) + ENDIF + + ! Error check ND50_IMAX + IF ( ND50_IMAX+I0 < 1 .or. ND50_IMAX+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND50_IMAX value!', LOCATION ) + ENDIF + + ! Compute longitude limits to write to disk + ! Also handle wrapping around the date line + IF ( ND50_IMAX >= ND50_IMIN ) THEN + ND50_NI = ( ND50_IMAX - ND50_IMIN ) + 1 + ELSE + ND50_NI = ( IIPAR - ND50_IMIN ) + 1 + ND50_IMAX + WRITE( 6, '(a)' ) 'We are wrapping around the date line!' + ENDIF + + ! Make sure that ND50_NI <= IIPAR + IF ( ND50_NI > IIPAR ) THEN + CALL ERROR_STOP( 'Too many longitudes!', LOCATION ) + ENDIF + + !----------- + ! Latitude + !----------- + + ! Error check JMIN_AREA + IF ( ND50_JMIN+J0 < 1 .or. ND50_JMIN+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND50_JMIN value!', LOCATION ) + ENDIF + + ! Error check JMAX_AREA + IF ( ND50_JMAX+J0 < 1 .or.ND50_JMAX+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND50_JMAX value!', LOCATION ) + ENDIF + + ! Compute latitude limits to write to disk (bey, bmy, 3/16/99) + IF ( ND50_JMAX >= ND50_JMIN ) THEN + ND50_NJ = ( ND50_JMAX - ND50_JMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND50_JMAX < ND50_JMIN!', LOCATION ) + ENDIF + + !----------- + ! Altitude + !----------- + + ! Error check ND50_LMIN, ND50_LMAX + IF ( ND50_LMIN < 1 .or. ND50_LMAX > LLPAR ) THEN + CALL ERROR_STOP( 'Bad ND50 altitude values!', LOCATION ) + ENDIF + + ! # of levels to save in ND50 timeseries + IF ( ND50_LMAX >= ND50_LMIN ) THEN + ND50_NL = ( ND50_LMAX - ND50_LMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND50_LMAX < ND50_LMIN!', LOCATION ) + ENDIF + + !----------- + ! Offsets + !----------- + IOFF = ND50_IMIN - 1 + JOFF = ND50_JMIN - 1 + LOFF = ND50_LMIN - 1 + + !------------ + ! Counter + !------------ + COUNT = 0 + + !------------ + ! For bpch + !------------ + TAU0 = GET_TAUb() + TITLE = 'GEOS-CHEM DIAG50 24hr average time series' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Reset offsets to global values for bpch write + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + !================================================================= + ! Allocate arrays + !================================================================= + + ! Accumulator array + ALLOCATE( Q( ND50_NI, ND50_NJ, ND50_NL, ND50_N_TRACERS), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'Q' ) + Q = 0d0 + + ! 3-D full chemistry timestep counter in troposphere + ALLOCATE( COUNT_CHEM3D( ND50_NI, ND50_NJ, ND50_NL ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'COUNT_CHEM3D' ) + COUNT_CHEM3D = 0d0 + + ! Return to calling program + END SUBROUTINE INIT_DIAG50 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG50 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG50 deallocates all module arrays. +! (bmy, 11/29/00, 1/24/07) +! +! NOTES: +! (1 ) Now deallocate COUNT_CHEM3D (phs, 1/24/07) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG50 begins here! + !================================================================= + IF ( ALLOCATED( Q ) ) DEALLOCATE( Q ) + IF ( ALLOCATED( COUNT_CHEM3D ) ) DEALLOCATE( COUNT_CHEM3D ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG50 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG50_MOD diff --git a/code/diag51_mod.f b/code/diag51_mod.f new file mode 100644 index 0000000..3cbe322 --- /dev/null +++ b/code/diag51_mod.f @@ -0,0 +1,1594 @@ +! $Id: diag51_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE DIAG51_MOD +! +!****************************************************************************** +! Module DIAG51_MOD contains variables and routines to generate save +! timeseries data where the local time is between two user-defined limits. +! This facilitates comparisons with morning or afternoon-passing satellites +! such as GOME. (amf, bey, bdf, pip, bmy, 11/30/00, 12/10/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_DIAG51 (LOGICAL ) : Flag to turn on DIAG51 timseries +! (2 ) GOOD (INTEGER ) : Array denoting grid boxes w/in LT limits +! (3 ) GOOD_CT (INTEGER ) : # of "good" times per grid box +! (4 ) GOOD_CT_CHEM (INTEGER ) : # of "good" chemistry timesteps +! (5 ) COUNT_CHEM3D (INTEGER ) : Counter for 3D chemistry boxes +! (6 ) ND51_HR_WRITE (INTEGER ) : Hour at which to save to disk +! (7 ) I0 (INTEGER ) : Offset between global & nested grid +! (8 ) J0 (INTEGER ) : Offset between global & nested grid +! (9 ) IOFF (INTEGER ) : Longitude offset +! (10) JOFF (INTEGER ) : Latitude offset +! (11) LOFF (INTEGER ) : Altitude offset +! (12) ND51_HR1 (REAL*8 ) : Starting hour of user-defined LT interval +! (13) ND51_HR2 (REAL*8 ) : Ending hour of user-defined LT interval +! (14) ND51_IMIN (INTEGER ) : Minimum latitude index for DIAG51 region +! (15) ND51_IMAX (INTEGER ) : Maximum latitude index for DIAG51 region +! (16) ND51_JMIN (INTEGER ) : Minimum longitude index for DIAG51 region +! (17) ND51_JMAX (INTEGER ) : Maximum longitude index for DIAG51 region +! (18) ND51_LMIN (INTEGER ) : Minimum altitude index for DIAG51 region +! (19) ND51_LMAX (INTEGER ) : Minimum latitude index for DIAG51 region +! (20) ND51_NI (INTEGER ) : Number of longitudes in DIAG51 region +! (21) ND51_NJ (INTEGER ) : Number of latitudes in DIAG51 region +! (22) ND51_NL (INTEGER ) : Number of levels in DIAG51 region +! (23) ND51_N_TRACERS (INTEGER ) : Number of tracers for DIAG51 +! (24) ND51_OUTPUT_FILE (CHAR*255) : Name of bpch file w timeseries data +! (25) ND51_TRACERS (INTEGER ) : Array of DIAG51 tracer numbers +! (26) Q (REAL*8 ) : Accumulator array for various quantities +! (27) TAU0 (REAL*8 ) : Starting TAU used to index the bpch file +! (28) TAU1 (REAL*8 ) : Ending TAU used to index the bpch file +! (29) HALFPOLAR (INTEGER ) : Used for bpch file output +! (30) CENTER180 (INTEGER ) : Used for bpch file output +! (31) LONRES (REAL*4 ) : Used for bpch file output +! (32) LATRES (REAL*4 ) : Used for bpch file output +! (33) MODELNAME (CHAR*20 ) : Used for bpch file output +! (34) RESERVED (CHAR*40 ) : Used for bpch file output +! +! Module Procedures: +! ============================================================================ +! (1 ) DIAG51 : Driver subroutine for US grid timeseries +! (2 ) GET_LOCAL_TIME : Computes the local times at each grid box +! (3 ) WRITE_DIAG51 : Writes timeseries data to a bpch file +! (4 ) ITS_TIME_FOR_WRITE_DIAG51 : Returns T if it's time to save to disk +! (5 ) ACCUMULATE_DIAG51 : Accumulates data over for later averaging +! (6 ) INIT_DIAG51 : Allocates and zeroes all module arrays +! (7 ) CLEANUP_DIAG51 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag51_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) error_mod.f : Module w/ NaN and other error check routines +! (4 ) file_mod.f : Module w/ file unit numbers and error checks +! (5 ) grid_mod.f : Module w/ horizontal grid information +! (6 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (7 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (8 ) time_mod.f : Module w/ routines to compute date & time +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND51 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D Cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box heights [m ] +! 94 : Relative Humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added extra counters for NO, NO2, OH, O3. Also all diagnostic counter +! arrays are 1-D since they only depend on longitude. (bmy, 10/25/04) +! (3 ) Bug fix: Now get I0 and J0 properly for nested grids (bmy, 11/9/04) +! (4 ) Now only archive AOD's once per chemistry timestep (bmy, 1/14/05) +! (5 ) Now references "pbl_mix_mod.f" (bmy, 2/16/05) +! (6 ) Now save cld frac and grid box heights (bmy, 4/20/05) +! (7 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (8 ) Bug fix: do not save SLP if it's not allocated (bmy, 8/2/05) +! (9 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (10) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (11) Modified INIT_DIAG51 to save out transects (cdh, bmy, 11/30/06) +! (12) Now use 3D timestep counter for full chem in the trop (phs, 1/24/07) +! (13) Renumber RH in WRITE_DIAG50 (bmy, 2/11/08) +! (14) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +! (15) Bug fix in GET_LOCAL_TIME (ccc, 12/10/08) +! (16) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 9/26/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag51_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG51 + + ! ... and these routines + PUBLIC :: CLEANUP_DIAG51 + PUBLIC :: DIAG51 + PUBLIC :: INIT_DIAG51 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_DIAG51 + INTEGER :: IOFF, JOFF, LOFF + INTEGER :: I0, J0 + INTEGER :: ND51_N_TRACERS, ND51_TRACERS(100) + INTEGER :: ND51_IMIN, ND51_IMAX + INTEGER :: ND51_JMIN, ND51_JMAX + INTEGER :: ND51_LMIN, ND51_LMAX + INTEGER :: ND51_FREQ, ND51_NI + INTEGER :: ND51_NJ, ND51_NL + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES, LATRES + REAL*8 :: TAU0, TAU1 + REAL*8 :: ND51_HR1, ND51_HR2 + REAL*8 :: ND51_HR_WRITE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = '' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND51_OUTPUT_FILE + + ! Arrays + INTEGER, ALLOCATABLE :: GOOD(:) + INTEGER, ALLOCATABLE :: GOOD_CT(:) + INTEGER, ALLOCATABLE :: GOOD_CT_CHEM(:) + INTEGER, ALLOCATABLE :: COUNT_CHEM3D(:,:,:) + REAL*8, ALLOCATABLE :: Q(:,:,:,:) + + !================================================================= + ! Original code from old DIAG51_MOD. Leave here as a guide to + ! figure out when the averaging periods should be and when to + ! write to disk (bmy, 9/28/04) + ! + !! For timeseries between 1300 and 1700 LT, uncomment this code: + !! + !! Need to write to the bpch file at 12 GMT, since this covers + !! an entire day over the US grid (amf, bmy, 12/1/00) + !! + !INTEGER, PARAMETER :: NHMS_WRITE = 120000 + !REAL*8, PARAMETER :: HR1 = 13d0 + !REAL*8, PARAMETER :: HR2 = 17d0 + !CHARACTER(LEN=255) :: FILENAME = 'ts1_4pm.bpch' + !================================================================= + ! For timeseries between 1000 and 1200 LT, uncomment this code: + ! + ! Between 10 and 12 has been chosen because the off-polar orbit + ! of GOME traverses (westward) through local times between 12 + ! and 10 over North America, finally crossing the equator at + ! 10.30 (local time). + ! + ! Need to write to the bpch file at 00 GMT, since we will be + ! interested in the whole northern hemisphere (pip, 12/1/00) + ! + !INTEGER, PARAMETER :: NHMS_WRITE = 000000 + !REAL*8, PARAMETER :: HR1 = 10d0 + !REAL*8, PARAMETER :: HR2 = 12d0 + !CHARACTER(LEN=255) :: FILENAME ='ts10_12pm.bpch' + !================================================================= + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG51 +! +!****************************************************************************** +! Subroutine DIAG51 generates time series (averages from 10am - 12pm LT +! or 1pm - 4pm LT) for the US grid area. Output is to binary punch files. +! (amf, bey, bdf, pip, bmy, 11/15/99, 9/28/04) +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added TAU_W as a local variable (bmy, 9/28/04) +!****************************************************************************** +! + ! Local variables + REAL*8 :: TAU_W + + !================================================================= + ! DIAG51 begins here! + !================================================================= + + ! Construct array of where local times are between HR1, HR2 + CALL GET_LOCAL_TIME + + ! Accumulate data in the Q array + CALL ACCUMULATE_DIAG51 + + ! Write data to disk at the proper time + IF ( ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) ) THEN + CALL WRITE_DIAG51( TAU_W ) + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG51 + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_LOCAL_TIME +! +!****************************************************************************** +! Subroutine GET_LOCAL_TIME computes the local time and returns an array +! of points where the local time is between two user-defined limits. +! (bmy, 11/29/00, 12/10/08) +! +! NOTES: +! (1 ) The 1d-3 in the computation of XLOCTM is to remove roundoff ambiguity +! if a the local time should fall exactly on an hour boundary. +! (bmy, 11/29/00) +! (2 ) Bug fix: XMID(I) should be XMID(II). Also updated comments. +! (bmy, 7/6/01) +! (3 ) Updated comments (rvm, bmy, 2/27/02) +! (4 ) Now uses function GET_LOCALTIME of "time_mod.f" (bmy, 3/27/03) +! (5 ) Removed reference to CMN (bmy, 7/20/04) +! (6 ) Bug fix: LT should be REAL*8 and not INTEGER (ccarouge, 12/10/08) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_LOCALTIME + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + !------------------------------------------ + ! Prior to 12/10/08: + ! LT should be REAL*8 (ccarouge, 12/10/08) + !INTEGER :: I, LT + !------------------------------------------ + INTEGER :: I + REAL*8 :: LT + + !================================================================= + ! GET_LOCAL_TIME begins here! + !================================================================= + DO I = 1, IIPAR + + ! Get local time + LT = GET_LOCALTIME(I) + + ! GOOD indicates which boxes have local times between HR1 and HR2 + IF ( LT >= ND51_HR1 .and. LT <= ND51_HR2 ) THEN + GOOD(I) = 1 + ELSE + GOOD(I) = 0 + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE GET_LOCAL_TIME + +!------------------------------------------------------------------------------ + + SUBROUTINE ACCUMULATE_DIAG51 +! +!****************************************************************************** +! Subroutine ACCUMULATE_DIAG51 accumulates tracers into the Q array. +! (bmy, 8/20/02, 1/24/07) +! +! NOTES: +! (1 ) Rewrote to remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. Now scale optical depths +! to 400 nm (which is usually what QAA(2,*) is. (bmy, 7/20/04) +! (2 ) Now reference GET_ELAPSED_MIN and GET_TS_CHEM from "time_mod.f". +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). (bmy, 10/25/04) +! (3 ) Only archive AOD's when it is a chem timestep (bmy, 1/14/05) +! (4 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (5 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D cloud +! fraction as tracer #79 and box height as tracer #93. Now remove +! references to CLMOSW, CLROSW, and PBL from "dao_mod.f". (bmy, 4/20/05) +! (6 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (7 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (8 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (9 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (10) Now account for time spent in the trop for non-tracers (phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, T + USE DAO_MOD, ONLY : UWND, VWND, SLP + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : GET_ELAPSED_MIN, GET_TS_CHEM + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : STT, TCVV, ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : N_TRACERS, XNUMOLAIR + USE TRACERID_MOD, ONLY : IDTHNO3, IDTHNO4, IDTN2O5, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + +# include "cmn_fj.h" ! includes CMN_SIZE +# include "jv_cmn.h" ! ODAER +# include "CMN_O3" ! FRACO3, FRACNO, SAVEO3, SAVENO2, SAVEHO2, FRACNO2 +# include "CMN_GCTM" ! SCALE_HEIGHT + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: IS_FULLCHEM, IS_NOx, IS_Ox, IS_SEASALT + LOGICAL, SAVE :: IS_CLDTOPS, IS_NOy, IS_OPTD, IS_SLP + LOGICAL :: IS_CHEM + INTEGER :: H, I, J, K, L, M, N + INTEGER :: PBLINT, R, X, Y, W, XMIN + REAL*8 :: C1, C2, PBLDEC, TEMPBL, TMP, SCALEAODnm + CHARACTER(LEN=16) :: STAMP + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + + !================================================================= + ! ACCUMULATE_DIAG51 begins here! + !================================================================= + + ! Set logical flags on first call + IF ( FIRST ) THEN + IS_OPTD = ALLOCATED( OPTD ) + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOx > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + FIRST = .FALSE. + ENDIF + + ! Is it a chemistry timestep? + IS_CHEM = ( MOD( GET_ELAPSED_MIN(), GET_TS_CHEM() ) == 0 ) + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 100 ) STAMP + 100 FORMAT( ' - DIAG51: Accumulation at ', a ) + + !================================================================= + ! Archive tracers into accumulating array Q + !================================================================= + + ! Archive counter array of good points + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT(X) = GOOD_CT(X) + GOOD(I) + ENDDO + + ! Archive counter array of good points for chemistry timesteps only + IF ( IS_CHEM ) THEN + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT_CHEM(X) = GOOD_CT_CHEM(X) + GOOD(I) + ENDDO + ENDIF + + + ! Also increment 3-D counter for boxes in the tropopause + IF ( IS_FULLCHEM .and. IS_CHEM ) THEN + + ! Loop over levels +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, I, J, L ) +!$OMP+SCHEDULE( DYNAMIC ) + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Only increment if we are in the trop + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + COUNT_CHEM3D(X,Y,K) = COUNT_CHEM3D(X,Y,K) + GOOD(I) + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !------------------------ + ! Accumulate quantities + !------------------------ +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( W, N, X, Y, K, I, J, L, TMP, H, R, SCALEAODnm ) +!$OMP+SCHEDULE( DYNAMIC ) + DO W = 1, ND51_N_TRACERS + + ! ND51 Tracer number + N = ND51_TRACERS(W) + + ! Loop over levels + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Archive by simulation + IF ( N <= N_TRACERS ) THEN + + !-------------------------------------- + ! GEOS-CHEM tracers [v/v] + !-------------------------------------- + + ! Archive afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,N) * TCVV(N) / + & AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 89 .and. IS_Ox .and. IS_CHEM ) THEN + + !-------------------------------------- + ! Pure O3 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTOX) * FRACO3(I,J,L) * + & TCVV(IDTOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 90 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !-------------------------------------- + ! NOy [v/v] + !-------------------------------------- + + ! Temp variable for accumulation + TMP = 0d0 + + ! NOx + TMP = TMP + ( TCVV(IDTNOX) * GOOD(I) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + ! PAN + TMP = TMP + ( TCVV(IDTPAN) * GOOD(I) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + TMP = TMP + ( TCVV(IDTHNO3) * GOOD(I) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + TMP = TMP + ( TCVV(IDTPMN) * GOOD(I) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + TMP = TMP + ( TCVV(IDTPPN) * GOOD(I) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + TMP = TMP + ( TCVV(IDTR4N2) * GOOD(I) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + TMP = TMP + ( 2d0 * TCVV(IDTN2O5) * GOOD(I) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + TMP = TMP + ( TCVV(IDTHNO4) * GOOD(I) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + + ! Save afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + TMP + + ELSE IF ( N == 74 .and. IS_FULLCHEM .and. IS_CHEM ) THEN + + !-------------------------------------- + ! OH [molec/cm3] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SAVEOH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 75 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO2 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO2(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 76 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [m] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_m( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 77 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [layers] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_L( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 78 ) THEN + + !-------------------------------------- + ! AIR DENSITY [molec/cm3] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 * GOOD(I) ) + + ELSE IF ( N == 79 ) THEN + + !-------------------------------------- + ! 3-D CLOUD FRACTION [unitless] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( CLDF(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !-------------------------------------- + ! COLUMN OPTICAL DEPTH [unitless] + !-------------------------------------- + Q(X,Y,1,W) = Q(X,Y,1,W) + ( OPTD(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !-------------------------------------- + ! CLOUD TOP HEIGHTS [mb] + !-------------------------------------- + IF ( K == 1 ) THEN + TMP = GET_PEDGE( I, J, CLDTOPS(I,J) ) + Q(X,Y,K,W) = Q(X,Y,K,W) + ( TMP * GOOD(I) ) + ENDIF + + ELSE IF ( N == 82 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO H = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+H-1) / QAA(4,IND(1)+H-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 83 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 84 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ORG CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 2*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 85 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 3*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 86 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! COARSE SEASALT AOD 400 nm [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 4*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 87 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! TOTAL DUST OPTD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODMDUST(I,J,L,R) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !----------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTSALA) + + & STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) * GOOD(I) + + ELSE IF ( N == 93 ) THEN + + !----------------------------------- + ! GRID BOX HEIGHTS [m] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( BXHEIGHT(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 94 ) THEN + + !----------------------------------- + ! RELATIVE HUMIDITY [%] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( RH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !----------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !----------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SLP(I,J) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 96 ) THEN + + !----------------------------------- + ! ZONAL (U) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( UWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 97 ) THEN + + !----------------------------------- + ! MERIDIONAL (V) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( VWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 98 ) THEN + + !----------------------------------- + ! PEDGE-$ (prs @ level edges) [hPa] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( GET_PEDGE(I,J,K) * GOOD(I) ) + + ELSE IF ( N == 99 ) THEN + + !----------------------------------- + ! TEMPERATURE [K] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( T(I,J,L) * GOOD(I) ) + + ENDIF + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE ACCUMULATE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_WRITE_DIAG51 returns TRUE if it's time to write +! the ND51 bpch file to disk. We test the time at the next dynamic +! timestep so that we can write to disk properly. (bmy, 7/20/04, 9/28/04) +! +! Arguments as Output: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Added TAU_W so to make sure the timestamp is accurate. (bmy, 9/28/04) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE, GET_TAU, + & GET_TAUb, GET_TAUe, GET_TS_DYN + + ! Arguments + REAL*8, INTENT(OUT) :: TAU_W + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: TAU, HOUR, DYN + + !================================================================= + ! ITS_TIME_FOR_WRITE_DIAG51 begins here! + !================================================================= + + ! Initialize + ITS_TIME = .FALSE. + + ! Current TAU, Hour, and Dynamic Timestep [hrs] + TAU = GET_TAU() + HOUR = ( GET_MINUTE() / 60d0 ) + GET_HOUR() + DYN = ( GET_TS_DYN() / 60d0 ) + + ! If first timestep, return FALSE + IF ( TAU == GET_TAUb() ) RETURN + + ! If the next dyn timestep is the hour of day + ! when we have to save to disk, return TRUE + IF ( MOD( HOUR+DYN, 24d0 ) == ND51_HR_WRITE ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! If the next dyn timestep is the + ! end of the run, return TRUE + IF ( TAU + DYN == GET_TAUe() ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG51( TAU_W ) +! +!****************************************************************************** +! Subroutine WRITE_DIAG51 computes the time-average of quantities between +! local time limits ND51_HR1 and ND51_HR2 and writes them to a bpch file. +! Arrays and counters are also zeroed for the next diagnostic interval. +! (bmy, 12/1/00, 10/7/08) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Rewrote to` remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. (bmy, 7/20/04) +! (2 ) Added TAU_W to the arg list. Now use TAU_W to set TAU0 and TAU0. +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). Also remove reference +! to FIRST. (bmy, 10/25/04) +! (3 ) Now divide tracers 82-87 (i.e. various AOD's) by GOOD_CT_CHEM since +! these are only updated once per chemistry timestep (bmy, 1/14/05) +! (4 ) Now save grid box heights as tracer #93. Now save 3-D cloud fraction +! as tracer #79 (bmy, 4/20/05) +! (5 ) Remove references to TRCOFFSET because it's always zero (bmy, 6/24/05) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) DIVISOR is now a 3-D array. Now zero COUNT_CHEM3D. Now use CASE +! statement instead of IF statements. Now zero counter arrays with +! array broadcast assignments. (phs, 1/24/07) +! (8 ) RH should be tracer #17 under "TIME-SER" category (bmy, 2/11/08) +! (9 ) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +!****************************************************************************** +! + ! Reference to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, OPEN_BPCH2_FOR_WRITE + USE ERROR_MOD, ONLY : ALLOC_ERR + USE FILE_MOD, ONLY : IU_ND51 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_NYMD + USE TIME_MOD, ONLY : GET_NHMS, GET_TAU + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size Parameters + + ! Arguments + REAL*8, INTENT(IN) :: TAU_W + + ! Local variables + INTEGER :: I, J, L, W, N, GMNL, GMTRC + INTEGER :: IOS, X, Y, K + CHARACTER(LEN=16) :: STAMP + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! WRITE_DIAG51 begins here! + !================================================================= + + ! Replace date tokens in FILENAME + FILENAME = ND51_OUTPUT_FILE + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - DIAG51: Opening file ', a ) + + ! Open output file + CALL OPEN_BPCH2_FOR_WRITE( IU_ND51, FILENAME, TITLE ) + + ! Set ENDING TAU for this bpch write + TAU1 = TAU_W + + !================================================================= + ! Compute time-average of tracers between local time limits + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 110 ) STAMP + 110 FORMAT( ' - DIAG51: Saving to disk at ', a ) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, W ) + + DO W = 1, ND51_N_TRACERS + + ! Loop over grid boxes + DO K = 1, ND51_NL + DO Y = 1, ND51_NJ + DO X = 1, ND51_NI + + SELECT CASE( ND51_TRACERS(W) ) + + CASE( 89, 90, 74, 75 ) + !-------------------------------------------------------- + ! Avoid div by zero for tracers which are archived each + ! chem timestep and only available in the troposphere + !-------------------------------------------------------- + IF ( COUNT_CHEM3D(X,Y,K) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / COUNT_CHEM3D(X,Y,K) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE( 82:87 ) + + !-------------------------------------------------------- + ! Avoid division by zero for tracers which are archived + ! on each chem timestep (at trop & strat levels) + !-------------------------------------------------------- + IF ( GOOD_CT_CHEM(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT_CHEM(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE DEFAULT + + !-------------------------------------------------------- + ! Avoid division by zero for all other tracers + !-------------------------------------------------------- + IF ( GOOD_CT(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + END SELECT + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !================================================================= + ! Write each tracer from "timeseries.dat" to the timeseries file + !================================================================= + DO W = 1, ND51_N_TRACERS + + ! ND51 tracer number + N = ND51_TRACERS(W) + + ! Save by simulation + IF ( N <= N_TRACERS ) THEN + + !--------------------- + ! GEOS-CHEM tracers + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N + + ELSE IF ( N == 89 ) THEN + + !--------------------- + ! Pure O3 + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N_TRACERS + 1 + + ELSE IF ( N == 90 ) THEN + !--------------------- + ! Pure NO [v/v] + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 91 ) THEN + !--------------------- + ! NOy + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 3 + + ELSE IF ( N == 74 ) THEN + + !--------------------- + ! OH + !--------------------- + CATEGORY = 'CHEM-L=$' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 75 ) THEN + + !--------------------- + ! NO2 + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 25 + + ELSE IF ( N == 76 ) THEN + + !--------------------- + ! PBL Height [m] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 77 ) THEN + + !--------------------- + ! PBL Height [levels] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMNL = 1 + GMTRC = 2 + + ELSE IF ( N == 78 ) THEN + + !--------------------- + ! Air Density + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 22 + + ELSE IF ( N == 79 ) THEN + + !--------------------- + ! 3-D Cloud fractions + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 19 + + ELSE IF ( N == 80 ) THEN + + !--------------------- + ! Column opt depths + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = 1 + GMTRC = 20 + + ELSE IF ( N == 81 ) THEN + + !--------------------- + ! Cloud top heights + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 82 ) THEN + + !--------------------- + ! Sulfate AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 6 + + ELSE IF ( N == 83 ) THEN + + !--------------------- + ! Black Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 84 ) THEN + + !--------------------- + ! Organic Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 12 + + ELSE IF ( N == 85 ) THEN + + !--------------------- + ! SS Accum AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 15 + + ELSE IF ( N == 86 ) THEN + + !--------------------- + ! SS Coarse AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 18 + + ELSE IF ( N == 87 ) THEN + + !--------------------- + ! Total dust OD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 4 + + ELSE IF ( N == 88 ) THEN + + !--------------------- + ! Total seasalt + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 24 + + ELSE IF ( N == 93 ) THEN + + !--------------------- + ! Grid box heights + !--------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 94 ) THEN + + !--------------------- + ! Relative humidity + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMNL = ND51_NL + GMTRC = 17 + + ELSE IF ( N == 95 ) THEN + + !--------------------- + ! Sea level prs + !--------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 96 ) THEN + + !--------------------- + ! U-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 97 ) THEN + + !--------------------- + ! V-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 2 + + ELSE IF ( N == 98 ) THEN + + !--------------------- + ! Psurface - PTOP + !--------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 99 ) THEN + + !--------------------- + ! Temperature + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'K' + GMNL = ND51_NL + GMTRC = 3 + + ELSE + + ! Otherwise skip + CYCLE + + ENDIF + + !------------------------ + ! Save to bpch file + !------------------------ + CALL BPCH2( IU_ND51, MODELNAME, LONRES, + & LATRES, HALFPOLAR, CENTER180, + & CATEGORY, GMTRC, UNIT, + & TAU0, TAU1, RESERVED, + & ND51_NI, ND51_NJ, GMNL, + & ND51_IMIN+I0, ND51_JMIN+J0, ND51_LMIN, + & REAL( Q(1:ND51_NI, 1:ND51_NJ, 1:GMNL, W) ) ) + ENDDO + + ! Echo info + WRITE( 6, 120 ) TRIM( FILENAME ) + 120 FORMAT( ' - DIAG51: Closing file ', a ) + + ! Close file + CLOSE( IU_ND51 ) + + !================================================================= + ! Re-initialize quantities for next diagnostic cycle + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 130 ) STAMP + 130 FORMAT( ' - DIAG51: Zeroing arrays at ', a ) + + ! Set STARTING TAU for the next bpch write + TAU0 = TAU_W + + ! Zero accumulating array for tracer + Q = 0d0 + + ! Zero counter arrays + COUNT_CHEM3D = 0d0 + GOOD_CT = 0d0 + GOOD_CT_CHEM = 0d0 + + ! Return to calling program + END SUBROUTINE WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION GET_I( X ) RESULT( I ) +! +!****************************************************************************** +! Function GET_I returns the absolute longitude index (I), given the +! relative longitude index (X). (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (INTEGER) : Relative longitude index (used by Q) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: X + + ! Local variables + INTEGER :: I + + !================================================================= + ! GET_I begins here! + !================================================================= + + ! Add the offset to X to get I + I = IOFF + X + + ! Handle wrapping around the date line, if necessary + IF ( I > IIPAR ) I = I - IIPAR + + ! Return to calling program + END FUNCTION GET_I + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG51( DO_ND51, N_ND51, TRACERS, HR_WRITE, + & HR1, HR2, IMIN, IMAX, + & JMIN, JMAX, LMIN, LMAX, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG51 allocates and zeroes all module arrays. +! It also gets values for module variables from "input_mod.f". +! (bmy, 7/20/04, 1/22/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND51 (LOGICAL ) : Switch to turn on ND51 timeseries diagnostic +! (2 ) N_ND51 (INTEGER ) : Number of ND51 read by "input_mod.f" +! (3 ) TRACERS (INTEGER ) : Array w/ ND51 tracer #'s read by "input_mod.f" +! (4 ) HR_WRITE (REAL*8 ) : GMT hour of day at which to write bpch file +! (5 ) HR1 (REAL*8 ) : Lower limit of local time averaging bin +! (6 ) HR2 (REAL*8 ) : Upper limit of local time averaging bin +! (7 ) IMIN (INTEGER ) : Min longitude index read by "input_mod.f" +! (8 ) IMAX (INTEGER ) : Max longitude index read by "input_mod.f" +! (9 ) JMIN (INTEGER ) : Min latitude index read by "input_mod.f" +! (10) JMAX (INTEGER ) : Min latitude index read by "input_mod.f" +! (11) LMIN (INTEGER ) : Min level index read by "input_mod.f" +! (12) LMAX (INTEGER ) : Min level index read by "input_mod.f" +! (13) FILE (CHAR*255) : ND51 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Diagnostic counter arrays are now only 1-D. Also add GOOD_CT_CHEM +! which is the counter array of "good" boxes at each chemistry +! timesteps. Now allocate GOOD_CT_CHEM. (bmy, 10/25/04) +! (2 ) Now get I0 and J0 correctly for nested grid simulations (bmy, 11/9/04) +! (3 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (4 ) Now allow ND51_IMIN to be equal to ND51_IMAX and ND51_JMIN to be +! equal to ND51_JMAX. This will allow us to save out longitude or +! latitude transects. Allocate COUNT_CHEM3D. (cdh, bmy, phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, ITS_A_NESTED_GRID + USE TIME_MOD, ONLY : GET_TAUb + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND51 + INTEGER, INTENT(IN) :: N_ND51, TRACERS(100) + INTEGER, INTENT(IN) :: IMIN, IMAX + INTEGER, INTENT(IN) :: JMIN, JMAX + INTEGER, INTENT(IN) :: LMIN, LMAX + REAL*8, INTENT(IN) :: HR1, HR2 + REAL*8, INTENT(IN) :: HR_WRITE + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + INTEGER :: AS + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG51 begins here! + !================================================================= + + ! Initialize + LOCATION = 'INIT_DIAG51 ("diag51_mod.f")' + ND51_TRACERS(:) = 0 + + ! Get values from "input_mod.f" + DO_SAVE_DIAG51 = DO_ND51 + ND51_N_TRACERS = N_ND51 + ND51_TRACERS(1:N_ND51) = TRACERS(1:N_ND51) + ND51_HR_WRITE = HR_WRITE + ND51_HR1 = HR1 + ND51_HR2 = HR2 + ND51_IMIN = IMIN + ND51_IMAX = IMAX + ND51_JMIN = JMIN + ND51_JMAX = JMAX + ND51_LMIN = LMIN + ND51_LMAX = LMAX + ND51_OUTPUT_FILE = TRIM( FILE ) + + ! Make sure ND51_HR_WRITE is in the range 0-23.999 hrs + ND51_HR_WRITE = MOD( ND51_HR_WRITE, 24d0 ) + + ! Exit if ND51 is turned off + IF ( .not. DO_SAVE_DIAG51 ) RETURN + + !================================================================= + ! Error check longitude, latitude, altitude limits + !================================================================= + + ! Get grid offsets + IF ( ITS_A_NESTED_GRID() ) THEN + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + ELSE + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + ENDIF + + !----------- + ! Longitude + !----------- + + ! Error check ND51_IMIN + IF ( ND51_IMIN+I0 < 1 .or. ND51_IMIN+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMIN value!', LOCATION ) + ENDIF + + ! Error check ND51_IMAX + IF ( ND51_IMAX+I0 < 1 .or. ND51_IMAX+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMAX value!', LOCATION ) + ENDIF + + ! Compute longitude limits to write to disk + ! Also handle wrapping around the date line + IF ( ND51_IMAX >= ND51_IMIN ) THEN + ND51_NI = ( ND51_IMAX - ND51_IMIN ) + 1 + ELSE + ND51_NI = ( IIPAR - ND51_IMIN ) + 1 + ND51_IMAX + WRITE( 6, '(a)' ) 'We are wrapping over the date line!' + ENDIF + + ! Make sure that ND50_NI <= IIPAR + IF ( ND51_NI > IIPAR ) THEN + CALL ERROR_STOP( 'Too many longitudes!', LOCATION ) + ENDIF + + !----------- + ! Latitude + !----------- + + ! Error check JMIN_AREA + IF ( ND51_JMIN+J0 < 1 .or. ND51_JMIN+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMIN value!', LOCATION ) + ENDIF + + ! Error check JMAX_AREA + IF ( ND51_JMAX+J0 < 1 .or.ND51_JMAX+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMAX value!', LOCATION ) + ENDIF + + ! Compute latitude limits to write to disk (bey, bmy, 3/16/99) + IF ( ND51_JMAX >= ND51_JMIN ) THEN + ND51_NJ = ( ND51_JMAX - ND51_JMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_JMAX < ND51_JMIN!', LOCATION ) + ENDIF + + !----------- + ! Altitude + !----------- + + ! Error check ND51_LMIN, ND51_LMAX + IF ( ND51_LMIN < 1 .or. ND51_LMAX > LLPAR ) THEN + CALL ERROR_STOP( 'Bad ND51 altitude values!', LOCATION ) + ENDIF + + ! # of levels to save in ND51 timeseries + IF ( ND51_LMAX >= ND51_LMIN ) THEN + ND51_NL = ( ND51_LMAX - ND51_LMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_LMAX < ND51_LMIN!', LOCATION ) + ENDIF + + !----------- + ! Offsets + !----------- + IOFF = ND51_IMIN - 1 + JOFF = ND51_JMIN - 1 + LOFF = ND51_LMIN - 1 + + !----------- + ! For bpch + !----------- + TAU0 = GET_TAUb() + TITLE = 'GEOS-CHEM DIAG51 time series' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Reset offsets to global values for bpch write + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + !================================================================= + ! Allocate arrays + !================================================================= + + ! Array denoting where LT is between HR1 and HR2 + ALLOCATE( GOOD( IIPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD' ) + GOOD = 0 + + ! Counter of "good" times per day at each grid box + ALLOCATE( GOOD_CT( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT' ) + GOOD_CT = 0 + + ! Counter of "good" times per day for each chemistry timestep + ALLOCATE( GOOD_CT_CHEM( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT_CHEM' ) + GOOD_CT_CHEM = 0 + + ! Accumulating array + ALLOCATE( Q( ND51_NI, ND51_NJ, ND51_NL, ND51_N_TRACERS), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'Q' ) + Q = 0d0 + + ! Accumulating array + ALLOCATE( COUNT_CHEM3D( ND51_NI, ND51_NJ, ND51_NL ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'COUNT_CHEM3D' ) + COUNT_CHEM3D = 0 + + ! Return to calling program + END SUBROUTINE INIT_DIAG51 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG51 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG51 deallocates all module arrays. +! (bmy, 11/29/00, 1/24/07) +! +! NOTES: +! (1 ) Now deallocate GOOD_CT_CHEM (bmy, 10/25/04) +! (2 ) Also deallocate COUNT_CHEM3D (phs, 1/24/07) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG51 begins here! + !================================================================= + IF ( ALLOCATED( COUNT_CHEM3D ) ) DEALLOCATE( COUNT_CHEM3D ) + IF ( ALLOCATED( GOOD ) ) DEALLOCATE( GOOD ) + IF ( ALLOCATED( GOOD_CT ) ) DEALLOCATE( GOOD_CT ) + IF ( ALLOCATED( GOOD_CT_CHEM ) ) DEALLOCATE( GOOD_CT_CHEM ) + IF ( ALLOCATED( Q ) ) DEALLOCATE( Q ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG51 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG51_MOD diff --git a/code/diag51b_mod.f b/code/diag51b_mod.f new file mode 100644 index 0000000..7f5172d --- /dev/null +++ b/code/diag51b_mod.f @@ -0,0 +1,1594 @@ +! $Id: diag51_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE DIAG51b_MOD +! +!****************************************************************************** +! Module DIAG51_MOD contains variables and routines to generate save +! timeseries data where the local time is between two user-defined limits. +! This facilitates comparisons with morning or afternoon-passing satellites +! such as GOME. (amf, bey, bdf, pip, bmy, 11/30/00, 12/10/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_DIAG51b (LOGICAL ) : Flag to turn on DIAG51 timseries +! (2 ) GOOD (INTEGER ) : Array denoting grid boxes w/in LT limits +! (3 ) GOOD_CT (INTEGER ) : # of "good" times per grid box +! (4 ) GOOD_CT_CHEM (INTEGER ) : # of "good" chemistry timesteps +! (5 ) COUNT_CHEM3D (INTEGER ) : Counter for 3D chemistry boxes +! (6 ) ND51_HR_WRITE (INTEGER ) : Hour at which to save to disk +! (7 ) I0 (INTEGER ) : Offset between global & nested grid +! (8 ) J0 (INTEGER ) : Offset between global & nested grid +! (9 ) IOFF (INTEGER ) : Longitude offset +! (10) JOFF (INTEGER ) : Latitude offset +! (11) LOFF (INTEGER ) : Altitude offset +! (12) ND51_HR1 (REAL*8 ) : Starting hour of user-defined LT interval +! (13) ND51_HR2 (REAL*8 ) : Ending hour of user-defined LT interval +! (14) ND51_IMIN (INTEGER ) : Minimum latitude index for DIAG51 region +! (15) ND51_IMAX (INTEGER ) : Maximum latitude index for DIAG51 region +! (16) ND51_JMIN (INTEGER ) : Minimum longitude index for DIAG51 region +! (17) ND51_JMAX (INTEGER ) : Maximum longitude index for DIAG51 region +! (18) ND51_LMIN (INTEGER ) : Minimum altitude index for DIAG51 region +! (19) ND51_LMAX (INTEGER ) : Minimum latitude index for DIAG51 region +! (20) ND51_NI (INTEGER ) : Number of longitudes in DIAG51 region +! (21) ND51_NJ (INTEGER ) : Number of latitudes in DIAG51 region +! (22) ND51_NL (INTEGER ) : Number of levels in DIAG51 region +! (23) ND51_N_TRACERS (INTEGER ) : Number of tracers for DIAG51 +! (24) ND51_OUTPUT_FILE (CHAR*255) : Name of bpch file w timeseries data +! (25) ND51_TRACERS (INTEGER ) : Array of DIAG51 tracer numbers +! (26) Q (REAL*8 ) : Accumulator array for various quantities +! (27) TAU0 (REAL*8 ) : Starting TAU used to index the bpch file +! (28) TAU1 (REAL*8 ) : Ending TAU used to index the bpch file +! (29) HALFPOLAR (INTEGER ) : Used for bpch file output +! (30) CENTER180 (INTEGER ) : Used for bpch file output +! (31) LONRES (REAL*4 ) : Used for bpch file output +! (32) LATRES (REAL*4 ) : Used for bpch file output +! (33) MODELNAME (CHAR*20 ) : Used for bpch file output +! (34) RESERVED (CHAR*40 ) : Used for bpch file output +! +! Module Procedures: +! ============================================================================ +! (1 ) DIAG51b : Driver subroutine for US grid timeseries +! (2 ) GET_LOCAL_TIME : Computes the local times at each grid box +! (3 ) WRITE_DIAG51 : Writes timeseries data to a bpch file +! (4 ) ITS_TIME_FOR_WRITE_DIAG51 : Returns T if it's time to save to disk +! (5 ) ACCUMULATE_DIAG51 : Accumulates data over for later averaging +! (6 ) INIT_DIAG51 : Allocates and zeroes all module arrays +! (7 ) CLEANUP_DIAG51b : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag51_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) error_mod.f : Module w/ NaN and other error check routines +! (4 ) file_mod.f : Module w/ file unit numbers and error checks +! (5 ) grid_mod.f : Module w/ horizontal grid information +! (6 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (7 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (8 ) time_mod.f : Module w/ routines to compute date & time +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND51 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D Cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box heights [m ] +! 94 : Relative Humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added extra counters for NO, NO2, OH, O3. Also all diagnostic counter +! arrays are 1-D since they only depend on longitude. (bmy, 10/25/04) +! (3 ) Bug fix: Now get I0 and J0 properly for nested grids (bmy, 11/9/04) +! (4 ) Now only archive AOD's once per chemistry timestep (bmy, 1/14/05) +! (5 ) Now references "pbl_mix_mod.f" (bmy, 2/16/05) +! (6 ) Now save cld frac and grid box heights (bmy, 4/20/05) +! (7 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (8 ) Bug fix: do not save SLP if it's not allocated (bmy, 8/2/05) +! (9 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (10) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (11) Modified INIT_DIAG51 to save out transects (cdh, bmy, 11/30/06) +! (12) Now use 3D timestep counter for full chem in the trop (phs, 1/24/07) +! (13) Renumber RH in WRITE_DIAG50 (bmy, 2/11/08) +! (14) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +! (15) Bug fix in GET_LOCAL_TIME (ccc, 12/10/08) +! (16) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 9/26/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag51_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG51b + + ! ... and these routines + PUBLIC :: CLEANUP_DIAG51b + PUBLIC :: DIAG51b + PUBLIC :: INIT_DIAG51b + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_DIAG51b + INTEGER :: IOFF, JOFF, LOFF + INTEGER :: I0, J0 + INTEGER :: ND51_N_TRACERS, ND51_TRACERS(100) + INTEGER :: ND51_IMIN, ND51_IMAX + INTEGER :: ND51_JMIN, ND51_JMAX + INTEGER :: ND51_LMIN, ND51_LMAX + INTEGER :: ND51_FREQ, ND51_NI + INTEGER :: ND51_NJ, ND51_NL + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES, LATRES + REAL*8 :: TAU0, TAU1 + REAL*8 :: ND51_HR1, ND51_HR2 + REAL*8 :: ND51_HR_WRITE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = '' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND51_OUTPUT_FILE + + ! Arrays + INTEGER, ALLOCATABLE :: GOOD(:) + INTEGER, ALLOCATABLE :: GOOD_CT(:) + INTEGER, ALLOCATABLE :: GOOD_CT_CHEM(:) + INTEGER, ALLOCATABLE :: COUNT_CHEM3D(:,:,:) + REAL*8, ALLOCATABLE :: Q(:,:,:,:) + + !================================================================= + ! Original code from old DIAG51_MOD. Leave here as a guide to + ! figure out when the averaging periods should be and when to + ! write to disk (bmy, 9/28/04) + ! + !! For timeseries between 1300 and 1700 LT, uncomment this code: + !! + !! Need to write to the bpch file at 12 GMT, since this covers + !! an entire day over the US grid (amf, bmy, 12/1/00) + !! + !INTEGER, PARAMETER :: NHMS_WRITE = 120000 + !REAL*8, PARAMETER :: HR1 = 13d0 + !REAL*8, PARAMETER :: HR2 = 17d0 + !CHARACTER(LEN=255) :: FILENAME = 'ts1_4pm.bpch' + !================================================================= + ! For timeseries between 1000 and 1200 LT, uncomment this code: + ! + ! Between 10 and 12 has been chosen because the off-polar orbit + ! of GOME traverses (westward) through local times between 12 + ! and 10 over North America, finally crossing the equator at + ! 10.30 (local time). + ! + ! Need to write to the bpch file at 00 GMT, since we will be + ! interested in the whole northern hemisphere (pip, 12/1/00) + ! + !INTEGER, PARAMETER :: NHMS_WRITE = 000000 + !REAL*8, PARAMETER :: HR1 = 10d0 + !REAL*8, PARAMETER :: HR2 = 12d0 + !CHARACTER(LEN=255) :: FILENAME ='ts10_12pm.bpch' + !================================================================= + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG51b +! +!****************************************************************************** +! Subroutine DIAG51 generates time series (averages from 10am - 12pm LT +! or 1pm - 4pm LT) for the US grid area. Output is to binary punch files. +! (amf, bey, bdf, pip, bmy, 11/15/99, 9/28/04) +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added TAU_W as a local variable (bmy, 9/28/04) +!****************************************************************************** +! + ! Local variables + REAL*8 :: TAU_W + + !================================================================= + ! DIAG51 begins here! + !================================================================= + + ! Construct array of where local times are between HR1, HR2 + CALL GET_LOCAL_TIME + + ! Accumulate data in the Q array + CALL ACCUMULATE_DIAG51 + + ! Write data to disk at the proper time + IF ( ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) ) THEN + CALL WRITE_DIAG51( TAU_W ) + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG51b + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_LOCAL_TIME +! +!****************************************************************************** +! Subroutine GET_LOCAL_TIME computes the local time and returns an array +! of points where the local time is between two user-defined limits. +! (bmy, 11/29/00, 12/10/08) +! +! NOTES: +! (1 ) The 1d-3 in the computation of XLOCTM is to remove roundoff ambiguity +! if a the local time should fall exactly on an hour boundary. +! (bmy, 11/29/00) +! (2 ) Bug fix: XMID(I) should be XMID(II). Also updated comments. +! (bmy, 7/6/01) +! (3 ) Updated comments (rvm, bmy, 2/27/02) +! (4 ) Now uses function GET_LOCALTIME of "time_mod.f" (bmy, 3/27/03) +! (5 ) Removed reference to CMN (bmy, 7/20/04) +! (6 ) Bug fix: LT should be REAL*8 and not INTEGER (ccarouge, 12/10/08) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_LOCALTIME + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + !------------------------------------------ + ! Prior to 12/10/08: + ! LT should be REAL*8 (ccarouge, 12/10/08) + !INTEGER :: I, LT + !------------------------------------------ + INTEGER :: I + REAL*8 :: LT + + !================================================================= + ! GET_LOCAL_TIME begins here! + !================================================================= + DO I = 1, IIPAR + + ! Get local time + LT = GET_LOCALTIME(I) + + ! GOOD indicates which boxes have local times between HR1 and HR2 + IF ( LT >= ND51_HR1 .and. LT <= ND51_HR2 ) THEN + GOOD(I) = 1 + ELSE + GOOD(I) = 0 + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE GET_LOCAL_TIME + +!------------------------------------------------------------------------------ + + SUBROUTINE ACCUMULATE_DIAG51 +! +!****************************************************************************** +! Subroutine ACCUMULATE_DIAG51 accumulates tracers into the Q array. +! (bmy, 8/20/02, 1/24/07) +! +! NOTES: +! (1 ) Rewrote to remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. Now scale optical depths +! to 400 nm (which is usually what QAA(2,*) is. (bmy, 7/20/04) +! (2 ) Now reference GET_ELAPSED_MIN and GET_TS_CHEM from "time_mod.f". +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). (bmy, 10/25/04) +! (3 ) Only archive AOD's when it is a chem timestep (bmy, 1/14/05) +! (4 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (5 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D cloud +! fraction as tracer #79 and box height as tracer #93. Now remove +! references to CLMOSW, CLROSW, and PBL from "dao_mod.f". (bmy, 4/20/05) +! (6 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (7 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (8 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (9 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (10) Now account for time spent in the trop for non-tracers (phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, T + USE DAO_MOD, ONLY : UWND, VWND, SLP + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : GET_ELAPSED_MIN, GET_TS_CHEM + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : STT, TCVV, ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : N_TRACERS, XNUMOLAIR + USE TRACERID_MOD, ONLY : IDTHNO3, IDTHNO4, IDTN2O5, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + +# include "cmn_fj.h" ! includes CMN_SIZE +# include "jv_cmn.h" ! ODAER +# include "CMN_O3" ! FRACO3, FRACNO, SAVEO3, SAVENO2, SAVEHO2, FRACNO2 +# include "CMN_GCTM" ! SCALE_HEIGHT + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: IS_FULLCHEM, IS_NOx, IS_Ox, IS_SEASALT + LOGICAL, SAVE :: IS_CLDTOPS, IS_NOy, IS_OPTD, IS_SLP + LOGICAL :: IS_CHEM + INTEGER :: H, I, J, K, L, M, N + INTEGER :: PBLINT, R, X, Y, W, XMIN + REAL*8 :: C1, C2, PBLDEC, TEMPBL, TMP, SCALEAODnm + CHARACTER(LEN=16) :: STAMP + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + + !================================================================= + ! ACCUMULATE_DIAG51 begins here! + !================================================================= + + ! Set logical flags on first call + IF ( FIRST ) THEN + IS_OPTD = ALLOCATED( OPTD ) + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOx > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + FIRST = .FALSE. + ENDIF + + ! Is it a chemistry timestep? + IS_CHEM = ( MOD( GET_ELAPSED_MIN(), GET_TS_CHEM() ) == 0 ) + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 100 ) STAMP + 100 FORMAT( ' - DIAG51b: Accumulation at ', a ) + + !================================================================= + ! Archive tracers into accumulating array Q + !================================================================= + + ! Archive counter array of good points + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT(X) = GOOD_CT(X) + GOOD(I) + ENDDO + + ! Archive counter array of good points for chemistry timesteps only + IF ( IS_CHEM ) THEN + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT_CHEM(X) = GOOD_CT_CHEM(X) + GOOD(I) + ENDDO + ENDIF + + + ! Also increment 3-D counter for boxes in the tropopause + IF ( IS_FULLCHEM .and. IS_CHEM ) THEN + + ! Loop over levels +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, I, J, L ) +!$OMP+SCHEDULE( DYNAMIC ) + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Only increment if we are in the trop + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + COUNT_CHEM3D(X,Y,K) = COUNT_CHEM3D(X,Y,K) + GOOD(I) + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !------------------------ + ! Accumulate quantities + !------------------------ +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( W, N, X, Y, K, I, J, L, TMP, H, R, SCALEAODnm ) +!$OMP+SCHEDULE( DYNAMIC ) + DO W = 1, ND51_N_TRACERS + + ! ND51 Tracer number + N = ND51_TRACERS(W) + + ! Loop over levels + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Archive by simulation + IF ( N <= N_TRACERS ) THEN + + !-------------------------------------- + ! GEOS-CHEM tracers [v/v] + !-------------------------------------- + + ! Archive afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,N) * TCVV(N) / + & AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 89 .and. IS_Ox .and. IS_CHEM ) THEN + + !-------------------------------------- + ! Pure O3 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTOX) * FRACO3(I,J,L) * + & TCVV(IDTOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 90 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !-------------------------------------- + ! NOy [v/v] + !-------------------------------------- + + ! Temp variable for accumulation + TMP = 0d0 + + ! NOx + TMP = TMP + ( TCVV(IDTNOX) * GOOD(I) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + ! PAN + TMP = TMP + ( TCVV(IDTPAN) * GOOD(I) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + TMP = TMP + ( TCVV(IDTHNO3) * GOOD(I) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + TMP = TMP + ( TCVV(IDTPMN) * GOOD(I) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + TMP = TMP + ( TCVV(IDTPPN) * GOOD(I) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + TMP = TMP + ( TCVV(IDTR4N2) * GOOD(I) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + TMP = TMP + ( 2d0 * TCVV(IDTN2O5) * GOOD(I) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + TMP = TMP + ( TCVV(IDTHNO4) * GOOD(I) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + + ! Save afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + TMP + + ELSE IF ( N == 74 .and. IS_FULLCHEM .and. IS_CHEM ) THEN + + !-------------------------------------- + ! OH [molec/cm3] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SAVEOH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 75 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO2 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO2(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 76 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [m] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_m( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 77 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [layers] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_L( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 78 ) THEN + + !-------------------------------------- + ! AIR DENSITY [molec/cm3] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 * GOOD(I) ) + + ELSE IF ( N == 79 ) THEN + + !-------------------------------------- + ! 3-D CLOUD FRACTION [unitless] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( CLDF(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !-------------------------------------- + ! COLUMN OPTICAL DEPTH [unitless] + !-------------------------------------- + Q(X,Y,1,W) = Q(X,Y,1,W) + ( OPTD(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !-------------------------------------- + ! CLOUD TOP HEIGHTS [mb] + !-------------------------------------- + IF ( K == 1 ) THEN + TMP = GET_PEDGE( I, J, CLDTOPS(I,J) ) + Q(X,Y,K,W) = Q(X,Y,K,W) + ( TMP * GOOD(I) ) + ENDIF + + ELSE IF ( N == 82 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO H = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+H-1) / QAA(4,IND(1)+H-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 83 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 84 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ORG CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 2*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 85 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 3*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 86 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! COARSE SEASALT AOD 400 nm [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 4*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 87 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! TOTAL DUST OPTD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODMDUST(I,J,L,R) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !----------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTSALA) + + & STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) * GOOD(I) + + ELSE IF ( N == 93 ) THEN + + !----------------------------------- + ! GRID BOX HEIGHTS [m] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( BXHEIGHT(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 94 ) THEN + + !----------------------------------- + ! RELATIVE HUMIDITY [%] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( RH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !----------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !----------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SLP(I,J) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 96 ) THEN + + !----------------------------------- + ! ZONAL (U) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( UWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 97 ) THEN + + !----------------------------------- + ! MERIDIONAL (V) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( VWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 98 ) THEN + + !----------------------------------- + ! PEDGE-$ (prs @ level edges) [hPa] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( GET_PEDGE(I,J,K) * GOOD(I) ) + + ELSE IF ( N == 99 ) THEN + + !----------------------------------- + ! TEMPERATURE [K] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( T(I,J,L) * GOOD(I) ) + + ENDIF + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE ACCUMULATE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_WRITE_DIAG51 returns TRUE if it's time to write +! the ND51 bpch file to disk. We test the time at the next dynamic +! timestep so that we can write to disk properly. (bmy, 7/20/04, 9/28/04) +! +! Arguments as Output: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Added TAU_W so to make sure the timestamp is accurate. (bmy, 9/28/04) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE, GET_TAU, + & GET_TAUb, GET_TAUe, GET_TS_DYN + + ! Arguments + REAL*8, INTENT(OUT) :: TAU_W + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: TAU, HOUR, DYN + + !================================================================= + ! ITS_TIME_FOR_WRITE_DIAG51 begins here! + !================================================================= + + ! Initialize + ITS_TIME = .FALSE. + + ! Current TAU, Hour, and Dynamic Timestep [hrs] + TAU = GET_TAU() + HOUR = ( GET_MINUTE() / 60d0 ) + GET_HOUR() + DYN = ( GET_TS_DYN() / 60d0 ) + + ! If first timestep, return FALSE + IF ( TAU == GET_TAUb() ) RETURN + + ! If the next dyn timestep is the hour of day + ! when we have to save to disk, return TRUE + IF ( MOD( HOUR+DYN, 24d0 ) == ND51_HR_WRITE ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! If the next dyn timestep is the + ! end of the run, return TRUE + IF ( TAU + DYN == GET_TAUe() ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG51( TAU_W ) +! +!****************************************************************************** +! Subroutine WRITE_DIAG51 computes the time-average of quantities between +! local time limits ND51_HR1 and ND51_HR2 and writes them to a bpch file. +! Arrays and counters are also zeroed for the next diagnostic interval. +! (bmy, 12/1/00, 10/7/08) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Rewrote to` remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. (bmy, 7/20/04) +! (2 ) Added TAU_W to the arg list. Now use TAU_W to set TAU0 and TAU0. +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). Also remove reference +! to FIRST. (bmy, 10/25/04) +! (3 ) Now divide tracers 82-87 (i.e. various AOD's) by GOOD_CT_CHEM since +! these are only updated once per chemistry timestep (bmy, 1/14/05) +! (4 ) Now save grid box heights as tracer #93. Now save 3-D cloud fraction +! as tracer #79 (bmy, 4/20/05) +! (5 ) Remove references to TRCOFFSET because it's always zero (bmy, 6/24/05) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) DIVISOR is now a 3-D array. Now zero COUNT_CHEM3D. Now use CASE +! statement instead of IF statements. Now zero counter arrays with +! array broadcast assignments. (phs, 1/24/07) +! (8 ) RH should be tracer #17 under "TIME-SER" category (bmy, 2/11/08) +! (9 ) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +!****************************************************************************** +! + ! Reference to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, OPEN_BPCH2_FOR_WRITE + USE ERROR_MOD, ONLY : ALLOC_ERR + USE FILE_MOD, ONLY : IU_ND51 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_NYMD + USE TIME_MOD, ONLY : GET_NHMS, GET_TAU + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size Parameters + + ! Arguments + REAL*8, INTENT(IN) :: TAU_W + + ! Local variables + INTEGER :: I, J, L, W, N, GMNL, GMTRC + INTEGER :: IOS, X, Y, K + CHARACTER(LEN=16) :: STAMP + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! WRITE_DIAG51 begins here! + !================================================================= + + ! Replace date tokens in FILENAME + FILENAME = ND51_OUTPUT_FILE + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - DIAG51b: Opening file ', a ) + + ! Open output file + CALL OPEN_BPCH2_FOR_WRITE( IU_ND51, FILENAME, TITLE ) + + ! Set ENDING TAU for this bpch write + TAU1 = TAU_W + + !================================================================= + ! Compute time-average of tracers between local time limits + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 110 ) STAMP + 110 FORMAT( ' - DIAG51b: Saving to disk at ', a ) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, W ) + + DO W = 1, ND51_N_TRACERS + + ! Loop over grid boxes + DO K = 1, ND51_NL + DO Y = 1, ND51_NJ + DO X = 1, ND51_NI + + SELECT CASE( ND51_TRACERS(W) ) + + CASE( 89, 90, 74, 75 ) + !-------------------------------------------------------- + ! Avoid div by zero for tracers which are archived each + ! chem timestep and only available in the troposphere + !-------------------------------------------------------- + IF ( COUNT_CHEM3D(X,Y,K) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / COUNT_CHEM3D(X,Y,K) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE( 82:87 ) + + !-------------------------------------------------------- + ! Avoid division by zero for tracers which are archived + ! on each chem timestep (at trop & strat levels) + !-------------------------------------------------------- + IF ( GOOD_CT_CHEM(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT_CHEM(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE DEFAULT + + !-------------------------------------------------------- + ! Avoid division by zero for all other tracers + !-------------------------------------------------------- + IF ( GOOD_CT(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + END SELECT + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !================================================================= + ! Write each tracer from "timeseries.dat" to the timeseries file + !================================================================= + DO W = 1, ND51_N_TRACERS + + ! ND51 tracer number + N = ND51_TRACERS(W) + + ! Save by simulation + IF ( N <= N_TRACERS ) THEN + + !--------------------- + ! GEOS-CHEM tracers + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N + + ELSE IF ( N == 89 ) THEN + + !--------------------- + ! Pure O3 + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N_TRACERS + 1 + + ELSE IF ( N == 90 ) THEN + !--------------------- + ! Pure NO [v/v] + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 91 ) THEN + !--------------------- + ! NOy + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 3 + + ELSE IF ( N == 74 ) THEN + + !--------------------- + ! OH + !--------------------- + CATEGORY = 'CHEM-L=$' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 75 ) THEN + + !--------------------- + ! NO2 + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 25 + + ELSE IF ( N == 76 ) THEN + + !--------------------- + ! PBL Height [m] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 77 ) THEN + + !--------------------- + ! PBL Height [levels] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMNL = 1 + GMTRC = 2 + + ELSE IF ( N == 78 ) THEN + + !--------------------- + ! Air Density + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 22 + + ELSE IF ( N == 79 ) THEN + + !--------------------- + ! 3-D Cloud fractions + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 19 + + ELSE IF ( N == 80 ) THEN + + !--------------------- + ! Column opt depths + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = 1 + GMTRC = 20 + + ELSE IF ( N == 81 ) THEN + + !--------------------- + ! Cloud top heights + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 82 ) THEN + + !--------------------- + ! Sulfate AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 6 + + ELSE IF ( N == 83 ) THEN + + !--------------------- + ! Black Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 84 ) THEN + + !--------------------- + ! Organic Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 12 + + ELSE IF ( N == 85 ) THEN + + !--------------------- + ! SS Accum AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 15 + + ELSE IF ( N == 86 ) THEN + + !--------------------- + ! SS Coarse AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 18 + + ELSE IF ( N == 87 ) THEN + + !--------------------- + ! Total dust OD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 4 + + ELSE IF ( N == 88 ) THEN + + !--------------------- + ! Total seasalt + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 24 + + ELSE IF ( N == 93 ) THEN + + !--------------------- + ! Grid box heights + !--------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 94 ) THEN + + !--------------------- + ! Relative humidity + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMNL = ND51_NL + GMTRC = 17 + + ELSE IF ( N == 95 ) THEN + + !--------------------- + ! Sea level prs + !--------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 96 ) THEN + + !--------------------- + ! U-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 97 ) THEN + + !--------------------- + ! V-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 2 + + ELSE IF ( N == 98 ) THEN + + !--------------------- + ! Psurface - PTOP + !--------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 99 ) THEN + + !--------------------- + ! Temperature + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'K' + GMNL = ND51_NL + GMTRC = 3 + + ELSE + + ! Otherwise skip + CYCLE + + ENDIF + + !------------------------ + ! Save to bpch file + !------------------------ + CALL BPCH2( IU_ND51, MODELNAME, LONRES, + & LATRES, HALFPOLAR, CENTER180, + & CATEGORY, GMTRC, UNIT, + & TAU0, TAU1, RESERVED, + & ND51_NI, ND51_NJ, GMNL, + & ND51_IMIN+I0, ND51_JMIN+J0, ND51_LMIN, + & REAL( Q(1:ND51_NI, 1:ND51_NJ, 1:GMNL, W) ) ) + ENDDO + + ! Echo info + WRITE( 6, 120 ) TRIM( FILENAME ) + 120 FORMAT( ' - DIAG51b: Closing file ', a ) + + ! Close file + CLOSE( IU_ND51 ) + + !================================================================= + ! Re-initialize quantities for next diagnostic cycle + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 130 ) STAMP + 130 FORMAT( ' - DIAG51b: Zeroing arrays at ', a ) + + ! Set STARTING TAU for the next bpch write + TAU0 = TAU_W + + ! Zero accumulating array for tracer + Q = 0d0 + + ! Zero counter arrays + COUNT_CHEM3D = 0d0 + GOOD_CT = 0d0 + GOOD_CT_CHEM = 0d0 + + ! Return to calling program + END SUBROUTINE WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION GET_I( X ) RESULT( I ) +! +!****************************************************************************** +! Function GET_I returns the absolute longitude index (I), given the +! relative longitude index (X). (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (INTEGER) : Relative longitude index (used by Q) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: X + + ! Local variables + INTEGER :: I + + !================================================================= + ! GET_I begins here! + !================================================================= + + ! Add the offset to X to get I + I = IOFF + X + + ! Handle wrapping around the date line, if necessary + IF ( I > IIPAR ) I = I - IIPAR + + ! Return to calling program + END FUNCTION GET_I + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG51b( DO_ND51, N_ND51, TRACERS, HR_WRITE, + & HR1, HR2, IMIN, IMAX, + & JMIN, JMAX, LMIN, LMAX, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG51 allocates and zeroes all module arrays. +! It also gets values for module variables from "input_mod.f". +! (bmy, 7/20/04, 1/22/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND51 (LOGICAL ) : Switch to turn on ND51 timeseries diagnostic +! (2 ) N_ND51 (INTEGER ) : Number of ND51 read by "input_mod.f" +! (3 ) TRACERS (INTEGER ) : Array w/ ND51 tracer #'s read by "input_mod.f" +! (4 ) HR_WRITE (REAL*8 ) : GMT hour of day at which to write bpch file +! (5 ) HR1 (REAL*8 ) : Lower limit of local time averaging bin +! (6 ) HR2 (REAL*8 ) : Upper limit of local time averaging bin +! (7 ) IMIN (INTEGER ) : Min longitude index read by "input_mod.f" +! (8 ) IMAX (INTEGER ) : Max longitude index read by "input_mod.f" +! (9 ) JMIN (INTEGER ) : Min latitude index read by "input_mod.f" +! (10) JMAX (INTEGER ) : Min latitude index read by "input_mod.f" +! (11) LMIN (INTEGER ) : Min level index read by "input_mod.f" +! (12) LMAX (INTEGER ) : Min level index read by "input_mod.f" +! (13) FILE (CHAR*255) : ND51 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Diagnostic counter arrays are now only 1-D. Also add GOOD_CT_CHEM +! which is the counter array of "good" boxes at each chemistry +! timesteps. Now allocate GOOD_CT_CHEM. (bmy, 10/25/04) +! (2 ) Now get I0 and J0 correctly for nested grid simulations (bmy, 11/9/04) +! (3 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (4 ) Now allow ND51_IMIN to be equal to ND51_IMAX and ND51_JMIN to be +! equal to ND51_JMAX. This will allow us to save out longitude or +! latitude transects. Allocate COUNT_CHEM3D. (cdh, bmy, phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, ITS_A_NESTED_GRID + USE TIME_MOD, ONLY : GET_TAUb + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND51 + INTEGER, INTENT(IN) :: N_ND51, TRACERS(100) + INTEGER, INTENT(IN) :: IMIN, IMAX + INTEGER, INTENT(IN) :: JMIN, JMAX + INTEGER, INTENT(IN) :: LMIN, LMAX + REAL*8, INTENT(IN) :: HR1, HR2 + REAL*8, INTENT(IN) :: HR_WRITE + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + INTEGER :: AS + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG51 begins here! + !================================================================= + + ! Initialize + LOCATION = 'INIT_DIAG51b ("diag51_mod.f")' + ND51_TRACERS(:) = 0 + + ! Get values from "input_mod.f" + DO_SAVE_DIAG51b = DO_ND51 + ND51_N_TRACERS = N_ND51 + ND51_TRACERS(1:N_ND51) = TRACERS(1:N_ND51) + ND51_HR_WRITE = HR_WRITE + ND51_HR1 = HR1 + ND51_HR2 = HR2 + ND51_IMIN = IMIN + ND51_IMAX = IMAX + ND51_JMIN = JMIN + ND51_JMAX = JMAX + ND51_LMIN = LMIN + ND51_LMAX = LMAX + ND51_OUTPUT_FILE = TRIM( FILE ) + + ! Make sure ND51_HR_WRITE is in the range 0-23.999 hrs + ND51_HR_WRITE = MOD( ND51_HR_WRITE, 24d0 ) + + ! Exit if ND51 is turned off + IF ( .not. DO_SAVE_DIAG51b ) RETURN + + !================================================================= + ! Error check longitude, latitude, altitude limits + !================================================================= + + ! Get grid offsets + IF ( ITS_A_NESTED_GRID() ) THEN + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + ELSE + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + ENDIF + + !----------- + ! Longitude + !----------- + + ! Error check ND51_IMIN + IF ( ND51_IMIN+I0 < 1 .or. ND51_IMIN+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMIN value!', LOCATION ) + ENDIF + + ! Error check ND51_IMAX + IF ( ND51_IMAX+I0 < 1 .or. ND51_IMAX+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMAX value!', LOCATION ) + ENDIF + + ! Compute longitude limits to write to disk + ! Also handle wrapping around the date line + IF ( ND51_IMAX >= ND51_IMIN ) THEN + ND51_NI = ( ND51_IMAX - ND51_IMIN ) + 1 + ELSE + ND51_NI = ( IIPAR - ND51_IMIN ) + 1 + ND51_IMAX + WRITE( 6, '(a)' ) 'We are wrapping over the date line!' + ENDIF + + ! Make sure that ND50_NI <= IIPAR + IF ( ND51_NI > IIPAR ) THEN + CALL ERROR_STOP( 'Too many longitudes!', LOCATION ) + ENDIF + + !----------- + ! Latitude + !----------- + + ! Error check JMIN_AREA + IF ( ND51_JMIN+J0 < 1 .or. ND51_JMIN+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMIN value!', LOCATION ) + ENDIF + + ! Error check JMAX_AREA + IF ( ND51_JMAX+J0 < 1 .or.ND51_JMAX+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMAX value!', LOCATION ) + ENDIF + + ! Compute latitude limits to write to disk (bey, bmy, 3/16/99) + IF ( ND51_JMAX >= ND51_JMIN ) THEN + ND51_NJ = ( ND51_JMAX - ND51_JMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_JMAX < ND51_JMIN!', LOCATION ) + ENDIF + + !----------- + ! Altitude + !----------- + + ! Error check ND51_LMIN, ND51_LMAX + IF ( ND51_LMIN < 1 .or. ND51_LMAX > LLPAR ) THEN + CALL ERROR_STOP( 'Bad ND51 altitude values!', LOCATION ) + ENDIF + + ! # of levels to save in ND51 timeseries + IF ( ND51_LMAX >= ND51_LMIN ) THEN + ND51_NL = ( ND51_LMAX - ND51_LMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_LMAX < ND51_LMIN!', LOCATION ) + ENDIF + + !----------- + ! Offsets + !----------- + IOFF = ND51_IMIN - 1 + JOFF = ND51_JMIN - 1 + LOFF = ND51_LMIN - 1 + + !----------- + ! For bpch + !----------- + TAU0 = GET_TAUb() + TITLE = 'GEOS-CHEM DIAG51 time series' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Reset offsets to global values for bpch write + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + !================================================================= + ! Allocate arrays + !================================================================= + + ! Array denoting where LT is between HR1 and HR2 + ALLOCATE( GOOD( IIPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD' ) + GOOD = 0 + + ! Counter of "good" times per day at each grid box + ALLOCATE( GOOD_CT( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT' ) + GOOD_CT = 0 + + ! Counter of "good" times per day for each chemistry timestep + ALLOCATE( GOOD_CT_CHEM( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT_CHEM' ) + GOOD_CT_CHEM = 0 + + ! Accumulating array + ALLOCATE( Q( ND51_NI, ND51_NJ, ND51_NL, ND51_N_TRACERS), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'Q' ) + Q = 0d0 + + ! Accumulating array + ALLOCATE( COUNT_CHEM3D( ND51_NI, ND51_NJ, ND51_NL ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'COUNT_CHEM3D' ) + COUNT_CHEM3D = 0 + + ! Return to calling program + END SUBROUTINE INIT_DIAG51b + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG51b +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG51 deallocates all module arrays. +! (bmy, 11/29/00, 1/24/07) +! +! NOTES: +! (1 ) Now deallocate GOOD_CT_CHEM (bmy, 10/25/04) +! (2 ) Also deallocate COUNT_CHEM3D (phs, 1/24/07) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG51 begins here! + !================================================================= + IF ( ALLOCATED( COUNT_CHEM3D ) ) DEALLOCATE( COUNT_CHEM3D ) + IF ( ALLOCATED( GOOD ) ) DEALLOCATE( GOOD ) + IF ( ALLOCATED( GOOD_CT ) ) DEALLOCATE( GOOD_CT ) + IF ( ALLOCATED( GOOD_CT_CHEM ) ) DEALLOCATE( GOOD_CT_CHEM ) + IF ( ALLOCATED( Q ) ) DEALLOCATE( Q ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG51b + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG51b_MOD diff --git a/code/diag51c_mod.f b/code/diag51c_mod.f new file mode 100644 index 0000000..49674a9 --- /dev/null +++ b/code/diag51c_mod.f @@ -0,0 +1,1594 @@ +! $Id: diag51_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE DIAG51c_MOD +! +!****************************************************************************** +! Module DIAG51_MOD contains variables and routines to generate save +! timeseries data where the local time is between two user-defined limits. +! This facilitates comparisons with morning or afternoon-passing satellites +! such as GOME. (amf, bey, bdf, pip, bmy, 11/30/00, 12/10/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_DIAG51c (LOGICAL ) : Flag to turn on DIAG51 timseries +! (2 ) GOOD (INTEGER ) : Array denoting grid boxes w/in LT limits +! (3 ) GOOD_CT (INTEGER ) : # of "good" times per grid box +! (4 ) GOOD_CT_CHEM (INTEGER ) : # of "good" chemistry timesteps +! (5 ) COUNT_CHEM3D (INTEGER ) : Counter for 3D chemistry boxes +! (6 ) ND51_HR_WRITE (INTEGER ) : Hour at which to save to disk +! (7 ) I0 (INTEGER ) : Offset between global & nested grid +! (8 ) J0 (INTEGER ) : Offset between global & nested grid +! (9 ) IOFF (INTEGER ) : Longitude offset +! (10) JOFF (INTEGER ) : Latitude offset +! (11) LOFF (INTEGER ) : Altitude offset +! (12) ND51_HR1 (REAL*8 ) : Starting hour of user-defined LT interval +! (13) ND51_HR2 (REAL*8 ) : Ending hour of user-defined LT interval +! (14) ND51_IMIN (INTEGER ) : Minimum latitude index for DIAG51 region +! (15) ND51_IMAX (INTEGER ) : Maximum latitude index for DIAG51 region +! (16) ND51_JMIN (INTEGER ) : Minimum longitude index for DIAG51 region +! (17) ND51_JMAX (INTEGER ) : Maximum longitude index for DIAG51 region +! (18) ND51_LMIN (INTEGER ) : Minimum altitude index for DIAG51 region +! (19) ND51_LMAX (INTEGER ) : Minimum latitude index for DIAG51 region +! (20) ND51_NI (INTEGER ) : Number of longitudes in DIAG51 region +! (21) ND51_NJ (INTEGER ) : Number of latitudes in DIAG51 region +! (22) ND51_NL (INTEGER ) : Number of levels in DIAG51 region +! (23) ND51_N_TRACERS (INTEGER ) : Number of tracers for DIAG51 +! (24) ND51_OUTPUT_FILE (CHAR*255) : Name of bpch file w timeseries data +! (25) ND51_TRACERS (INTEGER ) : Array of DIAG51 tracer numbers +! (26) Q (REAL*8 ) : Accumulator array for various quantities +! (27) TAU0 (REAL*8 ) : Starting TAU used to index the bpch file +! (28) TAU1 (REAL*8 ) : Ending TAU used to index the bpch file +! (29) HALFPOLAR (INTEGER ) : Used for bpch file output +! (30) CENTER180 (INTEGER ) : Used for bpch file output +! (31) LONRES (REAL*4 ) : Used for bpch file output +! (32) LATRES (REAL*4 ) : Used for bpch file output +! (33) MODELNAME (CHAR*20 ) : Used for bpch file output +! (34) RESERVED (CHAR*40 ) : Used for bpch file output +! +! Module Procedures: +! ============================================================================ +! (1 ) DIAG51c : Driver subroutine for US grid timeseries +! (2 ) GET_LOCAL_TIME : Computes the local times at each grid box +! (3 ) WRITE_DIAG51 : Writes timeseries data to a bpch file +! (4 ) ITS_TIME_FOR_WRITE_DIAG51 : Returns T if it's time to save to disk +! (5 ) ACCUMULATE_DIAG51 : Accumulates data over for later averaging +! (6 ) INIT_DIAG51 : Allocates and zeroes all module arrays +! (7 ) CLEANUP_DIAG51c : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag51_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) error_mod.f : Module w/ NaN and other error check routines +! (4 ) file_mod.f : Module w/ file unit numbers and error checks +! (5 ) grid_mod.f : Module w/ horizontal grid information +! (6 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (7 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (8 ) time_mod.f : Module w/ routines to compute date & time +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND51 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D Cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box heights [m ] +! 94 : Relative Humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added extra counters for NO, NO2, OH, O3. Also all diagnostic counter +! arrays are 1-D since they only depend on longitude. (bmy, 10/25/04) +! (3 ) Bug fix: Now get I0 and J0 properly for nested grids (bmy, 11/9/04) +! (4 ) Now only archive AOD's once per chemistry timestep (bmy, 1/14/05) +! (5 ) Now references "pbl_mix_mod.f" (bmy, 2/16/05) +! (6 ) Now save cld frac and grid box heights (bmy, 4/20/05) +! (7 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (8 ) Bug fix: do not save SLP if it's not allocated (bmy, 8/2/05) +! (9 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (10) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (11) Modified INIT_DIAG51 to save out transects (cdh, bmy, 11/30/06) +! (12) Now use 3D timestep counter for full chem in the trop (phs, 1/24/07) +! (13) Renumber RH in WRITE_DIAG50 (bmy, 2/11/08) +! (14) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +! (15) Bug fix in GET_LOCAL_TIME (ccc, 12/10/08) +! (16) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 9/26/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag51_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG51c + + ! ... and these routines + PUBLIC :: CLEANUP_DIAG51c + PUBLIC :: DIAG51c + PUBLIC :: INIT_DIAG51c + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_DIAG51c + INTEGER :: IOFF, JOFF, LOFF + INTEGER :: I0, J0 + INTEGER :: ND51_N_TRACERS, ND51_TRACERS(100) + INTEGER :: ND51_IMIN, ND51_IMAX + INTEGER :: ND51_JMIN, ND51_JMAX + INTEGER :: ND51_LMIN, ND51_LMAX + INTEGER :: ND51_FREQ, ND51_NI + INTEGER :: ND51_NJ, ND51_NL + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES, LATRES + REAL*8 :: TAU0, TAU1 + REAL*8 :: ND51_HR1, ND51_HR2 + REAL*8 :: ND51_HR_WRITE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = '' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND51_OUTPUT_FILE + + ! Arrays + INTEGER, ALLOCATABLE :: GOOD(:) + INTEGER, ALLOCATABLE :: GOOD_CT(:) + INTEGER, ALLOCATABLE :: GOOD_CT_CHEM(:) + INTEGER, ALLOCATABLE :: COUNT_CHEM3D(:,:,:) + REAL*8, ALLOCATABLE :: Q(:,:,:,:) + + !================================================================= + ! Original code from old DIAG51_MOD. Leave here as a guide to + ! figure out when the averaging periods should be and when to + ! write to disk (bmy, 9/28/04) + ! + !! For timeseries between 1300 and 1700 LT, uncomment this code: + !! + !! Need to write to the bpch file at 12 GMT, since this covers + !! an entire day over the US grid (amf, bmy, 12/1/00) + !! + !INTEGER, PARAMETER :: NHMS_WRITE = 120000 + !REAL*8, PARAMETER :: HR1 = 13d0 + !REAL*8, PARAMETER :: HR2 = 17d0 + !CHARACTER(LEN=255) :: FILENAME = 'ts1_4pm.bpch' + !================================================================= + ! For timeseries between 1000 and 1200 LT, uncomment this code: + ! + ! Between 10 and 12 has been chosen because the off-polar orbit + ! of GOME traverses (westward) through local times between 12 + ! and 10 over North America, finally crossing the equator at + ! 10.30 (local time). + ! + ! Need to write to the bpch file at 00 GMT, since we will be + ! interested in the whole northern hemisphere (pip, 12/1/00) + ! + !INTEGER, PARAMETER :: NHMS_WRITE = 000000 + !REAL*8, PARAMETER :: HR1 = 10d0 + !REAL*8, PARAMETER :: HR2 = 12d0 + !CHARACTER(LEN=255) :: FILENAME ='ts10_12pm.bpch' + !================================================================= + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG51c +! +!****************************************************************************** +! Subroutine DIAG51 generates time series (averages from 10am - 12pm LT +! or 1pm - 4pm LT) for the US grid area. Output is to binary punch files. +! (amf, bey, bdf, pip, bmy, 11/15/99, 9/28/04) +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added TAU_W as a local variable (bmy, 9/28/04) +!****************************************************************************** +! + ! Local variables + REAL*8 :: TAU_W + + !================================================================= + ! DIAG51 begins here! + !================================================================= + + ! Construct array of where local times are between HR1, HR2 + CALL GET_LOCAL_TIME + + ! Accumulate data in the Q array + CALL ACCUMULATE_DIAG51 + + ! Write data to disk at the proper time + IF ( ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) ) THEN + CALL WRITE_DIAG51( TAU_W ) + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG51c + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_LOCAL_TIME +! +!****************************************************************************** +! Subroutine GET_LOCAL_TIME computes the local time and returns an array +! of points where the local time is between two user-defined limits. +! (bmy, 11/29/00, 12/10/08) +! +! NOTES: +! (1 ) The 1d-3 in the computation of XLOCTM is to remove roundoff ambiguity +! if a the local time should fall exactly on an hour boundary. +! (bmy, 11/29/00) +! (2 ) Bug fix: XMID(I) should be XMID(II). Also updated comments. +! (bmy, 7/6/01) +! (3 ) Updated comments (rvm, bmy, 2/27/02) +! (4 ) Now uses function GET_LOCALTIME of "time_mod.f" (bmy, 3/27/03) +! (5 ) Removed reference to CMN (bmy, 7/20/04) +! (6 ) Bug fix: LT should be REAL*8 and not INTEGER (ccarouge, 12/10/08) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_LOCALTIME + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + !------------------------------------------ + ! Prior to 12/10/08: + ! LT should be REAL*8 (ccarouge, 12/10/08) + !INTEGER :: I, LT + !------------------------------------------ + INTEGER :: I + REAL*8 :: LT + + !================================================================= + ! GET_LOCAL_TIME begins here! + !================================================================= + DO I = 1, IIPAR + + ! Get local time + LT = GET_LOCALTIME(I) + + ! GOOD indicates which boxes have local times between HR1 and HR2 + IF ( LT >= ND51_HR1 .and. LT <= ND51_HR2 ) THEN + GOOD(I) = 1 + ELSE + GOOD(I) = 0 + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE GET_LOCAL_TIME + +!------------------------------------------------------------------------------ + + SUBROUTINE ACCUMULATE_DIAG51 +! +!****************************************************************************** +! Subroutine ACCUMULATE_DIAG51 accumulates tracers into the Q array. +! (bmy, 8/20/02, 1/24/07) +! +! NOTES: +! (1 ) Rewrote to remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. Now scale optical depths +! to 400 nm (which is usually what QAA(2,*) is. (bmy, 7/20/04) +! (2 ) Now reference GET_ELAPSED_MIN and GET_TS_CHEM from "time_mod.f". +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). (bmy, 10/25/04) +! (3 ) Only archive AOD's when it is a chem timestep (bmy, 1/14/05) +! (4 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (5 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D cloud +! fraction as tracer #79 and box height as tracer #93. Now remove +! references to CLMOSW, CLROSW, and PBL from "dao_mod.f". (bmy, 4/20/05) +! (6 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (7 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (8 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (9 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (10) Now account for time spent in the trop for non-tracers (phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, T + USE DAO_MOD, ONLY : UWND, VWND, SLP + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : GET_ELAPSED_MIN, GET_TS_CHEM + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : STT, TCVV, ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : N_TRACERS, XNUMOLAIR + USE TRACERID_MOD, ONLY : IDTHNO3, IDTHNO4, IDTN2O5, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + +# include "cmn_fj.h" ! includes CMN_SIZE +# include "jv_cmn.h" ! ODAER +# include "CMN_O3" ! FRACO3, FRACNO, SAVEO3, SAVENO2, SAVEHO2, FRACNO2 +# include "CMN_GCTM" ! SCALE_HEIGHT + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: IS_FULLCHEM, IS_NOx, IS_Ox, IS_SEASALT + LOGICAL, SAVE :: IS_CLDTOPS, IS_NOy, IS_OPTD, IS_SLP + LOGICAL :: IS_CHEM + INTEGER :: H, I, J, K, L, M, N + INTEGER :: PBLINT, R, X, Y, W, XMIN + REAL*8 :: C1, C2, PBLDEC, TEMPBL, TMP, SCALEAODnm + CHARACTER(LEN=16) :: STAMP + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + + !================================================================= + ! ACCUMULATE_DIAG51 begins here! + !================================================================= + + ! Set logical flags on first call + IF ( FIRST ) THEN + IS_OPTD = ALLOCATED( OPTD ) + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOx > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + FIRST = .FALSE. + ENDIF + + ! Is it a chemistry timestep? + IS_CHEM = ( MOD( GET_ELAPSED_MIN(), GET_TS_CHEM() ) == 0 ) + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 100 ) STAMP + 100 FORMAT( ' - DIAG51c: Accumulation at ', a ) + + !================================================================= + ! Archive tracers into accumulating array Q + !================================================================= + + ! Archive counter array of good points + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT(X) = GOOD_CT(X) + GOOD(I) + ENDDO + + ! Archive counter array of good points for chemistry timesteps only + IF ( IS_CHEM ) THEN + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT_CHEM(X) = GOOD_CT_CHEM(X) + GOOD(I) + ENDDO + ENDIF + + + ! Also increment 3-D counter for boxes in the tropopause + IF ( IS_FULLCHEM .and. IS_CHEM ) THEN + + ! Loop over levels +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, I, J, L ) +!$OMP+SCHEDULE( DYNAMIC ) + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Only increment if we are in the trop + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + COUNT_CHEM3D(X,Y,K) = COUNT_CHEM3D(X,Y,K) + GOOD(I) + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !------------------------ + ! Accumulate quantities + !------------------------ +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( W, N, X, Y, K, I, J, L, TMP, H, R, SCALEAODnm ) +!$OMP+SCHEDULE( DYNAMIC ) + DO W = 1, ND51_N_TRACERS + + ! ND51 Tracer number + N = ND51_TRACERS(W) + + ! Loop over levels + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Archive by simulation + IF ( N <= N_TRACERS ) THEN + + !-------------------------------------- + ! GEOS-CHEM tracers [v/v] + !-------------------------------------- + + ! Archive afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,N) * TCVV(N) / + & AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 89 .and. IS_Ox .and. IS_CHEM ) THEN + + !-------------------------------------- + ! Pure O3 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTOX) * FRACO3(I,J,L) * + & TCVV(IDTOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 90 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !-------------------------------------- + ! NOy [v/v] + !-------------------------------------- + + ! Temp variable for accumulation + TMP = 0d0 + + ! NOx + TMP = TMP + ( TCVV(IDTNOX) * GOOD(I) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + ! PAN + TMP = TMP + ( TCVV(IDTPAN) * GOOD(I) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + TMP = TMP + ( TCVV(IDTHNO3) * GOOD(I) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + TMP = TMP + ( TCVV(IDTPMN) * GOOD(I) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + TMP = TMP + ( TCVV(IDTPPN) * GOOD(I) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + TMP = TMP + ( TCVV(IDTR4N2) * GOOD(I) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + TMP = TMP + ( 2d0 * TCVV(IDTN2O5) * GOOD(I) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + TMP = TMP + ( TCVV(IDTHNO4) * GOOD(I) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + + ! Save afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + TMP + + ELSE IF ( N == 74 .and. IS_FULLCHEM .and. IS_CHEM ) THEN + + !-------------------------------------- + ! OH [molec/cm3] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SAVEOH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 75 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO2 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO2(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 76 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [m] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_m( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 77 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [layers] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_L( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 78 ) THEN + + !-------------------------------------- + ! AIR DENSITY [molec/cm3] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 * GOOD(I) ) + + ELSE IF ( N == 79 ) THEN + + !-------------------------------------- + ! 3-D CLOUD FRACTION [unitless] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( CLDF(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !-------------------------------------- + ! COLUMN OPTICAL DEPTH [unitless] + !-------------------------------------- + Q(X,Y,1,W) = Q(X,Y,1,W) + ( OPTD(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !-------------------------------------- + ! CLOUD TOP HEIGHTS [mb] + !-------------------------------------- + IF ( K == 1 ) THEN + TMP = GET_PEDGE( I, J, CLDTOPS(I,J) ) + Q(X,Y,K,W) = Q(X,Y,K,W) + ( TMP * GOOD(I) ) + ENDIF + + ELSE IF ( N == 82 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO H = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+H-1) / QAA(4,IND(1)+H-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 83 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 84 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ORG CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 2*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 85 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 3*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 86 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! COARSE SEASALT AOD 400 nm [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 4*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 87 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! TOTAL DUST OPTD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODMDUST(I,J,L,R) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !----------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTSALA) + + & STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) * GOOD(I) + + ELSE IF ( N == 93 ) THEN + + !----------------------------------- + ! GRID BOX HEIGHTS [m] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( BXHEIGHT(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 94 ) THEN + + !----------------------------------- + ! RELATIVE HUMIDITY [%] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( RH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !----------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !----------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SLP(I,J) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 96 ) THEN + + !----------------------------------- + ! ZONAL (U) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( UWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 97 ) THEN + + !----------------------------------- + ! MERIDIONAL (V) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( VWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 98 ) THEN + + !----------------------------------- + ! PEDGE-$ (prs @ level edges) [hPa] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( GET_PEDGE(I,J,K) * GOOD(I) ) + + ELSE IF ( N == 99 ) THEN + + !----------------------------------- + ! TEMPERATURE [K] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( T(I,J,L) * GOOD(I) ) + + ENDIF + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE ACCUMULATE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_WRITE_DIAG51 returns TRUE if it's time to write +! the ND51 bpch file to disk. We test the time at the next dynamic +! timestep so that we can write to disk properly. (bmy, 7/20/04, 9/28/04) +! +! Arguments as Output: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Added TAU_W so to make sure the timestamp is accurate. (bmy, 9/28/04) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE, GET_TAU, + & GET_TAUb, GET_TAUe, GET_TS_DYN + + ! Arguments + REAL*8, INTENT(OUT) :: TAU_W + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: TAU, HOUR, DYN + + !================================================================= + ! ITS_TIME_FOR_WRITE_DIAG51 begins here! + !================================================================= + + ! Initialize + ITS_TIME = .FALSE. + + ! Current TAU, Hour, and Dynamic Timestep [hrs] + TAU = GET_TAU() + HOUR = ( GET_MINUTE() / 60d0 ) + GET_HOUR() + DYN = ( GET_TS_DYN() / 60d0 ) + + ! If first timestep, return FALSE + IF ( TAU == GET_TAUb() ) RETURN + + ! If the next dyn timestep is the hour of day + ! when we have to save to disk, return TRUE + IF ( MOD( HOUR+DYN, 24d0 ) == ND51_HR_WRITE ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! If the next dyn timestep is the + ! end of the run, return TRUE + IF ( TAU + DYN == GET_TAUe() ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG51( TAU_W ) +! +!****************************************************************************** +! Subroutine WRITE_DIAG51 computes the time-average of quantities between +! local time limits ND51_HR1 and ND51_HR2 and writes them to a bpch file. +! Arrays and counters are also zeroed for the next diagnostic interval. +! (bmy, 12/1/00, 10/7/08) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Rewrote to` remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. (bmy, 7/20/04) +! (2 ) Added TAU_W to the arg list. Now use TAU_W to set TAU0 and TAU0. +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). Also remove reference +! to FIRST. (bmy, 10/25/04) +! (3 ) Now divide tracers 82-87 (i.e. various AOD's) by GOOD_CT_CHEM since +! these are only updated once per chemistry timestep (bmy, 1/14/05) +! (4 ) Now save grid box heights as tracer #93. Now save 3-D cloud fraction +! as tracer #79 (bmy, 4/20/05) +! (5 ) Remove references to TRCOFFSET because it's always zero (bmy, 6/24/05) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) DIVISOR is now a 3-D array. Now zero COUNT_CHEM3D. Now use CASE +! statement instead of IF statements. Now zero counter arrays with +! array broadcast assignments. (phs, 1/24/07) +! (8 ) RH should be tracer #17 under "TIME-SER" category (bmy, 2/11/08) +! (9 ) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +!****************************************************************************** +! + ! Reference to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, OPEN_BPCH2_FOR_WRITE + USE ERROR_MOD, ONLY : ALLOC_ERR + USE FILE_MOD, ONLY : IU_ND51 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_NYMD + USE TIME_MOD, ONLY : GET_NHMS, GET_TAU + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size Parameters + + ! Arguments + REAL*8, INTENT(IN) :: TAU_W + + ! Local variables + INTEGER :: I, J, L, W, N, GMNL, GMTRC + INTEGER :: IOS, X, Y, K + CHARACTER(LEN=16) :: STAMP + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! WRITE_DIAG51 begins here! + !================================================================= + + ! Replace date tokens in FILENAME + FILENAME = ND51_OUTPUT_FILE + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - DIAG51c: Opening file ', a ) + + ! Open output file + CALL OPEN_BPCH2_FOR_WRITE( IU_ND51, FILENAME, TITLE ) + + ! Set ENDING TAU for this bpch write + TAU1 = TAU_W + + !================================================================= + ! Compute time-average of tracers between local time limits + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 110 ) STAMP + 110 FORMAT( ' - DIAG51c: Saving to disk at ', a ) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, W ) + + DO W = 1, ND51_N_TRACERS + + ! Loop over grid boxes + DO K = 1, ND51_NL + DO Y = 1, ND51_NJ + DO X = 1, ND51_NI + + SELECT CASE( ND51_TRACERS(W) ) + + CASE( 89, 90, 74, 75 ) + !-------------------------------------------------------- + ! Avoid div by zero for tracers which are archived each + ! chem timestep and only available in the troposphere + !-------------------------------------------------------- + IF ( COUNT_CHEM3D(X,Y,K) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / COUNT_CHEM3D(X,Y,K) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE( 82:87 ) + + !-------------------------------------------------------- + ! Avoid division by zero for tracers which are archived + ! on each chem timestep (at trop & strat levels) + !-------------------------------------------------------- + IF ( GOOD_CT_CHEM(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT_CHEM(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE DEFAULT + + !-------------------------------------------------------- + ! Avoid division by zero for all other tracers + !-------------------------------------------------------- + IF ( GOOD_CT(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + END SELECT + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !================================================================= + ! Write each tracer from "timeseries.dat" to the timeseries file + !================================================================= + DO W = 1, ND51_N_TRACERS + + ! ND51 tracer number + N = ND51_TRACERS(W) + + ! Save by simulation + IF ( N <= N_TRACERS ) THEN + + !--------------------- + ! GEOS-CHEM tracers + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N + + ELSE IF ( N == 89 ) THEN + + !--------------------- + ! Pure O3 + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N_TRACERS + 1 + + ELSE IF ( N == 90 ) THEN + !--------------------- + ! Pure NO [v/v] + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 91 ) THEN + !--------------------- + ! NOy + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 3 + + ELSE IF ( N == 74 ) THEN + + !--------------------- + ! OH + !--------------------- + CATEGORY = 'CHEM-L=$' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 75 ) THEN + + !--------------------- + ! NO2 + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 25 + + ELSE IF ( N == 76 ) THEN + + !--------------------- + ! PBL Height [m] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 77 ) THEN + + !--------------------- + ! PBL Height [levels] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMNL = 1 + GMTRC = 2 + + ELSE IF ( N == 78 ) THEN + + !--------------------- + ! Air Density + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 22 + + ELSE IF ( N == 79 ) THEN + + !--------------------- + ! 3-D Cloud fractions + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 19 + + ELSE IF ( N == 80 ) THEN + + !--------------------- + ! Column opt depths + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = 1 + GMTRC = 20 + + ELSE IF ( N == 81 ) THEN + + !--------------------- + ! Cloud top heights + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 82 ) THEN + + !--------------------- + ! Sulfate AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 6 + + ELSE IF ( N == 83 ) THEN + + !--------------------- + ! Black Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 84 ) THEN + + !--------------------- + ! Organic Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 12 + + ELSE IF ( N == 85 ) THEN + + !--------------------- + ! SS Accum AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 15 + + ELSE IF ( N == 86 ) THEN + + !--------------------- + ! SS Coarse AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 18 + + ELSE IF ( N == 87 ) THEN + + !--------------------- + ! Total dust OD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 4 + + ELSE IF ( N == 88 ) THEN + + !--------------------- + ! Total seasalt + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 24 + + ELSE IF ( N == 93 ) THEN + + !--------------------- + ! Grid box heights + !--------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 94 ) THEN + + !--------------------- + ! Relative humidity + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMNL = ND51_NL + GMTRC = 17 + + ELSE IF ( N == 95 ) THEN + + !--------------------- + ! Sea level prs + !--------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 96 ) THEN + + !--------------------- + ! U-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 97 ) THEN + + !--------------------- + ! V-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 2 + + ELSE IF ( N == 98 ) THEN + + !--------------------- + ! Psurface - PTOP + !--------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 99 ) THEN + + !--------------------- + ! Temperature + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'K' + GMNL = ND51_NL + GMTRC = 3 + + ELSE + + ! Otherwise skip + CYCLE + + ENDIF + + !------------------------ + ! Save to bpch file + !------------------------ + CALL BPCH2( IU_ND51, MODELNAME, LONRES, + & LATRES, HALFPOLAR, CENTER180, + & CATEGORY, GMTRC, UNIT, + & TAU0, TAU1, RESERVED, + & ND51_NI, ND51_NJ, GMNL, + & ND51_IMIN+I0, ND51_JMIN+J0, ND51_LMIN, + & REAL( Q(1:ND51_NI, 1:ND51_NJ, 1:GMNL, W) ) ) + ENDDO + + ! Echo info + WRITE( 6, 120 ) TRIM( FILENAME ) + 120 FORMAT( ' - DIAG51c: Closing file ', a ) + + ! Close file + CLOSE( IU_ND51 ) + + !================================================================= + ! Re-initialize quantities for next diagnostic cycle + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 130 ) STAMP + 130 FORMAT( ' - DIAG51c: Zeroing arrays at ', a ) + + ! Set STARTING TAU for the next bpch write + TAU0 = TAU_W + + ! Zero accumulating array for tracer + Q = 0d0 + + ! Zero counter arrays + COUNT_CHEM3D = 0d0 + GOOD_CT = 0d0 + GOOD_CT_CHEM = 0d0 + + ! Return to calling program + END SUBROUTINE WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION GET_I( X ) RESULT( I ) +! +!****************************************************************************** +! Function GET_I returns the absolute longitude index (I), given the +! relative longitude index (X). (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (INTEGER) : Relative longitude index (used by Q) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: X + + ! Local variables + INTEGER :: I + + !================================================================= + ! GET_I begins here! + !================================================================= + + ! Add the offset to X to get I + I = IOFF + X + + ! Handle wrapping around the date line, if necessary + IF ( I > IIPAR ) I = I - IIPAR + + ! Return to calling program + END FUNCTION GET_I + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG51c( DO_ND51, N_ND51, TRACERS, HR_WRITE, + & HR1, HR2, IMIN, IMAX, + & JMIN, JMAX, LMIN, LMAX, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG51 allocates and zeroes all module arrays. +! It also gets values for module variables from "input_mod.f". +! (bmy, 7/20/04, 1/22/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND51 (LOGICAL ) : Switch to turn on ND51 timeseries diagnostic +! (2 ) N_ND51 (INTEGER ) : Number of ND51 read by "input_mod.f" +! (3 ) TRACERS (INTEGER ) : Array w/ ND51 tracer #'s read by "input_mod.f" +! (4 ) HR_WRITE (REAL*8 ) : GMT hour of day at which to write bpch file +! (5 ) HR1 (REAL*8 ) : Lower limit of local time averaging bin +! (6 ) HR2 (REAL*8 ) : Upper limit of local time averaging bin +! (7 ) IMIN (INTEGER ) : Min longitude index read by "input_mod.f" +! (8 ) IMAX (INTEGER ) : Max longitude index read by "input_mod.f" +! (9 ) JMIN (INTEGER ) : Min latitude index read by "input_mod.f" +! (10) JMAX (INTEGER ) : Min latitude index read by "input_mod.f" +! (11) LMIN (INTEGER ) : Min level index read by "input_mod.f" +! (12) LMAX (INTEGER ) : Min level index read by "input_mod.f" +! (13) FILE (CHAR*255) : ND51 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Diagnostic counter arrays are now only 1-D. Also add GOOD_CT_CHEM +! which is the counter array of "good" boxes at each chemistry +! timesteps. Now allocate GOOD_CT_CHEM. (bmy, 10/25/04) +! (2 ) Now get I0 and J0 correctly for nested grid simulations (bmy, 11/9/04) +! (3 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (4 ) Now allow ND51_IMIN to be equal to ND51_IMAX and ND51_JMIN to be +! equal to ND51_JMAX. This will allow us to save out longitude or +! latitude transects. Allocate COUNT_CHEM3D. (cdh, bmy, phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, ITS_A_NESTED_GRID + USE TIME_MOD, ONLY : GET_TAUb + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND51 + INTEGER, INTENT(IN) :: N_ND51, TRACERS(100) + INTEGER, INTENT(IN) :: IMIN, IMAX + INTEGER, INTENT(IN) :: JMIN, JMAX + INTEGER, INTENT(IN) :: LMIN, LMAX + REAL*8, INTENT(IN) :: HR1, HR2 + REAL*8, INTENT(IN) :: HR_WRITE + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + INTEGER :: AS + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG51 begins here! + !================================================================= + + ! Initialize + LOCATION = 'INIT_DIAG51c ("diag51_mod.f")' + ND51_TRACERS(:) = 0 + + ! Get values from "input_mod.f" + DO_SAVE_DIAG51c = DO_ND51 + ND51_N_TRACERS = N_ND51 + ND51_TRACERS(1:N_ND51) = TRACERS(1:N_ND51) + ND51_HR_WRITE = HR_WRITE + ND51_HR1 = HR1 + ND51_HR2 = HR2 + ND51_IMIN = IMIN + ND51_IMAX = IMAX + ND51_JMIN = JMIN + ND51_JMAX = JMAX + ND51_LMIN = LMIN + ND51_LMAX = LMAX + ND51_OUTPUT_FILE = TRIM( FILE ) + + ! Make sure ND51_HR_WRITE is in the range 0-23.999 hrs + ND51_HR_WRITE = MOD( ND51_HR_WRITE, 24d0 ) + + ! Exit if ND51 is turned off + IF ( .not. DO_SAVE_DIAG51c ) RETURN + + !================================================================= + ! Error check longitude, latitude, altitude limits + !================================================================= + + ! Get grid offsets + IF ( ITS_A_NESTED_GRID() ) THEN + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + ELSE + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + ENDIF + + !----------- + ! Longitude + !----------- + + ! Error check ND51_IMIN + IF ( ND51_IMIN+I0 < 1 .or. ND51_IMIN+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMIN value!', LOCATION ) + ENDIF + + ! Error check ND51_IMAX + IF ( ND51_IMAX+I0 < 1 .or. ND51_IMAX+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMAX value!', LOCATION ) + ENDIF + + ! Compute longitude limits to write to disk + ! Also handle wrapping around the date line + IF ( ND51_IMAX >= ND51_IMIN ) THEN + ND51_NI = ( ND51_IMAX - ND51_IMIN ) + 1 + ELSE + ND51_NI = ( IIPAR - ND51_IMIN ) + 1 + ND51_IMAX + WRITE( 6, '(a)' ) 'We are wrapping over the date line!' + ENDIF + + ! Make sure that ND50_NI <= IIPAR + IF ( ND51_NI > IIPAR ) THEN + CALL ERROR_STOP( 'Too many longitudes!', LOCATION ) + ENDIF + + !----------- + ! Latitude + !----------- + + ! Error check JMIN_AREA + IF ( ND51_JMIN+J0 < 1 .or. ND51_JMIN+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMIN value!', LOCATION ) + ENDIF + + ! Error check JMAX_AREA + IF ( ND51_JMAX+J0 < 1 .or.ND51_JMAX+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMAX value!', LOCATION ) + ENDIF + + ! Compute latitude limits to write to disk (bey, bmy, 3/16/99) + IF ( ND51_JMAX >= ND51_JMIN ) THEN + ND51_NJ = ( ND51_JMAX - ND51_JMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_JMAX < ND51_JMIN!', LOCATION ) + ENDIF + + !----------- + ! Altitude + !----------- + + ! Error check ND51_LMIN, ND51_LMAX + IF ( ND51_LMIN < 1 .or. ND51_LMAX > LLPAR ) THEN + CALL ERROR_STOP( 'Bad ND51 altitude values!', LOCATION ) + ENDIF + + ! # of levels to save in ND51 timeseries + IF ( ND51_LMAX >= ND51_LMIN ) THEN + ND51_NL = ( ND51_LMAX - ND51_LMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_LMAX < ND51_LMIN!', LOCATION ) + ENDIF + + !----------- + ! Offsets + !----------- + IOFF = ND51_IMIN - 1 + JOFF = ND51_JMIN - 1 + LOFF = ND51_LMIN - 1 + + !----------- + ! For bpch + !----------- + TAU0 = GET_TAUb() + TITLE = 'GEOS-CHEM DIAG51 time series' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Reset offsets to global values for bpch write + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + !================================================================= + ! Allocate arrays + !================================================================= + + ! Array denoting where LT is between HR1 and HR2 + ALLOCATE( GOOD( IIPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD' ) + GOOD = 0 + + ! Counter of "good" times per day at each grid box + ALLOCATE( GOOD_CT( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT' ) + GOOD_CT = 0 + + ! Counter of "good" times per day for each chemistry timestep + ALLOCATE( GOOD_CT_CHEM( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT_CHEM' ) + GOOD_CT_CHEM = 0 + + ! Accumulating array + ALLOCATE( Q( ND51_NI, ND51_NJ, ND51_NL, ND51_N_TRACERS), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'Q' ) + Q = 0d0 + + ! Accumulating array + ALLOCATE( COUNT_CHEM3D( ND51_NI, ND51_NJ, ND51_NL ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'COUNT_CHEM3D' ) + COUNT_CHEM3D = 0 + + ! Return to calling program + END SUBROUTINE INIT_DIAG51c + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG51c +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG51 deallocates all module arrays. +! (bmy, 11/29/00, 1/24/07) +! +! NOTES: +! (1 ) Now deallocate GOOD_CT_CHEM (bmy, 10/25/04) +! (2 ) Also deallocate COUNT_CHEM3D (phs, 1/24/07) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG51 begins here! + !================================================================= + IF ( ALLOCATED( COUNT_CHEM3D ) ) DEALLOCATE( COUNT_CHEM3D ) + IF ( ALLOCATED( GOOD ) ) DEALLOCATE( GOOD ) + IF ( ALLOCATED( GOOD_CT ) ) DEALLOCATE( GOOD_CT ) + IF ( ALLOCATED( GOOD_CT_CHEM ) ) DEALLOCATE( GOOD_CT_CHEM ) + IF ( ALLOCATED( Q ) ) DEALLOCATE( Q ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG51c + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG51c_MOD diff --git a/code/diag51d_mod.f b/code/diag51d_mod.f new file mode 100644 index 0000000..ba8da64 --- /dev/null +++ b/code/diag51d_mod.f @@ -0,0 +1,1594 @@ +! $Id: diag51_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE DIAG51d_MOD +! +!****************************************************************************** +! Module DIAG51_MOD contains variables and routines to generate save +! timeseries data where the local time is between two user-defined limits. +! This facilitates comparisons with morning or afternoon-passing satellites +! such as GOME. (amf, bey, bdf, pip, bmy, 11/30/00, 12/10/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_DIAG51d (LOGICAL ) : Flag to turn on DIAG51 timseries +! (2 ) GOOD (INTEGER ) : Array denoting grid boxes w/in LT limits +! (3 ) GOOD_CT (INTEGER ) : # of "good" times per grid box +! (4 ) GOOD_CT_CHEM (INTEGER ) : # of "good" chemistry timesteps +! (5 ) COUNT_CHEM3D (INTEGER ) : Counter for 3D chemistry boxes +! (6 ) ND51_HR_WRITE (INTEGER ) : Hour at which to save to disk +! (7 ) I0 (INTEGER ) : Offset between global & nested grid +! (8 ) J0 (INTEGER ) : Offset between global & nested grid +! (9 ) IOFF (INTEGER ) : Longitude offset +! (10) JOFF (INTEGER ) : Latitude offset +! (11) LOFF (INTEGER ) : Altitude offset +! (12) ND51_HR1 (REAL*8 ) : Starting hour of user-defined LT interval +! (13) ND51_HR2 (REAL*8 ) : Ending hour of user-defined LT interval +! (14) ND51_IMIN (INTEGER ) : Minimum latitude index for DIAG51 region +! (15) ND51_IMAX (INTEGER ) : Maximum latitude index for DIAG51 region +! (16) ND51_JMIN (INTEGER ) : Minimum longitude index for DIAG51 region +! (17) ND51_JMAX (INTEGER ) : Maximum longitude index for DIAG51 region +! (18) ND51_LMIN (INTEGER ) : Minimum altitude index for DIAG51 region +! (19) ND51_LMAX (INTEGER ) : Minimum latitude index for DIAG51 region +! (20) ND51_NI (INTEGER ) : Number of longitudes in DIAG51 region +! (21) ND51_NJ (INTEGER ) : Number of latitudes in DIAG51 region +! (22) ND51_NL (INTEGER ) : Number of levels in DIAG51 region +! (23) ND51_N_TRACERS (INTEGER ) : Number of tracers for DIAG51 +! (24) ND51_OUTPUT_FILE (CHAR*255) : Name of bpch file w timeseries data +! (25) ND51_TRACERS (INTEGER ) : Array of DIAG51 tracer numbers +! (26) Q (REAL*8 ) : Accumulator array for various quantities +! (27) TAU0 (REAL*8 ) : Starting TAU used to index the bpch file +! (28) TAU1 (REAL*8 ) : Ending TAU used to index the bpch file +! (29) HALFPOLAR (INTEGER ) : Used for bpch file output +! (30) CENTER180 (INTEGER ) : Used for bpch file output +! (31) LONRES (REAL*4 ) : Used for bpch file output +! (32) LATRES (REAL*4 ) : Used for bpch file output +! (33) MODELNAME (CHAR*20 ) : Used for bpch file output +! (34) RESERVED (CHAR*40 ) : Used for bpch file output +! +! Module Procedures: +! ============================================================================ +! (1 ) DIAG51d : Driver subroutine for US grid timeseries +! (2 ) GET_LOCAL_TIME : Computes the local times at each grid box +! (3 ) WRITE_DIAG51 : Writes timeseries data to a bpch file +! (4 ) ITS_TIME_FOR_WRITE_DIAG51 : Returns T if it's time to save to disk +! (5 ) ACCUMULATE_DIAG51 : Accumulates data over for later averaging +! (6 ) INIT_DIAG51 : Allocates and zeroes all module arrays +! (7 ) CLEANUP_DIAG51d : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag51_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) error_mod.f : Module w/ NaN and other error check routines +! (4 ) file_mod.f : Module w/ file unit numbers and error checks +! (5 ) grid_mod.f : Module w/ horizontal grid information +! (6 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (7 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (8 ) time_mod.f : Module w/ routines to compute date & time +! (9 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! ND51 tracer numbers: +! ============================================================================ +! 1 - N_TRACERS : GEOS-CHEM transported tracers [v/v ] +! 74 : OH concentration [molec/cm3] +! 75 : NO2 concentration [v/v ] +! 76 : PBL heights [m ] +! 77 : PBL heights [levels ] +! 78 : Air density [molec/cm3] +! 79 : 3-D Cloud fractions [unitless ] +! 80 : Column optical depths [unitless ] +! 81 : Cloud top heights [hPa ] +! 82 : Sulfate aerosol optical depth [unitless ] +! 83 : Black carbon aerosol optical depth [unitless ] +! 84 : Organic carbon aerosol optical depth [unitless ] +! 85 : Accumulation mode seasalt optical depth [unitless ] +! 86 : Coarse mode seasalt optical depth [unitless ] +! 87 : Total dust optical depth [unitless ] +! 88 : Total seasalt tracer concentration [unitless ] +! 89 : Pure O3 (not Ox) concentration [v/v ] +! 90 : NO concentration [v/v ] +! 91 : NOy concentration [v/v ] +! 92 : RESERVED FOR FUTURE USE +! 93 : Grid box heights [m ] +! 94 : Relative Humidity [% ] +! 95 : Sea level pressure [hPa ] +! 96 : Zonal wind (a.k.a. U-wind) [m/s ] +! 97 : Meridional wind (a.k.a. V-wind) [m/s ] +! 98 : P(surface) - PTOP [hPa ] +! 99 : Temperature [K ] +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added extra counters for NO, NO2, OH, O3. Also all diagnostic counter +! arrays are 1-D since they only depend on longitude. (bmy, 10/25/04) +! (3 ) Bug fix: Now get I0 and J0 properly for nested grids (bmy, 11/9/04) +! (4 ) Now only archive AOD's once per chemistry timestep (bmy, 1/14/05) +! (5 ) Now references "pbl_mix_mod.f" (bmy, 2/16/05) +! (6 ) Now save cld frac and grid box heights (bmy, 4/20/05) +! (7 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (8 ) Bug fix: do not save SLP if it's not allocated (bmy, 8/2/05) +! (9 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (10) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (11) Modified INIT_DIAG51 to save out transects (cdh, bmy, 11/30/06) +! (12) Now use 3D timestep counter for full chem in the trop (phs, 1/24/07) +! (13) Renumber RH in WRITE_DIAG50 (bmy, 2/11/08) +! (14) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +! (15) Bug fix in GET_LOCAL_TIME (ccc, 12/10/08) +! (16) Modified to archive O3, NO, NOy as tracers 89, 90, 91 (tmf, 9/26/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag51_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DO_SAVE_DIAG51d + + ! ... and these routines + PUBLIC :: CLEANUP_DIAG51d + PUBLIC :: DIAG51d + PUBLIC :: INIT_DIAG51d + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_DIAG51d + INTEGER :: IOFF, JOFF, LOFF + INTEGER :: I0, J0 + INTEGER :: ND51_N_TRACERS, ND51_TRACERS(100) + INTEGER :: ND51_IMIN, ND51_IMAX + INTEGER :: ND51_JMIN, ND51_JMAX + INTEGER :: ND51_LMIN, ND51_LMAX + INTEGER :: ND51_FREQ, ND51_NI + INTEGER :: ND51_NJ, ND51_NL + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180=1 + REAL*4 :: LONRES, LATRES + REAL*8 :: TAU0, TAU1 + REAL*8 :: ND51_HR1, ND51_HR2 + REAL*8 :: ND51_HR_WRITE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: RESERVED = '' + CHARACTER(LEN=80) :: TITLE + CHARACTER(LEN=255) :: ND51_OUTPUT_FILE + + ! Arrays + INTEGER, ALLOCATABLE :: GOOD(:) + INTEGER, ALLOCATABLE :: GOOD_CT(:) + INTEGER, ALLOCATABLE :: GOOD_CT_CHEM(:) + INTEGER, ALLOCATABLE :: COUNT_CHEM3D(:,:,:) + REAL*8, ALLOCATABLE :: Q(:,:,:,:) + + !================================================================= + ! Original code from old DIAG51_MOD. Leave here as a guide to + ! figure out when the averaging periods should be and when to + ! write to disk (bmy, 9/28/04) + ! + !! For timeseries between 1300 and 1700 LT, uncomment this code: + !! + !! Need to write to the bpch file at 12 GMT, since this covers + !! an entire day over the US grid (amf, bmy, 12/1/00) + !! + !INTEGER, PARAMETER :: NHMS_WRITE = 120000 + !REAL*8, PARAMETER :: HR1 = 13d0 + !REAL*8, PARAMETER :: HR2 = 17d0 + !CHARACTER(LEN=255) :: FILENAME = 'ts1_4pm.bpch' + !================================================================= + ! For timeseries between 1000 and 1200 LT, uncomment this code: + ! + ! Between 10 and 12 has been chosen because the off-polar orbit + ! of GOME traverses (westward) through local times between 12 + ! and 10 over North America, finally crossing the equator at + ! 10.30 (local time). + ! + ! Need to write to the bpch file at 00 GMT, since we will be + ! interested in the whole northern hemisphere (pip, 12/1/00) + ! + !INTEGER, PARAMETER :: NHMS_WRITE = 000000 + !REAL*8, PARAMETER :: HR1 = 10d0 + !REAL*8, PARAMETER :: HR2 = 12d0 + !CHARACTER(LEN=255) :: FILENAME ='ts10_12pm.bpch' + !================================================================= + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG51d +! +!****************************************************************************** +! Subroutine DIAG51 generates time series (averages from 10am - 12pm LT +! or 1pm - 4pm LT) for the US grid area. Output is to binary punch files. +! (amf, bey, bdf, pip, bmy, 11/15/99, 9/28/04) +! +! NOTES: +! (1 ) Rewritten for clarity (bmy, 7/20/04) +! (2 ) Added TAU_W as a local variable (bmy, 9/28/04) +!****************************************************************************** +! + ! Local variables + REAL*8 :: TAU_W + + !================================================================= + ! DIAG51 begins here! + !================================================================= + + ! Construct array of where local times are between HR1, HR2 + CALL GET_LOCAL_TIME + + ! Accumulate data in the Q array + CALL ACCUMULATE_DIAG51 + + ! Write data to disk at the proper time + IF ( ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) ) THEN + CALL WRITE_DIAG51( TAU_W ) + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG51d + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_LOCAL_TIME +! +!****************************************************************************** +! Subroutine GET_LOCAL_TIME computes the local time and returns an array +! of points where the local time is between two user-defined limits. +! (bmy, 11/29/00, 12/10/08) +! +! NOTES: +! (1 ) The 1d-3 in the computation of XLOCTM is to remove roundoff ambiguity +! if a the local time should fall exactly on an hour boundary. +! (bmy, 11/29/00) +! (2 ) Bug fix: XMID(I) should be XMID(II). Also updated comments. +! (bmy, 7/6/01) +! (3 ) Updated comments (rvm, bmy, 2/27/02) +! (4 ) Now uses function GET_LOCALTIME of "time_mod.f" (bmy, 3/27/03) +! (5 ) Removed reference to CMN (bmy, 7/20/04) +! (6 ) Bug fix: LT should be REAL*8 and not INTEGER (ccarouge, 12/10/08) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_LOCALTIME + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + !------------------------------------------ + ! Prior to 12/10/08: + ! LT should be REAL*8 (ccarouge, 12/10/08) + !INTEGER :: I, LT + !------------------------------------------ + INTEGER :: I + REAL*8 :: LT + + !================================================================= + ! GET_LOCAL_TIME begins here! + !================================================================= + DO I = 1, IIPAR + + ! Get local time + LT = GET_LOCALTIME(I) + + ! GOOD indicates which boxes have local times between HR1 and HR2 + IF ( LT >= ND51_HR1 .and. LT <= ND51_HR2 ) THEN + GOOD(I) = 1 + ELSE + GOOD(I) = 0 + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE GET_LOCAL_TIME + +!------------------------------------------------------------------------------ + + SUBROUTINE ACCUMULATE_DIAG51 +! +!****************************************************************************** +! Subroutine ACCUMULATE_DIAG51 accumulates tracers into the Q array. +! (bmy, 8/20/02, 1/24/07) +! +! NOTES: +! (1 ) Rewrote to remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. Now scale optical depths +! to 400 nm (which is usually what QAA(2,*) is. (bmy, 7/20/04) +! (2 ) Now reference GET_ELAPSED_MIN and GET_TS_CHEM from "time_mod.f". +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). (bmy, 10/25/04) +! (3 ) Only archive AOD's when it is a chem timestep (bmy, 1/14/05) +! (4 ) Remove reference to "CMN". Also now get PBL heights in meters and +! model layers from GET_PBL_TOP_m and GET_PBL_TOP_L of "pbl_mix_mod.f". +! (bmy, 2/16/05) +! (5 ) Now reference CLDF and BXHEIGHT from "dao_mod.f". Now save 3-D cloud +! fraction as tracer #79 and box height as tracer #93. Now remove +! references to CLMOSW, CLROSW, and PBL from "dao_mod.f". (bmy, 4/20/05) +! (6 ) Remove TRCOFFSET since it's always zero Also now get HALFPOLAR for +! both GCAP and GEOS grids. (bmy, 6/28/05) +! (7 ) Now do not save SLP data if it is not allocated (bmy, 8/2/05) +! (8 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (9 ) Now references XNUMOLAIR from "tracer_mod.f" (bmy, 10/25/05) +! (10) Now account for time spent in the trop for non-tracers (phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AD, AIRDEN, BXHEIGHT, CLDF + USE DAO_MOD, ONLY : CLDTOPS, OPTD, RH, T + USE DAO_MOD, ONLY : UWND, VWND, SLP + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_L, GET_PBL_TOP_m + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : GET_ELAPSED_MIN, GET_TS_CHEM + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : STT, TCVV, ITS_A_FULLCHEM_SIM + USE TRACER_MOD, ONLY : N_TRACERS, XNUMOLAIR + USE TRACERID_MOD, ONLY : IDTHNO3, IDTHNO4, IDTN2O5, IDTNOX + USE TRACERID_MOD, ONLY : IDTPAN, IDTPMN, IDTPPN, IDTOX + USE TRACERID_MOD, ONLY : IDTR4N2, IDTSALA, IDTSALC + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + +# include "cmn_fj.h" ! includes CMN_SIZE +# include "jv_cmn.h" ! ODAER +# include "CMN_O3" ! FRACO3, FRACNO, SAVEO3, SAVENO2, SAVEHO2, FRACNO2 +# include "CMN_GCTM" ! SCALE_HEIGHT + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL, SAVE :: IS_FULLCHEM, IS_NOx, IS_Ox, IS_SEASALT + LOGICAL, SAVE :: IS_CLDTOPS, IS_NOy, IS_OPTD, IS_SLP + LOGICAL :: IS_CHEM + INTEGER :: H, I, J, K, L, M, N + INTEGER :: PBLINT, R, X, Y, W, XMIN + REAL*8 :: C1, C2, PBLDEC, TEMPBL, TMP, SCALEAODnm + CHARACTER(LEN=16) :: STAMP + + ! Aerosol types (rvm, aad, bmy, 7/20/04) + INTEGER :: IND(6) = (/ 22, 29, 36, 43, 50, 15 /) + + !================================================================= + ! ACCUMULATE_DIAG51 begins here! + !================================================================= + + ! Set logical flags on first call + IF ( FIRST ) THEN + IS_OPTD = ALLOCATED( OPTD ) + IS_CLDTOPS = ALLOCATED( CLDTOPS ) + IS_SLP = ALLOCATED( SLP ) + IS_FULLCHEM = ITS_A_FULLCHEM_SIM() + IS_SEASALT = ( IDTSALA > 0 .and. IDTSALC > 0 ) + IS_NOx = ( IS_FULLCHEM .and. IDTNOX > 0 ) + IS_Ox = ( IS_FULLCHEM .and. IDTOx > 0 ) + IS_NOy = ( IS_FULLCHEM .and. + & IDTNOX > 0 .and. IDTPAN > 0 .and. + & IDTHNO3 > 0 .and. IDTPMN > 0 .and. + & IDTPPN > 0 .and. IDTR4N2 > 0 .and. + & IDTN2O5 > 0 .and. IDTHNO4 > 0 ) + FIRST = .FALSE. + ENDIF + + ! Is it a chemistry timestep? + IS_CHEM = ( MOD( GET_ELAPSED_MIN(), GET_TS_CHEM() ) == 0 ) + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 100 ) STAMP + 100 FORMAT( ' - DIAG51d: Accumulation at ', a ) + + !================================================================= + ! Archive tracers into accumulating array Q + !================================================================= + + ! Archive counter array of good points + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT(X) = GOOD_CT(X) + GOOD(I) + ENDDO + + ! Archive counter array of good points for chemistry timesteps only + IF ( IS_CHEM ) THEN + DO X = 1, ND51_NI + I = GET_I( X ) + GOOD_CT_CHEM(X) = GOOD_CT_CHEM(X) + GOOD(I) + ENDDO + ENDIF + + + ! Also increment 3-D counter for boxes in the tropopause + IF ( IS_FULLCHEM .and. IS_CHEM ) THEN + + ! Loop over levels +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, I, J, L ) +!$OMP+SCHEDULE( DYNAMIC ) + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Only increment if we are in the trop + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + COUNT_CHEM3D(X,Y,K) = COUNT_CHEM3D(X,Y,K) + GOOD(I) + ENDIF + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + !------------------------ + ! Accumulate quantities + !------------------------ +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( W, N, X, Y, K, I, J, L, TMP, H, R, SCALEAODnm ) +!$OMP+SCHEDULE( DYNAMIC ) + DO W = 1, ND51_N_TRACERS + + ! ND51 Tracer number + N = ND51_TRACERS(W) + + ! Loop over levels + DO K = 1, ND51_NL + L = LOFF + K + + ! Loop over latitudes + DO Y = 1, ND51_NJ + J = JOFF + Y + + ! Loop over longitudes + DO X = 1, ND51_NI + I = GET_I( X ) + + ! Archive by simulation + IF ( N <= N_TRACERS ) THEN + + !-------------------------------------- + ! GEOS-CHEM tracers [v/v] + !-------------------------------------- + + ! Archive afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,N) * TCVV(N) / + & AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 89 .and. IS_Ox .and. IS_CHEM ) THEN + + !-------------------------------------- + ! Pure O3 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTOX) * FRACO3(I,J,L) * + & TCVV(IDTOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 90 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 91 .and. IS_NOy ) THEN + + !-------------------------------------- + ! NOy [v/v] + !-------------------------------------- + + ! Temp variable for accumulation + TMP = 0d0 + + ! NOx + TMP = TMP + ( TCVV(IDTNOX) * GOOD(I) * + & STT(I,J,L,IDTNOX) / AD(I,J,L) ) + ! PAN + TMP = TMP + ( TCVV(IDTPAN) * GOOD(I) * + & STT(I,J,L,IDTPAN) / AD(I,J,L) ) + + ! HNO3 + TMP = TMP + ( TCVV(IDTHNO3) * GOOD(I) * + & STT(I,J,L,IDTHNO3) / AD(I,J,L) ) + + ! PMN + TMP = TMP + ( TCVV(IDTPMN) * GOOD(I) * + & STT(I,J,L,IDTPMN) / AD(I,J,L) ) + + ! PPN + TMP = TMP + ( TCVV(IDTPPN) * GOOD(I) * + & STT(I,J,L,IDTPPN) / AD(I,J,L) ) + + ! R4N2 + TMP = TMP + ( TCVV(IDTR4N2) * GOOD(I) * + & STT(I,J,L,IDTR4N2) / AD(I,J,L) ) + + ! N2O5 + TMP = TMP + ( 2d0 * TCVV(IDTN2O5) * GOOD(I) * + & STT(I,J,L,IDTN2O5) / AD(I,J,L) ) + + ! HNO4 + TMP = TMP + ( TCVV(IDTHNO4) * GOOD(I) * + & STT(I,J,L,IDTHNO4) / AD(I,J,L) ) + + ! Save afternoon points + Q(X,Y,K,W) = Q(X,Y,K,W) + TMP + + ELSE IF ( N == 74 .and. IS_FULLCHEM .and. IS_CHEM ) THEN + + !-------------------------------------- + ! OH [molec/cm3] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + + ! Accumulate data + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SAVEOH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 75 .and. IS_NOx .and. IS_CHEM ) THEN + + !-------------------------------------- + ! NO2 [v/v] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTNOX) * FRACNO2(I,J,L) * + & TCVV(IDTNOX) / AD(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 76 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [m] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_m( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 77 ) THEN + + !-------------------------------------- + ! PBL HEIGHTS [layers] + !-------------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( GET_PBL_TOP_L( I, J ) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 78 ) THEN + + !-------------------------------------- + ! AIR DENSITY [molec/cm3] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( AIRDEN(L,I,J) * XNUMOLAIR * 1d-6 * GOOD(I) ) + + ELSE IF ( N == 79 ) THEN + + !-------------------------------------- + ! 3-D CLOUD FRACTION [unitless] + !-------------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( CLDF(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 80 .and. IS_OPTD ) THEN + + !-------------------------------------- + ! COLUMN OPTICAL DEPTH [unitless] + !-------------------------------------- + Q(X,Y,1,W) = Q(X,Y,1,W) + ( OPTD(L,I,J) * GOOD(I) ) + + ELSE IF ( N == 81 .and. IS_CLDTOPS ) THEN + + !-------------------------------------- + ! CLOUD TOP HEIGHTS [mb] + !-------------------------------------- + IF ( K == 1 ) THEN + TMP = GET_PEDGE( I, J, CLDTOPS(I,J) ) + Q(X,Y,K,W) = Q(X,Y,K,W) + ( TMP * GOOD(I) ) + ENDIF + + ELSE IF ( N == 82 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! SULFATE AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO H = 1, NRH + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(1)+H-1) / QAA(4,IND(1)+H-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 83 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! BLACK CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(2)+R-1) / QAA(4,IND(2)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 84 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ORG CARBON AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 2*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(3)+R-1) / QAA(4,IND(3)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 85 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! ACCUM SEASALT AOD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 3*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(4)+R-1) / QAA(4,IND(4)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 86 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! COARSE SEASALT AOD 400 nm [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NRH + + ! Index for ODAER + H = 4*NRH + R + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(5)+R-1) / QAA(4,IND(5)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODAER(I,J,L,H) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 87 .and. IS_CHEM ) THEN + + !-------------------------------------- + ! TOTAL DUST OPTD @ jv_spec_aod.dat wavelength [unitless] + ! NOTE: Only archive at chem timestep + !-------------------------------------- + DO R = 1, NDUST + + ! Scaling factor for AOD wavelength (clh, 05/09) + SCALEAODnm = QAA_AOD(IND(6)+R-1) / QAA(4,IND(6)+R-1) + + ! Accumulate + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( ODMDUST(I,J,L,R) * SCALEAODnm * GOOD(I) ) + ENDDO + + ELSE IF ( N == 88 .and. IS_SEASALT ) THEN + + !----------------------------------- + ! TOTAL SEASALT TRACER [v/v] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + + & ( STT(I,J,L,IDTSALA) + + & STT(I,J,L,IDTSALC) ) * + & TCVV(IDTSALA) / AD(I,J,L) * GOOD(I) + + ELSE IF ( N == 93 ) THEN + + !----------------------------------- + ! GRID BOX HEIGHTS [m] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( BXHEIGHT(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 94 ) THEN + + !----------------------------------- + ! RELATIVE HUMIDITY [%] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( RH(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 95 .and. IS_SLP ) THEN + + !----------------------------------- + ! SEA LEVEL PRESSURE [hPa] + !----------------------------------- + IF ( K == 1 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) + ( SLP(I,J) * GOOD(I) ) + ENDIF + + ELSE IF ( N == 96 ) THEN + + !----------------------------------- + ! ZONAL (U) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( UWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 97 ) THEN + + !----------------------------------- + ! MERIDIONAL (V) WIND [M/S] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( VWND(I,J,L) * GOOD(I) ) + + ELSE IF ( N == 98 ) THEN + + !----------------------------------- + ! PEDGE-$ (prs @ level edges) [hPa] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( GET_PEDGE(I,J,K) * GOOD(I) ) + + ELSE IF ( N == 99 ) THEN + + !----------------------------------- + ! TEMPERATURE [K] + !----------------------------------- + Q(X,Y,K,W) = Q(X,Y,K,W) + ( T(I,J,L) * GOOD(I) ) + + ENDIF + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE ACCUMULATE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_WRITE_DIAG51( TAU_W ) RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_WRITE_DIAG51 returns TRUE if it's time to write +! the ND51 bpch file to disk. We test the time at the next dynamic +! timestep so that we can write to disk properly. (bmy, 7/20/04, 9/28/04) +! +! Arguments as Output: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Added TAU_W so to make sure the timestamp is accurate. (bmy, 9/28/04) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE, GET_TAU, + & GET_TAUb, GET_TAUe, GET_TS_DYN + + ! Arguments + REAL*8, INTENT(OUT) :: TAU_W + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: TAU, HOUR, DYN + + !================================================================= + ! ITS_TIME_FOR_WRITE_DIAG51 begins here! + !================================================================= + + ! Initialize + ITS_TIME = .FALSE. + + ! Current TAU, Hour, and Dynamic Timestep [hrs] + TAU = GET_TAU() + HOUR = ( GET_MINUTE() / 60d0 ) + GET_HOUR() + DYN = ( GET_TS_DYN() / 60d0 ) + + ! If first timestep, return FALSE + IF ( TAU == GET_TAUb() ) RETURN + + ! If the next dyn timestep is the hour of day + ! when we have to save to disk, return TRUE + IF ( MOD( HOUR+DYN, 24d0 ) == ND51_HR_WRITE ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! If the next dyn timestep is the + ! end of the run, return TRUE + IF ( TAU + DYN == GET_TAUe() ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG51( TAU_W ) +! +!****************************************************************************** +! Subroutine WRITE_DIAG51 computes the time-average of quantities between +! local time limits ND51_HR1 and ND51_HR2 and writes them to a bpch file. +! Arrays and counters are also zeroed for the next diagnostic interval. +! (bmy, 12/1/00, 10/7/08) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +! (1 ) Rewrote to` remove hardwiring and for better efficiency. Added extra +! diagnostics and updated numbering scheme. (bmy, 7/20/04) +! (2 ) Added TAU_W to the arg list. Now use TAU_W to set TAU0 and TAU0. +! Also now all diagnostic counters are 1-D since they only depend on +! longitude. Now only archive NO, NO2, OH, O3 on every chemistry +! timestep (i.e. only when fullchem is called). Also remove reference +! to FIRST. (bmy, 10/25/04) +! (3 ) Now divide tracers 82-87 (i.e. various AOD's) by GOOD_CT_CHEM since +! these are only updated once per chemistry timestep (bmy, 1/14/05) +! (4 ) Now save grid box heights as tracer #93. Now save 3-D cloud fraction +! as tracer #79 (bmy, 4/20/05) +! (5 ) Remove references to TRCOFFSET because it's always zero (bmy, 6/24/05) +! (6 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (7 ) DIVISOR is now a 3-D array. Now zero COUNT_CHEM3D. Now use CASE +! statement instead of IF statements. Now zero counter arrays with +! array broadcast assignments. (phs, 1/24/07) +! (8 ) RH should be tracer #17 under "TIME-SER" category (bmy, 2/11/08) +! (9 ) Bug fix: replace "PS-PTOP" with "PEDGE-$" (bmy, phs, 10/7/08) +!****************************************************************************** +! + ! Reference to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, OPEN_BPCH2_FOR_WRITE + USE ERROR_MOD, ONLY : ALLOC_ERR + USE FILE_MOD, ONLY : IU_ND51 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_NYMD + USE TIME_MOD, ONLY : GET_NHMS, GET_TAU + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size Parameters + + ! Arguments + REAL*8, INTENT(IN) :: TAU_W + + ! Local variables + INTEGER :: I, J, L, W, N, GMNL, GMTRC + INTEGER :: IOS, X, Y, K + CHARACTER(LEN=16) :: STAMP + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! WRITE_DIAG51 begins here! + !================================================================= + + ! Replace date tokens in FILENAME + FILENAME = ND51_OUTPUT_FILE + CALL EXPAND_DATE( FILENAME, GET_NYMD(), GET_NHMS() ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - DIAG51d: Opening file ', a ) + + ! Open output file + CALL OPEN_BPCH2_FOR_WRITE( IU_ND51, FILENAME, TITLE ) + + ! Set ENDING TAU for this bpch write + TAU1 = TAU_W + + !================================================================= + ! Compute time-average of tracers between local time limits + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 110 ) STAMP + 110 FORMAT( ' - DIAG51d: Saving to disk at ', a ) + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( X, Y, K, W ) + + DO W = 1, ND51_N_TRACERS + + ! Loop over grid boxes + DO K = 1, ND51_NL + DO Y = 1, ND51_NJ + DO X = 1, ND51_NI + + SELECT CASE( ND51_TRACERS(W) ) + + CASE( 89, 90, 74, 75 ) + !-------------------------------------------------------- + ! Avoid div by zero for tracers which are archived each + ! chem timestep and only available in the troposphere + !-------------------------------------------------------- + IF ( COUNT_CHEM3D(X,Y,K) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / COUNT_CHEM3D(X,Y,K) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE( 82:87 ) + + !-------------------------------------------------------- + ! Avoid division by zero for tracers which are archived + ! on each chem timestep (at trop & strat levels) + !-------------------------------------------------------- + IF ( GOOD_CT_CHEM(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT_CHEM(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + CASE DEFAULT + + !-------------------------------------------------------- + ! Avoid division by zero for all other tracers + !-------------------------------------------------------- + IF ( GOOD_CT(X) > 0 ) THEN + Q(X,Y,K,W) = Q(X,Y,K,W) / GOOD_CT(X) + ELSE + Q(X,Y,K,W) = 0d0 + ENDIF + + END SELECT + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !================================================================= + ! Write each tracer from "timeseries.dat" to the timeseries file + !================================================================= + DO W = 1, ND51_N_TRACERS + + ! ND51 tracer number + N = ND51_TRACERS(W) + + ! Save by simulation + IF ( N <= N_TRACERS ) THEN + + !--------------------- + ! GEOS-CHEM tracers + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N + + ELSE IF ( N == 89 ) THEN + + !--------------------- + ! Pure O3 + !--------------------- + CATEGORY = 'IJ-AVG-$' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = N_TRACERS + 1 + + ELSE IF ( N == 90 ) THEN + !--------------------- + ! Pure NO [v/v] + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 91 ) THEN + !--------------------- + ! NOy + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 3 + + ELSE IF ( N == 74 ) THEN + + !--------------------- + ! OH + !--------------------- + CATEGORY = 'CHEM-L=$' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 75 ) THEN + + !--------------------- + ! NO2 + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 25 + + ELSE IF ( N == 76 ) THEN + + !--------------------- + ! PBL Height [m] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'm' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 77 ) THEN + + !--------------------- + ! PBL Height [levels] + !--------------------- + CATEGORY = 'PBLDEPTH' + UNIT = 'levels' + GMNL = 1 + GMTRC = 2 + + ELSE IF ( N == 78 ) THEN + + !--------------------- + ! Air Density + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'molec/cm3' + GMNL = ND51_NL + GMTRC = 22 + + ELSE IF ( N == 79 ) THEN + + !--------------------- + ! 3-D Cloud fractions + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 19 + + ELSE IF ( N == 80 ) THEN + + !--------------------- + ! Column opt depths + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'unitless' + GMNL = 1 + GMTRC = 20 + + ELSE IF ( N == 81 ) THEN + + !--------------------- + ! Cloud top heights + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 82 ) THEN + + !--------------------- + ! Sulfate AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 6 + + ELSE IF ( N == 83 ) THEN + + !--------------------- + ! Black Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 9 + + ELSE IF ( N == 84 ) THEN + + !--------------------- + ! Organic Carbon AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 12 + + ELSE IF ( N == 85 ) THEN + + !--------------------- + ! SS Accum AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 15 + + ELSE IF ( N == 86 ) THEN + + !--------------------- + ! SS Coarse AOD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 18 + + ELSE IF ( N == 87 ) THEN + + !--------------------- + ! Total dust OD + !--------------------- + CATEGORY = 'OD-MAP-$' + UNIT = 'unitless' + GMNL = ND51_NL + GMTRC = 4 + + ELSE IF ( N == 88 ) THEN + + !--------------------- + ! Total seasalt + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '' ! Let GAMAP pick unit + GMNL = ND51_NL + GMTRC = 24 + + ELSE IF ( N == 93 ) THEN + + !--------------------- + ! Grid box heights + !--------------------- + CATEGORY = 'BXHGHT-$' + UNIT = 'm' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 94 ) THEN + + !--------------------- + ! Relative humidity + !--------------------- + CATEGORY = 'TIME-SER' + UNIT = '%' + GMNL = ND51_NL + GMTRC = 17 + + ELSE IF ( N == 95 ) THEN + + !--------------------- + ! Sea level prs + !--------------------- + CATEGORY = 'DAO-FLDS' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 21 + + ELSE IF ( N == 96 ) THEN + + !--------------------- + ! U-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 1 + + ELSE IF ( N == 97 ) THEN + + !--------------------- + ! V-wind + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'm/s' + GMNL = ND51_NL + GMTRC = 2 + + ELSE IF ( N == 98 ) THEN + + !--------------------- + ! Psurface - PTOP + !--------------------- + CATEGORY = 'PEDGE-$' + UNIT = 'hPa' + GMNL = 1 + GMTRC = 1 + + ELSE IF ( N == 99 ) THEN + + !--------------------- + ! Temperature + !--------------------- + CATEGORY = 'DAO-3D-$' + UNIT = 'K' + GMNL = ND51_NL + GMTRC = 3 + + ELSE + + ! Otherwise skip + CYCLE + + ENDIF + + !------------------------ + ! Save to bpch file + !------------------------ + CALL BPCH2( IU_ND51, MODELNAME, LONRES, + & LATRES, HALFPOLAR, CENTER180, + & CATEGORY, GMTRC, UNIT, + & TAU0, TAU1, RESERVED, + & ND51_NI, ND51_NJ, GMNL, + & ND51_IMIN+I0, ND51_JMIN+J0, ND51_LMIN, + & REAL( Q(1:ND51_NI, 1:ND51_NJ, 1:GMNL, W) ) ) + ENDDO + + ! Echo info + WRITE( 6, 120 ) TRIM( FILENAME ) + 120 FORMAT( ' - DIAG51d: Closing file ', a ) + + ! Close file + CLOSE( IU_ND51 ) + + !================================================================= + ! Re-initialize quantities for next diagnostic cycle + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 130 ) STAMP + 130 FORMAT( ' - DIAG51d: Zeroing arrays at ', a ) + + ! Set STARTING TAU for the next bpch write + TAU0 = TAU_W + + ! Zero accumulating array for tracer + Q = 0d0 + + ! Zero counter arrays + COUNT_CHEM3D = 0d0 + GOOD_CT = 0d0 + GOOD_CT_CHEM = 0d0 + + ! Return to calling program + END SUBROUTINE WRITE_DIAG51 + +!------------------------------------------------------------------------------ + + FUNCTION GET_I( X ) RESULT( I ) +! +!****************************************************************************** +! Function GET_I returns the absolute longitude index (I), given the +! relative longitude index (X). (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (INTEGER) : Relative longitude index (used by Q) +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: X + + ! Local variables + INTEGER :: I + + !================================================================= + ! GET_I begins here! + !================================================================= + + ! Add the offset to X to get I + I = IOFF + X + + ! Handle wrapping around the date line, if necessary + IF ( I > IIPAR ) I = I - IIPAR + + ! Return to calling program + END FUNCTION GET_I + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG51d( DO_ND51, N_ND51, TRACERS, HR_WRITE, + & HR1, HR2, IMIN, IMAX, + & JMIN, JMAX, LMIN, LMAX, FILE ) +! +!****************************************************************************** +! Subroutine INIT_DIAG51 allocates and zeroes all module arrays. +! It also gets values for module variables from "input_mod.f". +! (bmy, 7/20/04, 1/22/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DO_ND51 (LOGICAL ) : Switch to turn on ND51 timeseries diagnostic +! (2 ) N_ND51 (INTEGER ) : Number of ND51 read by "input_mod.f" +! (3 ) TRACERS (INTEGER ) : Array w/ ND51 tracer #'s read by "input_mod.f" +! (4 ) HR_WRITE (REAL*8 ) : GMT hour of day at which to write bpch file +! (5 ) HR1 (REAL*8 ) : Lower limit of local time averaging bin +! (6 ) HR2 (REAL*8 ) : Upper limit of local time averaging bin +! (7 ) IMIN (INTEGER ) : Min longitude index read by "input_mod.f" +! (8 ) IMAX (INTEGER ) : Max longitude index read by "input_mod.f" +! (9 ) JMIN (INTEGER ) : Min latitude index read by "input_mod.f" +! (10) JMAX (INTEGER ) : Min latitude index read by "input_mod.f" +! (11) LMIN (INTEGER ) : Min level index read by "input_mod.f" +! (12) LMAX (INTEGER ) : Min level index read by "input_mod.f" +! (13) FILE (CHAR*255) : ND51 output file name read by "input_mod.f" +! +! NOTES: +! (1 ) Diagnostic counter arrays are now only 1-D. Also add GOOD_CT_CHEM +! which is the counter array of "good" boxes at each chemistry +! timesteps. Now allocate GOOD_CT_CHEM. (bmy, 10/25/04) +! (2 ) Now get I0 and J0 correctly for nested grid simulations (bmy, 11/9/04) +! (3 ) Now call GET_HALFPOLAR from "bpch2_mod.f" to get the HALFPOLAR flag +! value for GEOS or GCAP grids. (bmy, 6/28/05) +! (4 ) Now allow ND51_IMIN to be equal to ND51_IMAX and ND51_JMIN to be +! equal to ND51_JMAX. This will allow us to save out longitude or +! latitude transects. Allocate COUNT_CHEM3D. (cdh, bmy, phs, 1/24/07) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_MODELNAME, GET_HALFPOLAR + USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, ITS_A_NESTED_GRID + USE TIME_MOD, ONLY : GET_TAUb + USE TRACER_MOD, ONLY : N_TRACERS + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: DO_ND51 + INTEGER, INTENT(IN) :: N_ND51, TRACERS(100) + INTEGER, INTENT(IN) :: IMIN, IMAX + INTEGER, INTENT(IN) :: JMIN, JMAX + INTEGER, INTENT(IN) :: LMIN, LMAX + REAL*8, INTENT(IN) :: HR1, HR2 + REAL*8, INTENT(IN) :: HR_WRITE + CHARACTER(LEN=255), INTENT(IN) :: FILE + + ! Local variables + INTEGER :: AS + CHARACTER(LEN=255) :: LOCATION + + !================================================================= + ! INIT_DIAG51 begins here! + !================================================================= + + ! Initialize + LOCATION = 'INIT_DIAG51d ("diag51_mod.f")' + ND51_TRACERS(:) = 0 + + ! Get values from "input_mod.f" + DO_SAVE_DIAG51d = DO_ND51 + ND51_N_TRACERS = N_ND51 + ND51_TRACERS(1:N_ND51) = TRACERS(1:N_ND51) + ND51_HR_WRITE = HR_WRITE + ND51_HR1 = HR1 + ND51_HR2 = HR2 + ND51_IMIN = IMIN + ND51_IMAX = IMAX + ND51_JMIN = JMIN + ND51_JMAX = JMAX + ND51_LMIN = LMIN + ND51_LMAX = LMAX + ND51_OUTPUT_FILE = TRIM( FILE ) + + ! Make sure ND51_HR_WRITE is in the range 0-23.999 hrs + ND51_HR_WRITE = MOD( ND51_HR_WRITE, 24d0 ) + + ! Exit if ND51 is turned off + IF ( .not. DO_SAVE_DIAG51d ) RETURN + + !================================================================= + ! Error check longitude, latitude, altitude limits + !================================================================= + + ! Get grid offsets + IF ( ITS_A_NESTED_GRID() ) THEN + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + ELSE + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + ENDIF + + !----------- + ! Longitude + !----------- + + ! Error check ND51_IMIN + IF ( ND51_IMIN+I0 < 1 .or. ND51_IMIN+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMIN value!', LOCATION ) + ENDIF + + ! Error check ND51_IMAX + IF ( ND51_IMAX+I0 < 1 .or. ND51_IMAX+I0 > IGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_IMAX value!', LOCATION ) + ENDIF + + ! Compute longitude limits to write to disk + ! Also handle wrapping around the date line + IF ( ND51_IMAX >= ND51_IMIN ) THEN + ND51_NI = ( ND51_IMAX - ND51_IMIN ) + 1 + ELSE + ND51_NI = ( IIPAR - ND51_IMIN ) + 1 + ND51_IMAX + WRITE( 6, '(a)' ) 'We are wrapping over the date line!' + ENDIF + + ! Make sure that ND50_NI <= IIPAR + IF ( ND51_NI > IIPAR ) THEN + CALL ERROR_STOP( 'Too many longitudes!', LOCATION ) + ENDIF + + !----------- + ! Latitude + !----------- + + ! Error check JMIN_AREA + IF ( ND51_JMIN+J0 < 1 .or. ND51_JMIN+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMIN value!', LOCATION ) + ENDIF + + ! Error check JMAX_AREA + IF ( ND51_JMAX+J0 < 1 .or.ND51_JMAX+J0 > JGLOB ) THEN + CALL ERROR_STOP( 'Bad ND51_JMAX value!', LOCATION ) + ENDIF + + ! Compute latitude limits to write to disk (bey, bmy, 3/16/99) + IF ( ND51_JMAX >= ND51_JMIN ) THEN + ND51_NJ = ( ND51_JMAX - ND51_JMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_JMAX < ND51_JMIN!', LOCATION ) + ENDIF + + !----------- + ! Altitude + !----------- + + ! Error check ND51_LMIN, ND51_LMAX + IF ( ND51_LMIN < 1 .or. ND51_LMAX > LLPAR ) THEN + CALL ERROR_STOP( 'Bad ND51 altitude values!', LOCATION ) + ENDIF + + ! # of levels to save in ND51 timeseries + IF ( ND51_LMAX >= ND51_LMIN ) THEN + ND51_NL = ( ND51_LMAX - ND51_LMIN ) + 1 + ELSE + CALL ERROR_STOP( 'ND51_LMAX < ND51_LMIN!', LOCATION ) + ENDIF + + !----------- + ! Offsets + !----------- + IOFF = ND51_IMIN - 1 + JOFF = ND51_JMIN - 1 + LOFF = ND51_LMIN - 1 + + !----------- + ! For bpch + !----------- + TAU0 = GET_TAUb() + TITLE = 'GEOS-CHEM DIAG51 time series' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + + ! Reset offsets to global values for bpch write + I0 = GET_XOFFSET( GLOBAL=.TRUE. ) + J0 = GET_YOFFSET( GLOBAL=.TRUE. ) + + !================================================================= + ! Allocate arrays + !================================================================= + + ! Array denoting where LT is between HR1 and HR2 + ALLOCATE( GOOD( IIPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD' ) + GOOD = 0 + + ! Counter of "good" times per day at each grid box + ALLOCATE( GOOD_CT( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT' ) + GOOD_CT = 0 + + ! Counter of "good" times per day for each chemistry timestep + ALLOCATE( GOOD_CT_CHEM( ND51_NI ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GOOD_CT_CHEM' ) + GOOD_CT_CHEM = 0 + + ! Accumulating array + ALLOCATE( Q( ND51_NI, ND51_NJ, ND51_NL, ND51_N_TRACERS), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'Q' ) + Q = 0d0 + + ! Accumulating array + ALLOCATE( COUNT_CHEM3D( ND51_NI, ND51_NJ, ND51_NL ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'COUNT_CHEM3D' ) + COUNT_CHEM3D = 0 + + ! Return to calling program + END SUBROUTINE INIT_DIAG51d + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG51d +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG51 deallocates all module arrays. +! (bmy, 11/29/00, 1/24/07) +! +! NOTES: +! (1 ) Now deallocate GOOD_CT_CHEM (bmy, 10/25/04) +! (2 ) Also deallocate COUNT_CHEM3D (phs, 1/24/07) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG51 begins here! + !================================================================= + IF ( ALLOCATED( COUNT_CHEM3D ) ) DEALLOCATE( COUNT_CHEM3D ) + IF ( ALLOCATED( GOOD ) ) DEALLOCATE( GOOD ) + IF ( ALLOCATED( GOOD_CT ) ) DEALLOCATE( GOOD_CT ) + IF ( ALLOCATED( GOOD_CT_CHEM ) ) DEALLOCATE( GOOD_CT_CHEM ) + IF ( ALLOCATED( Q ) ) DEALLOCATE( Q ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG51d + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG51d_MOD diff --git a/code/diag56_mod.f b/code/diag56_mod.f new file mode 100644 index 0000000..fe97cb3 --- /dev/null +++ b/code/diag56_mod.f @@ -0,0 +1,222 @@ +! $Id: diag56_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE DIAG56_MOD +! +!****************************************************************************** +! Module DIAG56_MOD contains arrays and routines for archiving the ND56 +! diagnostic -- lightning flash rates. (bmy, 5/11/06, 3/7/07) +! +! Module Variables: +! ============================================================================ +! (1 ) AD56 (REAL*4) : Diagnostic array for lightning flash rates +! +! Module Routines: +! ============================================================================ +! (1 ) ZERO_DIAG56 : Sets all module arrays to zero +! (2 ) WRITE_DIAG56 : Writes data in module arrays to bpch file +! (3 ) INIT_DIAG56 : Allocates all module arrays +! (4 ) CLEANUP_DIAG56 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag03_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary pch file I/O +! (2 ) error_mod.f : Module w/ NaN and other error check routines +! (3 ) file_mod.f : Module w/ file unit numbers and error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) time_mod.f : Module w/ routines to compute date & time +! +! NOTES: +! (1 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (2 ) Now divide AD56 by the # of A-6 timesteps (ltm, bmy, 3/7/07) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag56_mod.f" + !================================================================= + + ! Make everything PUBLIC + PUBLIC + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + INTEGER :: ND56 + INTEGER, PARAMETER :: PD56 = 3 + + ! Arrays + REAL*4, ALLOCATABLE :: AD56(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE ZERO_DIAG56 +! +!****************************************************************************** +! Subroutine ZERO_DIAG03 zeroes the ND03 diagnostic arrays. +! (bmy, 5/11/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! ZERO_DIAG56 begins here! + !================================================================= + + ! Exit if ND56 is turned off + IF ( ND56 == 0 ) RETURN + + ! Zero arrays + AD56(:,:,:) = 0e0 + + ! Return to calling program + END SUBROUTINE ZERO_DIAG56 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG56 +! +!****************************************************************************** +! Subroutine WRITE_DIAG56 writes the ND03 diagnostic arrays to the binary +! punch file at the proper time. (bmy, 5/11/06, 3/7/06) +! +! # : Field : Description : Units : Scale factor +! -------------------------------------------------------------------------- +! (1 ) LFLASH-$ : Lightning flash rate : flashes/min/km2 : SCALE_A6 +! (2 ) LFLASH-$ : Intra-cloud flash rate : flashes/min/km2 : SCALE_A6 +! (3 ) LFLASH-$ : Cloud-ground flash rate : flashes/min/km2 : SCALE_A6 +! +! NOTES: +! (1 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (2 ) Now scale AD56 by the # of A-6 timesteps (ltm, bmy, 3/7/07) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_MODELNAME, GET_HALFPOLAR + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : GET_CT_A6, GET_DIAGb, GET_DIAGe + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! TINDEX + + ! Local variables + INTEGER :: CENTER180, HALFPOLAR, IFIRST + INTEGER :: JFIRST, LFIRST, M, N + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*4 :: LONRES, LATRES + REAL*8 :: DIAGb, DIAGe, SCALE + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY, RESERVED, UNIT + + !================================================================= + ! WRITE_DIAG56 begins here! + !================================================================= + + ! Exit if ND03 is turned off + IF ( ND56 == 0 ) RETURN + + ! Initialize + CENTER180 = 1 + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + HALFPOLAR = GET_HALFPOLAR() + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LATRES = DJSIZE + LFIRST = 1 + LONRES = DISIZE + MODELNAME = GET_MODELNAME() + RESERVED = '' + SCALE = DBLE( GET_CT_A6() ) + 1d-32 + + !================================================================= + ! Write data to the bpch file + !================================================================= + + ! Loop over ND03 diagnostic tracers + DO M = 1, TMAX(56) + + ! Define quantities + N = TINDEX(56,M) + CATEGORY = 'LFLASH-$' + UNIT = 'flashes/min/km2' + ARRAY(:,:,1) = AD56(:,:,N) / SCALE + + ! Write data to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, 1, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1) ) + ENDDO + + ! Return to calling program + END SUBROUTINE WRITE_DIAG56 + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG56 +! +!****************************************************************************** +! Subroutine INIT_DIAG56 allocates all module arrays (bmy, 5/11/06) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DIAG03 begins here! + !================================================================= + + ! Exit if ND56 is turned off + IF ( ND56 == 0 ) RETURN + + ! 2-D array ("LFLASH-$") + ALLOCATE( AD56( IIPAR, JJPAR, PD56 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD56' ) + + ! Zero arrays + CALL ZERO_DIAG56 + + ! Return to calling program + END SUBROUTINE INIT_DIAG56 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG56 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG56 deallocates all module arrays (bmy, 5/11/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG56 begins here! + !================================================================= + IF ( ALLOCATED( AD56 ) ) DEALLOCATE( AD56 ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG56 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG56_MOD diff --git a/code/diag59_mod.f b/code/diag59_mod.f new file mode 100644 index 0000000..cce7280 --- /dev/null +++ b/code/diag59_mod.f @@ -0,0 +1,373 @@ +! $Id: diag59_mod.f,v 1.1 2011/02/23 00:08:47 daven Exp $ + MODULE DIAG59_MOD +! +!****************************************************************************** +! Module DIAG59_MOD contains arrays and routines for archiving the ND59 +! diagnostic -- concentrations of NH3 [ug/m3]. (lz,10/07/10) +! +! Module Variables: +! ============================================================================ +! (1 ) AD59 (REAL*4) : Array for NH3 concentrations [ug/m3] +! +! Module Routines: +! ============================================================================ +! (1 ) DIAG59 : Archives quantities for diagnostic +! (2 ) ZERO_DIAG59 : Sets all module arrays to zero +! (3 ) WRITE_DIAG59 : Writes data in module arrays to bpch file +! (4 ) INIT_DIAG59 : Allocates all module arrays +! (5 ) CLEANUP_DIAG59 : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag03_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary pch file I/O +! (2 ) error_mod.f : Module w/ NaN and other error check routines +! (3 ) file_mod.f : Module w/ file unit numbers and error checks +! (4 ) grid_mod.f : Module w/ horizontal grid information +! (5 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (6 ) time_mod.f : Module w/ routines to compute date & time +! +! NOTES: +! (1 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag59_mod.f" + !================================================================= + + ! Make everything PUBLIC + PUBLIC + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + INTEGER :: ND59, LD59 + + ! Parameters + INTEGER, PARAMETER :: PD59 = 10 + + ! Arrays + REAL*4, ALLOCATABLE :: AD59(:,:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG59 +! +!****************************************************************************** +! Subroutine DIAG59 archives NH3 concentrations [ug/m3] for the ND59 +! diagnostic. (lz,10/07/10) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : AIRVOL, T + !USE DIAG_MOD, ONLY : LTOTH + USE PRESSURE_MOD, ONLY : GET_PCENTER + USE TRACER_MOD, ONLY : STT + USE TRACERID_MOD, ONLY : IDTNH3 + USE TRACERID_MOD, ONLY : IDTNH4 + USE TRACERID_MOD, ONLY : IDTNIT + USE TRACERID_MOD, ONLY : IDTSO4 + USE TRACERID_MOD, ONLY : IDTBCPI,IDTBCPO + USE TRACERID_MOD, ONLY : IDTOCPI,IDTOCPO + USE TRACERID_MOD, ONLY : IDTDST1,IDTDST2 + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! NDxx flags + + ! Local variables + INTEGER :: I, J, L + REAL*8 :: FACTOR, PRES + + ! Factor for computing standard volume + REAL*8, PARAMETER :: STD_VOL_FAC = 1013.25d0 / 273.15d0 + + !================================================================= + ! DIAG59 begins here! + !================================================================= + + ! Error check + IF ( IDTNH3 == 0 ) RETURN + IF ( IDTNH4 == 0 ) RETURN + IF ( IDTNIT == 0 ) RETURN + IF ( IDTSO4 == 0 ) RETURN + IF ( IDTBCPI == 0 ) RETURN + IF ( IDTBCPO == 0 ) RETURN + IF ( IDTOCPI == 0 ) RETURN + IF ( IDTOCPO == 0 ) RETURN + IF ( IDTDST1 == 0 ) RETURN + IF ( IDTDST2 == 0 ) RETURN + + ! Loop over grid boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, FACTOR, PRES ) + DO L = 1, LD59 + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Conversion factor from [kg] --> [ug/m3] + ! (LTOTH=1 if between OTH_HR1 and OTH_HR2, LTOTH=0 otherwise) + !FACTOR = 1d9 / AIRVOL(I,J,L) * LTOTH(I,J) + + ! Conversion factor from [kg] --> [ug/m3] + FACTOR = 1d9 / AIRVOL(I,J,L) + + ! NH3 [ug/m3] + AD59(I,J,L,1) = AD59(I,J,L,1) + + & ( STT(I,J,L,IDTNH3) * FACTOR) + + ! NH4 [ug/m3] + AD59(I,J,L,2) = AD59(I,J,L,2) + + & ( STT(I,J,L,IDTNH4) * FACTOR) + + ! NIT [ug/m3] + AD59(I,J,L,3) = AD59(I,J,L,3) + + & ( STT(I,J,L,IDTNIT) * FACTOR) + + ! SO4 [ug/m3] + AD59(I,J,L,4) = AD59(I,J,L,4) + + & ( STT(I,J,L,IDTSO4) * FACTOR) + + ! BCPI [ug/m3] + AD59(I,J,L,5) = AD59(I,J,L,5) + + & ( STT(I,J,L,IDTBCPI) * FACTOR) + + ! BCPO [ug/m3] + AD59(I,J,L,6) = AD59(I,J,L,6) + + & ( STT(I,J,L,IDTBCPO) * FACTOR) + + ! OCPI [ug/m3] + AD59(I,J,L,7) = AD59(I,J,L,7) + + & ( STT(I,J,L,IDTOCPI) * FACTOR) + & * 1.4d0 + + ! OCPO [ug/m3] + AD59(I,J,L,8) = AD59(I,J,L,8) + + & ( STT(I,J,L,IDTOCPO) * FACTOR) + & * 1.40d0 + + ! DST1 [ug/m3] + AD59(I,J,L,9) = AD59(I,J,L,9) + + & ( STT(I,J,L,IDTDST1) * FACTOR) + + + ! DST2 [ug/m3] + AD59(I,J,L,10) = AD59(I,J,L,10) + + & ( STT(I,J,L,IDTDST2) * FACTOR) + & * 0.38d0 + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DIAG59 + +!------------------------------------------------------------------------------ + + SUBROUTINE ZERO_DIAG59 +! +!****************************************************************************** +! Subroutine ZERO_DIAG59 zeroes the ND03 diagnostic arrays. +! (dkh, bmy, 5/22/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! ZERO_DIAG59 begins here! + !================================================================= + + ! Exit if ND59 is turned off + IF ( ND59 == 0 ) RETURN + + ! Zero arrays + AD59(:,:,:,:) = 0e0 + + ! Return to calling program + END SUBROUTINE ZERO_DIAG59 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE_DIAG59 +! +!****************************************************************************** +! Subroutine WRITE_DIAG03 writes the ND03 diagnostic arrays to the binary +! punch file at the proper time. (bmy, 5/22/06, 9/5/06) +! +! # : Field : Description : Units : Scale factor +! ----------------------------------------------------------------------- +! (1 ) IJ-ugm3 : NH3 : ug/m3 : SCALE_OTH +! (2 ) IJ-ugm3 : NH4 : ug/m3 : SCALE_OTH +! (3 ) IJ-ugm3 : NIT : ug/m3 : SCALE_OTH +! (4 ) IJ-ugm3 : SO4 : ug/m3 : SCALE_OTH +! (5 ) IJ-ugm3 : BCPI : ug/m3 : SCALE_OTH +! (6 ) IJ-ugm3 : BCPO : ug/m3 : SCALE_OTH +! +! NOTES: +! (1 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_MODELNAME, GET_HALFPOLAR + !USE DIAG_MOD, ONLY : CTOTH + USE FILE_MOD, ONLY : IU_BPCH + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE TIME_MOD, ONLY : GET_CT_DYN, GET_DIAGb, GET_DIAGe + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! TINDEX + + ! Local variables + INTEGER :: CENTER180, HALFPOLAR + INTEGER :: L, M, N + INTEGER :: IFIRST, JFIRST, LFIRST + REAL*4 :: LONRES, LATRES + REAL*4 :: ARRAY(IIPAR,JJPAR,LLPAR) + !REAL*8 :: SCALE(IIPAR,JJPAR) + REAL*8 :: SCALE + REAL*8 :: DIAGb, DIAGe + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: RESERVED + CHARACTER(LEN=40) :: UNIT + + !================================================================= + ! WRITE_DIAG59 begins here! + !================================================================= + + ! Exit if ND03 is turned off + IF ( ND59 == 0 ) RETURN + + ! Initialize + CENTER180 = 1 + DIAGb = GET_DIAGb() + DIAGe = GET_DIAGe() + HALFPOLAR = GET_HALFPOLAR() + IFIRST = GET_XOFFSET( GLOBAL=.TRUE. ) + 1 + JFIRST = GET_YOFFSET( GLOBAL=.TRUE. ) + 1 + LATRES = DJSIZE + LFIRST = 1 + LONRES = DISIZE + MODELNAME = GET_MODELNAME() + RESERVED = '' + !SCALE = FLOAT( CTOTH ) + TINY( 1d0 ) + !SCALE = DBLE( GET_CT_DYN() ) + TINY( 1d0 ) + SCALE = DBLE( GET_CT_DYN() ) + TINY( 1e0 ) + + !================================================================= + ! Write data to the bpch file + !================================================================= + + ! debug + !print*, ' LD59 = ', LD59 + !print*, ' some values of AD59 = ', AD59(20,20,:,:) + + ! Loop over ND03 diagnostic tracers + DO M = 1, TMAX(59) + + ! Define quantities + N = TINDEX(59,M) + CATEGORY = 'IJ-ugm3' + UNIT ='ug/m3' + + IF ( N == 0 ) CYCLE + + ! Apply scale factor + DO L = 1, LD59 + ARRAY(:,:,L) = AD59(:,:,L,N) / SCALE + ENDDO + + ! Write data to disk + CALL BPCH2( IU_BPCH, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, N, + & UNIT, DIAGb, DIAGe, RESERVED, + & IIPAR, JJPAR, LD59, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD59) ) + ENDDO + + ! Return to calling program + END SUBROUTINE WRITE_DIAG59 + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG59 +! +!****************************************************************************** +! Subroutine INIT_DIAG59 allocates all module arrays (bmy, 5/22/06) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LSOA + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DIAG42 begins here! + !================================================================= + + ! Turn off ND59 if NH3 tracers are not used +! IF ( .not. LNH3 ) THEN +! ND59 = 0 +! RETURN +! ENDIF + +! ! debug +! print*, ' check ND59 = ', ND59 + + ! Exit if ND59 is turned off + IF ( ND59 == 0 ) RETURN + + ! Number of levels to save for this diagnostic + LD59 = MIN( ND59, LLPAR ) + + ! 2-D array ("LFLASH-$") + ALLOCATE( AD59( IIPAR, JJPAR, LD59, PD59 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD59' ) + + ! Zero arrays + CALL ZERO_DIAG59 + + ! Return to calling program + END SUBROUTINE INIT_DIAG59 + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG59 +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG59 deallocates all module arrays (bmy, 5/22/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG59 begins here! + !================================================================= + IF ( ALLOCATED( AD59 ) ) DEALLOCATE( AD59 ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG59 + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG59_MOD diff --git a/code/diag_2pm.f b/code/diag_2pm.f new file mode 100644 index 0000000..91b6d10 --- /dev/null +++ b/code/diag_2pm.f @@ -0,0 +1,181 @@ +! $Id: diag_2pm.f,v 1.2 2010/05/07 20:39:47 daven Exp $ + SUBROUTINE DIAG_2PM +! +!***************************************************************************** +! Subroutine DIAG_2PM (bmy, 3/26/99, 11/18/08) constructs the diagnostic +! flag arrays : +! LTJV : J-values (ND22) +! LTOH : OH concentrations (ND43) +! LTNO : NO concentrations (ND43) +! LTNO2 : NO2 concentrations (ND43) +! LTHO2 : HO2 concentrations (ND43) +! LTOTH : used for tracers (ND45) +! +! These arrays are either 1 (if it is within a certain time interval) +! or 0 (if it is not within a certain time interval). The limits of +! the time intervals for CTOTH and CTJV are now defined in input.geos +! The arrays CTOTH, CTOH, CTNO, CTJV count the number of times the +! diagnostics are accumulated for each grid box (i.e LTOTH is 1) +! +! NOTES: +! (1 ) Now use F90 syntax (bmy, 3/26/99) +! (2 ) Now reference LTNO2, CTNO2, LTHO2, CTHO2 arrays from "diag_mod.f". +! Updated comments, cosmetic changes. (rvm, bmy, 2/27/02) +! (3 ) Now removed NMIN from the arg list. Now use functions GET_LOCALTIME, +! ITS_TIME_FOR_CHEM, ITS_TIME_FOR_DYN from "time_mod.f" (bmy, 2/11/03) +! (4 ) Now rewritten using a parallel DO-loop (bmy, 7/20/04) +! (5 ) Now account for the time spent in the troposphere for ND43 and ND45 +! pure O3. Now only accumulate counter for 3D pure O3 in ND45 if +! it's a chemistry timestep. (phs, 1/24/07) +! (6 ) Added 3D counter for ND65 and 03 in ND47 (phs, 11/17/08) +!***************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : LTJV, CTJV, LTNO, CTNO, CTO3 + USE DIAG_MOD, ONLY : LTOH, CTOH, LTOTH, CTOTH, LTNO2 + USE DIAG_MOD, ONLY : CTNO2, LTHO2, CTHO2, LTNO3, CTNO3 + USE DIAG_MOD, ONLY : CTO3_24h + USE TIME_MOD, ONLY : GET_LOCALTIME + USE TIME_MOD, ONLY : ITS_TIME_FOR_DYN, ITS_TIME_FOR_CHEM + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! HR_OH1, HR_OH2, etc. + + ! Local variables + LOGICAL :: IS_ND22, IS_ND43, IS_ND45, IS_ND45_O3 + LOGICAL :: IS_ND47, IS_ND65 + INTEGER :: I, J, L + REAL*8 :: LT(IIPAR) + + !================================================================= + ! DIAG_2PM begins here! + !================================================================= + + ! Set logical flags + IS_ND22 = ( ND22 > 0 .and. ITS_TIME_FOR_CHEM() ) + IS_ND45_O3 = ( ITS_TIME_FOR_CHEM() ) + IS_ND45 = ( ND45 > 0 .and. ITS_TIME_FOR_DYN() ) + IS_ND43 = ( ND43 > 0 .and. ITS_TIME_FOR_CHEM() ) + IS_ND47 = ( ND47 > 0 ) + IS_ND65 = ( ND65 > 0 ) + + ! Pre-compute local time + DO I = 1, IIPAR + LT(I) = GET_LOCALTIME( I ) + ENDDO + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + !----------------------------- + ! ND45 -- mixing ratios + !----------------------------- + IF ( IS_ND45 ) THEN + + ! Archive if we fall w/in the local time limits + IF ( LT(I) >= HR1_OTH .and. LT(I) <= HR2_OTH ) THEN + LTOTH(I,J) = 1 + CTOTH(I,J) = CTOTH(I,J) + 1 + + ! Counter for # of O3 boxes in the troposphere (phs, 1/24/07) + DO L = 1, LD45 + IF ( IS_ND45_O3 .and. ITS_IN_THE_TROP( I, J, L )) THEN + CTO3(I,J,L) = CTO3(I,J,L) + 1 + ENDIF + ENDDO + + ELSE + LTOTH(I,J) = 0 + ENDIF + ENDIF + + !----------------------------- + ! ND47_O3 / ND65 -- "chemistry all day long" counter + !----------------------------- + IF ( IS_ND47 .OR. IS_ND65 ) THEN + + ! Counter for # of O3 boxes in the troposphere (phs, 11/17/08) + DO L = 1, MAX( LD47, LD65 ) + !IF ( IS_ND45_O3 .and. ITS_IN_THE_TROP( I, J, L )) THEN + ! dbj changed for strat. archive + IF ( IS_ND45_O3 ) THEN + CTO3_24h(I,J,L) = CTO3_24h(I,J,L) + 1 + ENDIF + ENDDO + + ENDIF + + !----------------------------- + ! ND22 -- J-Value diagnostic + !----------------------------- + IF ( IS_ND22 ) THEN + + ! Archive if we fall w/in the local time limits + IF ( LT(I) >= HR1_JV .and. LT(I) <= HR2_JV ) THEN + LTJV(I,J) = 1 + CTJV(I,J) = CTJV(I,J) + 1 + ELSE + LTJV(I,J) = 0 + ENDIF + ENDIF + + !----------------------------- + ! ND43 -- OH, NO, NO2, HO2 + !----------------------------- + IF ( IS_ND43 ) THEN + + ! LTNO denotes where LT is between HR1_NO and HR2_NO + ! CTNO counts the times when LT was between HR1_NO and HR2_NO + ! Now set LTNO2, CTNO2 based on the NO times (rvm, bmy, 2/27/02) + IF ( LT(I) >= HR1_NO .and. LT(I) <= HR2_NO ) THEN + LTNO(I,J) = 1 + LTNO2(I,J) = 1 + + ! Counters for # of NO, NO2 boxes in the trop (phs, 1/24/07) + DO L = 1, LD43 + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + CTNO(I,J,L) = CTNO(I,J,L) + 1 + CTNO2(I,J,L) = CTNO2(I,J,L) + 1 + ENDIF + ENDDO + + ELSE + LTNO(I,J) = 0 + LTNO2(I,J) = 0 + ENDIF + + ! LTNO denotes where LT is between HR1_OH and HR2_OH + ! CTNO counts the times when LT was between HR1_OH and HR2_OH + ! Now set LTHO2, CTHO2 based on the OH times (rvm, bmy, 2/27/02) + IF ( LT(I) >= HR1_OH .and. LT(I) <= HR2_OH ) THEN + LTOH(I,J) = 1 + LTHO2(I,J) = 1 + LTNO3(I,J) = 1 + + ! Counters for # of OH,HO2,NO3 boxes in the trop (phs, 1/24/07) + DO L = 1, LD43 + IF ( ITS_IN_THE_TROP( I, J, L ) ) THEN + CTOH(I,J,L) = CTOH(I,J,L) + 1 + CTHO2(I,J,L) = CTHO2(I,J,L) + 1 + CTNO3(I,J,L) = CTNO3(I,J,L) + 1 + ENDIF + ENDDO + + ELSE + LTOH(I,J) = 0 + LTHO2(I,J) = 0 + LTNO3(I,J) = 0 + ENDIF + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DIAG_2PM diff --git a/code/diag_mod.f b/code/diag_mod.f new file mode 100644 index 0000000..350369f --- /dev/null +++ b/code/diag_mod.f @@ -0,0 +1,422 @@ +! $Id: diag_mod.f,v 1.2 2012/03/01 22:00:26 daven Exp $ + MODULE DIAG_MOD +! +!****************************************************************************** +! Module DIAG_MOD contains declarations for allocatable arrays for use with +! GEOS-CHEM diagnostics. (amf, bdf, bmy, 11/30/99, 11/18/08) +! +! Module Routines: +! ============================================================================ +! (1 ) CLEANUP_DIAG : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by diag_mod.f +! ============================================================================ +! none +! +! NOTES: +! (1 ) DIAG_MOD is written in Fixed-Format F90. +! (2 ) Call subroutine CLEANUP at the end of the MAIN program to deallocate +! the memory before the run stops. It is always good style to free +! any memory we have dynamically allocated when we don't need it +! anymoren +! (3 ) Added ND13 arrays for sulfur emissions (bmy, 6/6/00) +! (4 ) Moved ND51 arrays to "diag51_mod.f" (bmy, 11/29/00) +! (5 ) Added AD34 array for biofuel burning emissions (bmy, 3/15/01) +! (6 ) Eliminated old commented-out code (bmy, 4/20/01) +! (7 ) Added AD12 array for boundary layer emissions in routine "setemis.f". +! (bdf, bmy, 6/15/01) +! (8 ) Added CHEML24, DRYDL24, CTCHDD for archiving daily mean chemical +! and drydep loss in chemo3 and chemo3.f (amf, bmy, 7/2/01) +! (9 ) Add ND43 arrays LTNO2, CTNO2, LTHO2, CTHO2 (rvm, bmy, 2/27/02) +! (10) Add AD01, AD02 arrays for Rn-Pb-Be simulation (hyl, bmy, 8/7/02) +! (11) Add AD05 array for sulfate P-L diagnostic (rjp, bdf, bmy, 9/20/02) +! (12) Added subroutine CLEANUP_DIAG...moved code here from "cleanup.f", +! so that it is internal to "diag_mod.f". Added arrays AD13_NH3_bb, +! AD13_NH3_bf, AD13_NH3_an for NH3 emissons in ND13. Deleted obsolete +! allocatable arrays CHEML24, DRYDL24, CTCHDD. Now also added LTNO3 +! and CTNO3 arrays for ND43 diagnostic. Added AD13_SO2_bf array for +! SO2 biofuel. (bmy, 1/16/03) +! (13) Added array AD13_NH3_na for ND13 diagnostic (rjp, bmy, 3/23/03) +! (14) Removed P24H and L24H -- these are now defined w/in "tagged_ox_mod.f" +! Also added AD03 array for Kr85 prod/loss diag. (jsw, bmy, 8/20/03) +! (15) Added ND06 (dust emission) and ND07 (carbon aerosol emission) +! diagnostic arrays (rjp, tdf, bmy, 4/5/04) +! (16) Added AD13_SO2_sh diagnostic array for ND13 (bec, bmy, 5/20/04) +! (17) Added AD07_HC diagnostic array for ND07 (rjp, bmy, 7/13/04) +! (18) Moved AD65 & FAMPL to "diag65_mod.f" (bmy, 7/20/04) +! (19) Added array AD13_SO4_bf (bmy, 11/17/04)! +! (20) Added extra arrays for ND03 mercury diagnostics (eck, bmy, 12/7/04) +! (21) Added extra ND21 array for crystalline sulfur tracers. Also remove +! ND03 and ND48 arrays; they are obsolete (bmy, 1/21/05) +! (22) Removed AD41 and AFTTOT arrays; they're obsolete (bmy, 2/17/05) +! (23) Added AD09, AD09_em arrays for HCN/CH3CN simulation (xyp, bmy, 6/27/05) +! (24) Added AD30 array for land/water/ice output (bmy, 8/18/05) +! (25) Added AD54 array for time spend in the troposphere (phs, 9/22/06) +! (26) Added CTO3 counter. Convert ND43 counter arrays from 2D to 3D, for +! the variable tropopause. (phs, 1/19/07) +! (27) Added AD10 and AD10em arrays for ND10 H2-HD-sim diag (phs, 9/18/07) +! (28) Added CTO3_24h to account for time in the troposphere for O3 in +! ND47 (phs, 11/17/08) +! (29) Added AD52 for Gamma HO2 diagnostic. (jaegle, ccc, 2/26/09) +! (30) Updated to save out GLYX production of SOAG in ND07. +! (tmf, 3/6/09) +!****************************************************************************** +! + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! For ND01 -- Rn, Pb, Be emissions + REAL*4, ALLOCATABLE :: AD01(:,:,:,:) + + ! For ND02 -- Rn, Pb, Be decay + REAL*4, ALLOCATABLE :: AD02(:,:,:,:) + + !-------------------------------------------- + !! For ND03 -- Kr85 prod/loss + !REAL*4, ALLOCATABLE :: AD03(:,:,:,:) + !-------------------------------------------- + + ! For ND05 -- Sulfate prod/loss diagnostics + REAL*4, ALLOCATABLE :: AD05(:,:,:,:) + + ! For ND06 -- Dust aerosol emission + REAL*4, ALLOCATABLE :: AD06(:,:,:) + + ! For ND07 -- Carbon aerosol emission + REAL*4, ALLOCATABLE :: AD07(:,:,:) + REAL*4, ALLOCATABLE :: AD07_BC(:,:,:) + REAL*4, ALLOCATABLE :: AD07_OC(:,:,:) + REAL*4, ALLOCATABLE :: AD07_HC(:,:,:,:) + REAL*4, ALLOCATABLE :: AD07_SOAGM(:,:,:,:) + + ! For ND08 -- seasalt emission + REAL*4, ALLOCATABLE :: AD08(:,:,:) + + ! For ND09 -- HCN / CH3CN simulation + REAL*4, ALLOCATABLE :: AD09(:,:,:,:) + REAL*4, ALLOCATABLE :: AD09_em(:,:,:) + + ! For ND10 -- H2/HD prod, loss, & emiss diagnostics + REAL*4, ALLOCATABLE :: AD10(:,:,:,:) + REAL*4, ALLOCATABLE :: AD10em(:,:,:) + + ! For ND12 -- boundary layer multiplication factor + REAL*4, ALLOCATABLE :: AD11(:,:,:) + + ! For ND12 -- boundary layer multiplication factor + REAL*4, ALLOCATABLE :: AD12(:,:,:) + + ! For ND13 -- Sulfur emissions + REAL*4, ALLOCATABLE :: AD13_DMS(:,:) + REAL*4, ALLOCATABLE :: AD13_SO2_ac(:,:,:) + REAL*4, ALLOCATABLE :: AD13_SO2_an(:,:,:) + REAL*4, ALLOCATABLE :: AD13_SO2_bb(:,:) + REAL*4, ALLOCATABLE :: AD13_SO2_bf(:,:) + REAL*4, ALLOCATABLE :: AD13_SO2_nv(:,:,:) + REAL*4, ALLOCATABLE :: AD13_SO2_ev(:,:,:) + REAL*4, ALLOCATABLE :: AD13_SO2_sh(:,:) + REAL*4, ALLOCATABLE :: AD13_SO4_an(:,:,:) + REAL*4, ALLOCATABLE :: AD13_SO4_bf(:,:) + REAL*4, ALLOCATABLE :: AD13_NH3_an(:,:) + REAL*4, ALLOCATABLE :: AD13_NH3_na(:,:) + REAL*4, ALLOCATABLE :: AD13_NH3_bb(:,:) + REAL*4, ALLOCATABLE :: AD13_NH3_bf(:,:) + + ! For ND14 -- wet convection mass flux diagnostic + REAL*8, ALLOCATABLE :: CONVFLUP(:,:,:,:) + + ! For ND15 -- BL mixing mass flux diagnostic + REAL*8, ALLOCATABLE :: TURBFLUP(:,:,:,:) + + ! For ND16 -- Fraction of grid box that is precipitating + REAL*4, ALLOCATABLE :: AD16(:,:,:,:) + INTEGER, ALLOCATABLE :: CT16(:,:,:,:) + + ! For ND17 -- Fraction of tracer lost to rainout + REAL*4, ALLOCATABLE :: AD17(:,:,:,:,:) + INTEGER, ALLOCATABLE :: CT17(:,:,:,:) + + ! For ND18 -- Fraction of tracer lost to washout + REAL*4, ALLOCATABLE :: AD18(:,:,:,:,:) + INTEGER, ALLOCATABLE :: CT18(:,:,:,:) + + ! For ND21 -- Optical Depth diagnostic + REAL*4, ALLOCATABLE :: AD21(:,:,:,:) + REAL*4, ALLOCATABLE :: AD21_cr(:,:,:) + + ! For ND22 -- J-value diagnostic + REAL*4, ALLOCATABLE :: AD22(:,:,:,:) + INTEGER, ALLOCATABLE :: LTJV(:,:) + INTEGER, ALLOCATABLE :: CTJV(:,:) + + ! For ND23 -- CH3CCl3 lifetime diagnostic + REAL*8, ALLOCATABLE :: DIAGCHLORO(:,:,:,:) + + ! For ND24 -- E/W transport mass flux diagnostic + REAL*8, ALLOCATABLE :: MASSFLEW(:,:,:,:) + + ! For ND25 -- N/S transport mass flux diagnostic + REAL*8, ALLOCATABLE :: MASSFLNS(:,:,:,:) + + ! For ND26 -- UP/DOWN transport mass flux diagnostic + REAL*8, ALLOCATABLE :: MASSFLUP(:,:,:,:) + + ! For ND28 -- Biomass burning diagnostic + REAL*4, ALLOCATABLE :: AD28(:,:,:) + + ! For ND29 -- CO source diagnostic + REAL*4, ALLOCATABLE :: AD29(:,:,:) + + ! For ND30 -- land / water / ice flags + REAL*4, ALLOCATABLE :: AD30(:,:) + + ! For ND31 -- surface pressures + REAL*4, ALLOCATABLE :: AD31(:,:,:) + + ! For ND32 -- NOx sources + REAL*4, ALLOCATABLE :: AD32_ac(:,:,:) + REAL*4, ALLOCATABLE :: AD32_an(:,:,:) + REAL*4, ALLOCATABLE :: AD32_bb(:,:) + REAL*4, ALLOCATABLE :: AD32_bf(:,:) + REAL*4, ALLOCATABLE :: AD32_fe(:,:) + REAL*4, ALLOCATABLE :: AD32_li(:,:,:) + REAL*4, ALLOCATABLE :: AD32_so(:,:) + REAL*4, ALLOCATABLE :: AD32_ub(:,:) + REAL*4, ALLOCATABLE :: AD32_SHIP(:,:) + INTEGER, ALLOCATABLE :: AD32_SHIP_COUNT + + ! For ND33 -- tropopsheric sum of tracer + REAL*4, ALLOCATABLE :: AD33(:,:,:) + + ! For ND34 -- biofuel emissions + REAL*4, ALLOCATABLE :: AD34(:,:,:) + + ! For ND35 -- 500 mb tracer + REAL*4, ALLOCATABLE :: AD35(:,:,:) + + ! For ND36 -- Anthropogenic source diagnostic + REAL*4, ALLOCATABLE :: AD36(:,:,:) + REAL*4, ALLOCATABLE :: AD36_SHIP(:,:,:) + INTEGER, ALLOCATABLE :: AD36_SHIP_COUNT + REAL*4, ALLOCATABLE :: EMISS_ANTHR(:,:,:) + + ! For ND37 -- Fraction of tracer scavenged in cloud updrafts + REAL*4, ALLOCATABLE :: AD37(:,:,:,:) + + ! For ND38 -- Rainout in moist convection diagnostic + REAL*4, ALLOCATABLE :: AD38(:,:,:,:) + + ! For ND39 -- Washout in aerosol wet deposition diagnostic + REAL*4, ALLOCATABLE :: AD39(:,:,:,:) + + ! For ND43 -- OH, NO, NO2, HO2 chemical diagnostics + REAL*4, ALLOCATABLE :: AD43(:,:,:,:) + INTEGER, ALLOCATABLE :: LTNO(:,:) + INTEGER, ALLOCATABLE :: CTNO(:,:,:) + INTEGER, ALLOCATABLE :: LTOH(:,:) + INTEGER, ALLOCATABLE :: CTOH(:,:,:) + INTEGER, ALLOCATABLE :: LTNO2(:,:) + INTEGER, ALLOCATABLE :: CTNO2(:,:,:) + INTEGER, ALLOCATABLE :: LTHO2(:,:) + INTEGER, ALLOCATABLE :: CTHO2(:,:,:) + INTEGER, ALLOCATABLE :: LTNO3(:,:) + INTEGER, ALLOCATABLE :: CTNO3(:,:,:) + + ! For ND44 -- Dry deposition fluxes & velocities + REAL*4, ALLOCATABLE :: AD44(:,:,:,:) + + ! For ND45 -- Tracer concentration diagnostic + REAL*4, ALLOCATABLE :: AD45(:,:,:,:) + INTEGER, ALLOCATABLE :: LTOTH(:,:) + INTEGER, ALLOCATABLE :: CTOTH(:,:) + INTEGER, ALLOCATABLE :: CTO3(:,:,:) + + ! For ND46 -- Tracer concentration diagnostic + REAL*4, ALLOCATABLE :: AD46(:,:,:) + + ! For ND47 -- 24-h tracer concentration diagnostic + REAL*4, ALLOCATABLE :: AD47(:,:,:,:) + + ! For ND47(O3) / ND65 -- 24-h tracer diagnostic + INTEGER, ALLOCATABLE :: CTO3_24h(:,:,:) + + ! Dynamically allocatable array -- local only to DIAG50.F + REAL*8, ALLOCATABLE :: STT_TEMPO2(:,:,:,:) + + ! For ND52 -- gamma HO2 diagnostic + REAL*4, ALLOCATABLE :: AD52(:,:,:) + + ! For ND54 -- tropopause diagnostics + REAL*4, ALLOCATABLE :: AD54(:,:,:) + + ! For ND55 -- tropopause diagnostics + REAL*4, ALLOCATABLE :: AD55(:,:,:) + + ! -- for methane simulation diagnostics + ! (kjw, dkh, 02/12/12, adj32_023) + REAL*4, ALLOCATABLE :: AD19(:,:,:) + REAL*4, ALLOCATABLE :: AD58(:,:,:) + REAL*4, ALLOCATABLE :: AD60(:,:) + + ! For ND63 -- fraction of NOx remaining and Integrated OPE + REAL*4, ALLOCATABLE :: AD63(:,:,:) + INTEGER, ALLOCATABLE :: AD63_COUNT + + ! For ND66 -- I-6 fields diagnostic + REAL*4, ALLOCATABLE :: AD66(:,:,:,:) + + ! For ND67 -- DAO surface fields diagnostic + REAL*4, ALLOCATABLE :: AD67(:,:,:) + + ! For ND68 -- BXHEIGHT, AD, AVGW diagnostic + REAL*4, ALLOCATABLE :: AD68(:,:,:,:) + + ! For ND69 -- DXYP diagnostic + REAL*4, ALLOCATABLE :: AD69(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG deallocates all module arrays. +! (bmy, 12/13/02, 9/18/07) +! +! NOTES: +! (1 ) Now also deallocate AD13_NH3_an, AD13_NH3_bb, AD13_NH3_bf arrays +! for the ND13 diagnostic. (bmy, 12/13/02) +! (2 ) Now also deallocate AD13_NH3_na array for ND13 (rjp, bmy, 3/23/03) +! (3 ) Removed P24H and L24H, these are now defined within "tagged_ox_mod.f". +! Now also deallocate AD03 array for Kr85 prod/loss (jsw, bmy, 8/20/03) +! (4 ) Now also deallocate AD06 and AD07* arrays (rjp, bdf, bmy, 4/5/04) +! (5 ) Now also deallocate AD08 array (rjp, bec, bmy, 4/20/04) +! (6 ) Now also deallocaes AD13_SO2_sh array (bec, bmy, 5/20/04) +! (7 ) Now also deallocates AD07_HC array (rjp, bmy, 7/13/04) +! (8 ) Now also deallocate AD13_SO4_bf array (bmy, 11/17/04) +! (9 ) Now deallocate extra arrays for ND03 diagnostics (eck, bmy, 12/7/04) +! (10) Now deallocates AD21_cr array. Remove reference to arrays for ND03 +! and ND48 diagnostics, they're obsolete. (cas, sas, bmy, 1/21/05) +! (11) Removed AD41 and AFTTOT arrays; they're obsolete (bmy, 2/17/05) +! (12) Now also deallocate AD09 and AD09_em (bmy, 6/27/05) +! (13) Now deallocate AD30 (bmy, 8/18/05) +! (14) Now deallocate CTO3, AD10, AD10em arrays (phs, 9/18/07) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG begins here! + !================================================================= + IF ( ALLOCATED( AD01 ) ) DEALLOCATE( AD01 ) + IF ( ALLOCATED( AD02 ) ) DEALLOCATE( AD02 ) + IF ( ALLOCATED( AD06 ) ) DEALLOCATE( AD06 ) + IF ( ALLOCATED( AD07 ) ) DEALLOCATE( AD07 ) + IF ( ALLOCATED( AD07_BC ) ) DEALLOCATE( AD07_BC ) + IF ( ALLOCATED( AD07_OC ) ) DEALLOCATE( AD07_OC ) + IF ( ALLOCATED( AD07_HC ) ) DEALLOCATE( AD07_HC ) + IF ( ALLOCATED( AD07_SOAGM ) ) DEALLOCATE( AD07_SOAGM ) + IF ( ALLOCATED( AD08 ) ) DEALLOCATE( AD08 ) + IF ( ALLOCATED( AD09 ) ) DEALLOCATE( AD09 ) + IF ( ALLOCATED( AD09_em ) ) DEALLOCATE( AD09_em ) + IF ( ALLOCATED( AD10 ) ) DEALLOCATE( AD10 ) + IF ( ALLOCATED( AD10em ) ) DEALLOCATE( AD10em ) + IF ( ALLOCATED( AD11 ) ) DEALLOCATE( AD11 ) + IF ( ALLOCATED( AD12 ) ) DEALLOCATE( AD12 ) + IF ( ALLOCATED( AD13_DMS ) ) DEALLOCATE( AD13_DMS ) + IF ( ALLOCATED( AD13_SO2_ac ) ) DEALLOCATE( AD13_SO2_ac ) + IF ( ALLOCATED( AD13_SO2_an ) ) DEALLOCATE( AD13_SO2_an ) + IF ( ALLOCATED( AD13_SO2_bb ) ) DEALLOCATE( AD13_SO2_bb ) + IF ( ALLOCATED( AD13_SO2_bf ) ) DEALLOCATE( AD13_SO2_bf ) + IF ( ALLOCATED( AD13_SO2_nv ) ) DEALLOCATE( AD13_SO2_nv ) + IF ( ALLOCATED( AD13_SO2_ev ) ) DEALLOCATE( AD13_SO2_ev ) + IF ( ALLOCATED( AD13_SO2_sh ) ) DEALLOCATE( AD13_SO2_sh ) + IF ( ALLOCATED( AD13_SO4_an ) ) DEALLOCATE( AD13_SO4_an ) + IF ( ALLOCATED( AD13_SO4_bf ) ) DEALLOCATE( AD13_SO4_bf ) + IF ( ALLOCATED( AD13_NH3_an ) ) DEALLOCATE( AD13_NH3_an ) + IF ( ALLOCATED( AD13_NH3_na ) ) DEALLOCATE( AD13_NH3_na ) + IF ( ALLOCATED( AD13_NH3_bb ) ) DEALLOCATE( AD13_NH3_bb ) + IF ( ALLOCATED( AD13_NH3_bf ) ) DEALLOCATE( AD13_NH3_bf ) + IF ( ALLOCATED( AD16 ) ) DEALLOCATE( AD16 ) + IF ( ALLOCATED( AD17 ) ) DEALLOCATE( AD17 ) + IF ( ALLOCATED( AD18 ) ) DEALLOCATE( AD18 ) + IF ( ALLOCATED( AD21 ) ) DEALLOCATE( AD21 ) + IF ( ALLOCATED( AD21_cr ) ) DEALLOCATE( AD21_cr ) + IF ( ALLOCATED( AD22 ) ) DEALLOCATE( AD22 ) + IF ( ALLOCATED( AD28 ) ) DEALLOCATE( AD28 ) + IF ( ALLOCATED( AD29 ) ) DEALLOCATE( AD29 ) + IF ( ALLOCATED( AD30 ) ) DEALLOCATE( AD30 ) + IF ( ALLOCATED( AD31 ) ) DEALLOCATE( AD31 ) + IF ( ALLOCATED( AD32_ac ) ) DEALLOCATE( AD32_ac ) + IF ( ALLOCATED( AD32_an ) ) DEALLOCATE( AD32_an ) + IF ( ALLOCATED( AD32_bb ) ) DEALLOCATE( AD32_bb ) + IF ( ALLOCATED( AD32_bf ) ) DEALLOCATE( AD32_bf ) + IF ( ALLOCATED( AD32_fe ) ) DEALLOCATE( AD32_fe ) + IF ( ALLOCATED( AD32_li ) ) DEALLOCATE( AD32_li ) + IF ( ALLOCATED( AD32_so ) ) DEALLOCATE( AD32_so ) + IF ( ALLOCATED( AD32_ub ) ) DEALLOCATE( AD32_ub ) + IF ( ALLOCATED( AD32_ship ) ) DEALLOCATE( AD32_ship ) + IF ( ALLOCATED( AD32_ship_count) ) DEALLOCATE( AD32_ship_count) + IF ( ALLOCATED( AD33 ) ) DEALLOCATE( AD33 ) + IF ( ALLOCATED( AD34 ) ) DEALLOCATE( AD34 ) + IF ( ALLOCATED( AD35 ) ) DEALLOCATE( AD35 ) + IF ( ALLOCATED( AD36 ) ) DEALLOCATE( AD36 ) + IF ( ALLOCATED( AD36_SHIP ) ) DEALLOCATE( AD36_SHIP ) + IF ( ALLOCATED( AD36_SHIP_COUNT ) ) DEALLOCATE( AD36_SHIP_COUNT ) + IF ( ALLOCATED( AD37 ) ) DEALLOCATE( AD37 ) + IF ( ALLOCATED( AD38 ) ) DEALLOCATE( AD38 ) + IF ( ALLOCATED( AD39 ) ) DEALLOCATE( AD39 ) + IF ( ALLOCATED( AD43 ) ) DEALLOCATE( AD43 ) + IF ( ALLOCATED( AD44 ) ) DEALLOCATE( AD44 ) + IF ( ALLOCATED( AD45 ) ) DEALLOCATE( AD45 ) + IF ( ALLOCATED( AD46 ) ) DEALLOCATE( AD46 ) + IF ( ALLOCATED( AD47 ) ) DEALLOCATE( AD47 ) + IF ( ALLOCATED( AD52 ) ) DEALLOCATE( AD52 ) + IF ( ALLOCATED( AD54 ) ) DEALLOCATE( AD54 ) + IF ( ALLOCATED( AD55 ) ) DEALLOCATE( AD55 ) + IF ( ALLOCATED( AD19 ) ) DEALLOCATE( AD19 ) + IF ( ALLOCATED( AD58 ) ) DEALLOCATE( AD58 ) + IF ( ALLOCATED( AD60 ) ) DEALLOCATE( AD60 ) + IF ( ALLOCATED( AD63 ) ) DEALLOCATE( AD63 ) + IF ( ALLOCATED( AD63_COUNT ) ) DEALLOCATE( AD63_COUNT ) + IF ( ALLOCATED( AD66 ) ) DEALLOCATE( AD66 ) + IF ( ALLOCATED( AD68 ) ) DEALLOCATE( AD68 ) + IF ( ALLOCATED( AD69 ) ) DEALLOCATE( AD69 ) + IF ( ALLOCATED( CONVFLUP ) ) DEALLOCATE( CONVFLUP ) + IF ( ALLOCATED( CT16 ) ) DEALLOCATE( CT16 ) + IF ( ALLOCATED( CT17 ) ) DEALLOCATE( CT17 ) + IF ( ALLOCATED( CT18 ) ) DEALLOCATE( CT18 ) + IF ( ALLOCATED( CTJV ) ) DEALLOCATE( CTJV ) + IF ( ALLOCATED( CTNO ) ) DEALLOCATE( CTNO ) + IF ( ALLOCATED( CTO3 ) ) DEALLOCATE( CTO3 ) + IF ( ALLOCATED( CTO3_24h ) ) DEALLOCATE( CTO3_24h ) + IF ( ALLOCATED( CTOH ) ) DEALLOCATE( CTOH ) + IF ( ALLOCATED( CTNO2 ) ) DEALLOCATE( CTNO2 ) + IF ( ALLOCATED( CTNO3 ) ) DEALLOCATE( CTNO3 ) + IF ( ALLOCATED( EMISS_ANTHR ) ) DEALLOCATE( EMISS_ANTHR ) + IF ( ALLOCATED( CTHO2 ) ) DEALLOCATE( CTHO2 ) + IF ( ALLOCATED( CTOTH ) ) DEALLOCATE( CTOTH ) + IF ( ALLOCATED( DIAGCHLORO ) ) DEALLOCATE( DIAGCHLORO ) + IF ( ALLOCATED( LTJV ) ) DEALLOCATE( LTJV ) + IF ( ALLOCATED( LTNO ) ) DEALLOCATE( LTNO ) + IF ( ALLOCATED( LTOH ) ) DEALLOCATE( LTOH ) + IF ( ALLOCATED( LTNO2 ) ) DEALLOCATE( LTNO2 ) + IF ( ALLOCATED( LTNO3 ) ) DEALLOCATE( LTNO3 ) + IF ( ALLOCATED( LTHO2 ) ) DEALLOCATE( LTHO2 ) + IF ( ALLOCATED( LTOTH ) ) DEALLOCATE( LTOTH ) + IF ( ALLOCATED( MASSFLEW ) ) DEALLOCATE( MASSFLEW ) + IF ( ALLOCATED( MASSFLNS ) ) DEALLOCATE( MASSFLNS ) + IF ( ALLOCATED( MASSFLUP ) ) DEALLOCATE( MASSFLUP ) + IF ( ALLOCATED( TURBFLUP ) ) DEALLOCATE( TURBFLUP ) + IF ( ALLOCATED( STT_TEMPO2 ) ) DEALLOCATE( STT_TEMPO2 ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG + +!------------------------------------------------------------------------------ + + END MODULE DIAG_MOD + diff --git a/code/diag_oh_mod.f b/code/diag_oh_mod.f new file mode 100644 index 0000000..eb240f0 --- /dev/null +++ b/code/diag_oh_mod.f @@ -0,0 +1,406 @@ +! $Id: diag_oh_mod.f,v 1.2 2012/03/01 22:00:26 daven Exp $ + MODULE DIAG_OH_MOD +! +!****************************************************************************** +! Module DIAG_OH_MOD contains routines and variables to archive OH mass +! and air mass concentrations. These are then used to print out the mass- +! weighted mean OH concentration in 1e5 molec/cm3. This is a metric of +! how certain chemisry simulations are performing. (bmy, 7/20/04, 6/24/05) +! +! Module Variables: +! ============================================================================ +! (1 ) AIR_MASS (REAL*8) : Array used to sum mean air mass [molec/cm3] +! (2 ) OH_MASS (REAL*8) : Array used to sum mean OH mass [molec/cm3] +! +! Module Routines: +! ============================================================================ +! (1 ) DO_DIAG_OH : Driver routine for mean OH diagnostic (fullchem) +! (2 ) DO_DIAG_OH_CH4 : Driver routine for mean OH diagnostic (CH4 sim) +! (3 ) PRINT_DIAG_OH : Prints the mean OH concentration [1e5 molec/cm3] +! (4 ) INIT_DIAG_OH : Allocates and zeroes module arrays +! (5 ) CLEANUP_DIAG_OH : Deallocates module arrays +! +! GEOS-CHEM modules referenced by "diag_oh_mod.f": +! ============================================================================ +! (1 ) comode_mod.f : Module w/ SMVGEAR allocatable arrays +! (2 ) error_mod.f : Module w/ I/O error and NaN check routines +! (3 ) logical_mod.f : Module w/ GEOS-CHEM logical switches +! (4 ) tracer_mod.f : Module w/ GEOS-CHEM tracer array STT etc. +! (5 ) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! NOTES: +! (1 ) Remove code for obsolete CO-OH simulation (bmy, 6/24/05) +! (2 ) Add OH_LOSS array (kjw, dkh, 02/12/12, adj32_023) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag_oh_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these routines + PUBLIC :: CLEANUP_DIAG_OH + PUBLIC :: DO_DIAG_OH + PUBLIC :: DO_DIAG_OH_CH4 + PUBLIC :: INIT_DIAG_OH + PUBLIC :: PRINT_DIAG_OH + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_OH + + ! Arrays + REAL*8, ALLOCATABLE :: OH_MASS(:,:,:) + REAL*8, ALLOCATABLE :: AIR_MASS(:,:,:) + REAL*8, ALLOCATABLE :: OH_LOSS(:,:,:) + REAL*8, ALLOCATABLE :: OHCH4_LOSS(:,:,:) + REAL*8, ALLOCATABLE :: CH4_MASS(:,:,:) + REAL*8, ALLOCATABLE :: CH4_TROPMASS(:,:,:) + REAL*8, ALLOCATABLE :: CH4_EMIS(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DO_DIAG_OH +! +!****************************************************************************** +! Subroutine DO_DIAG_OH sums the OH and air mass (from SMVGEAR arrays) for +! the mean OH concentration diagnostic. (bmy, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! Reference to F90 modules + USE COMODE_MOD, ONLY : AIRDENS, CSPEC, JLOP, T3, VOLUME + USE TRACERID_MOD, ONLY : IDOH + +# include "CMN_SIZE" ! Size parameters +# include "comode.h" ! NPVERT, NLAT, NLONG + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: I, J, L, JLOOP + REAL*8 :: XLOSS, XOHMASS, XAIRMASS + + !================================================================= + ! DO_DIAG_OH begins here! + !================================================================= + + ! Safety valve -- avoid seg faults + IF ( .not. DO_SAVE_OH ) RETURN + + ! Loop over boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, JLOOP, XAIRMASS, XOHMASS, XLOSS ) +!$OMP+SCHEDULE( DYNAMIC ) + DO L = 1, NPVERT + DO J = 1, NLAT + DO I = 1, NLONG + + ! 1-D grid box index + JLOOP = JLOP(I,J,L) + + ! Cycle if this isn't a valid SMVGEAR gridbox + IF ( JLOOP > 0 ) THEN + + ! Sum air mass term into AIR_MASS array + XAIRMASS = AIRDENS(JLOOP) * VOLUME(JLOOP) + AIR_MASS(I,J,L) = AIR_MASS(I,J,L) + XAIRMASS + + ! Sum OH mass term into OH_MASS array + XOHMASS = CSPEC(JLOOP,IDOH) * XAIRMASS + OH_MASS(I,J,L) = OH_MASS(I,J,L) + XOHMASS + + ENDIF + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DO_DIAG_OH + +!------------------------------------------------------------------------------ + + SUBROUTINE DO_DIAG_OH_CH4( I, J, L, XOHMASS, XAIRMASS, XLOSS, + & XCH4LOSS, XCH4TROPMASS, XCH4EMIS, XCH4MASS ) +! +!****************************************************************************** +! Subroutine DO_DIAG_OH_CH4 passes the OH loss, OH mass, and air mass terms +! from "global_ch4_mod.f" to "diag_oh_mod.f" (bmy, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1-3) I, J, L (INTEGER) : GEOS-CHEM lon, lat, & altitude indices +! (4 ) XOHMASS (REAL*8 ) : OH mass term from "global_ch4_mod.f" +! (5 ) XAIRMASS (REAL*8 ) : air mass term from "global_ch4_mod.f" +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I ! Longitude index + INTEGER, INTENT(IN) :: J ! Latitude index + INTEGER, INTENT(IN) :: L ! Level index + REAL*8, INTENT(IN) :: XOHMASS ! OH Mass (from global_ch4_mod.f) + REAL*8, INTENT(IN) :: XAIRMASS ! Air mass (from global_ch4_mod.f) + REAL*8, INTENT(IN) :: XLOSS ! Loss of ch3ccl3 by OH + REAL*8, INTENT(IN) :: XCH4LOSS ! Loss of ch4 by OH + REAL*8, INTENT(IN) :: XCH4MASS ! CH4 Mass (from global_ch4_mod.f) + REAL*8, INTENT(IN) :: XCH4TROPMASS ! CH4 Mass (from global_ch4_mod.f) + REAL*8, INTENT(IN) :: XCH4EMIS ! CH4 emissions + + !================================================================= + ! DO_DIAG_OH_CH4 begins here! + !================================================================= + + ! Sum air mass & OH mass into arrays + AIR_MASS(I,J,L) = AIR_MASS(I,J,L) + XAIRMASS + OH_MASS(I,J,L) = OH_MASS(I,J,L) + XOHMASS + OH_LOSS(I,J,L) = OH_LOSS(I,J,L) + XLOSS + OHCH4_LOSS(I,J,L) = OHCH4_LOSS(I,J,L) + XCH4LOSS + CH4_MASS(I,J,L) = CH4_MASS(I,J,L) + XCH4MASS + CH4_TROPMASS(I,J,L) = CH4_TROPMASS(I,J,L) + XCH4TROPMASS + CH4_EMIS(I,J,L) = CH4_EMIS(I,J,L) + XCH4EMIS + + ! Return to calling program + END SUBROUTINE DO_DIAG_OH_CH4 + +!------------------------------------------------------------------------------ + + SUBROUTINE PRINT_DIAG_OH +! +!****************************************************************************** +! Subroutine PRINT_DIAG_OH prints the mass-weighted OH concentration at +! the end of a simulation. (bmy, 10/21/03, 7/20/04) +! +! NOTES: +!****************************************************************************** +! + ! Reference to F90 modules + USE TRACER_MOD, ONLY : ITS_A_CH4_SIM + + ! Local variables + REAL*8 :: SUM_OHMASS, SUM_MASS, SUM_OHLOSS, OHCONC, LIFETIME + REAL*8 :: SUM_OHCH4LOSS, SUM_CH4MASS, SUM_CH4EMIS, SUM_CH4TROPMASS + + !================================================================= + ! PRINT_DIAG_OH begins here! + !================================================================= + + ! Return if this diagnostic is turned off + IF ( .not. DO_SAVE_OH ) RETURN + + ! Total Mass-weighted OH [molec OH/cm3] * [molec air] + SUM_OHMASS = SUM( OH_MASS ) + + ! Atmospheric air mass [molec air] + SUM_MASS = SUM( AIR_MASS ) + + ! OH Loss from CH4 + OH [molec / box / s] + SUM_OHCH4LOSS = SUM( OHCH4_LOSS ) + + ! Atmospheric mass of CH4 + SUM_CH4MASS = SUM( CH4_MASS ) + + ! Atmospheric mass of tropospheric CH4 + SUM_CH4TROPMASS = SUM( CH4_TROPMASS ) + + ! Atmospheric ch4 emissions + SUM_CH4EMIS = SUM( CH4_EMIS ) + + ! Avoid divide-by-zero errors + IF ( SUM_MASS > 0d0 ) THEN + + ! Divide OH by [molec air] and report as [1e5 molec/cm3] + OHCONC = ( SUM_OHMASS / SUM_MASS ) / 1d5 + + ! Write value to log file + WRITE( 6, '(/,a)' ) REPEAT( '=', 79 ) + WRITE( 6, * ) 'ND23: Mass-Weighted OH Concentration' + WRITE( 6, * ) 'Mean OH = ', OHCONC, ' [1e5 molec/cm3]' + WRITE( 6, '( a)' ) REPEAT( '=', 79 ) + + ! Avoid divide-by-zero errors + IF ( ITS_A_CH4_SIM() ) THEN + IF ( SUM_OHLOSS > 0 ) THEN + + ! Mass weighted lifetimes printed below + WRITE( 6, * ) 'All lifetimes printed below ' // + & 'are mass-weighted' + WRITE( 6, '( a)' ) REPEAT( '-', 79 ) + + ! Calculate CH4 lifetime w/r/t OH loss [years] + LIFETIME = ( SUM_MASS / SUM_OHCH4LOSS ) / + & ( 3600d0*365d0*24d0 ) + ! Write value to log file + WRITE( 6, * ) 'Methane (CH4)' + WRITE( 6, * ) 'Tropospheric Lifetime w/r/t OH = ', + & LIFETIME, ' [years]' + WRITE( 6, '( a)' ) REPEAT( '=', 79 ) + + ! Calculate CH4 lifetime [years] + LIFETIME = ( SUM_CH4TROPMASS / SUM_CH4EMIS ) / + & ( 3600d0*365d0*24d0 ) + ! Write value to log file + WRITE( 6, * ) 'Methane (CH4)' + WRITE( 6, * ) 'Tropospheric Lifetime (total) = ', + & LIFETIME, ' [years]' + WRITE( 6, '( a)' ) REPEAT( '=', 79 ) + + ! Calculate CH4 lifetime [years] + LIFETIME = ( SUM_CH4MASS / SUM_CH4EMIS ) / + & ( 3600d0*365d0*24d0 ) + ! Write value to log file + WRITE( 6, * ) 'Methane (CH4)' + WRITE( 6, * ) 'Global Lifetime (total) = ', + & LIFETIME, ' [years]' + WRITE( 6, '( a)' ) REPEAT( '=', 79 ) + + ENDIF + ENDIF + ELSE + + ! Write error msg if SUM_MASS is zero + WRITE( 6, '(/,a)' ) REPEAT( '=', 79 ) + WRITE( 6, '( a)' ) 'Could not print mass-weighted OH!' + WRITE( 6, '( a)' ) 'Atmospheric air mass is zero!' + WRITE( 6, '( a)' ) REPEAT( '=', 79 ) + + ENDIF + + ! Return to MAIN program + END SUBROUTINE PRINT_DIAG_OH + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG_OH +! +!****************************************************************************** +! Subroutine INIT_DIAG_OH initializes all module arrays. +! (bmy, 7/20/04, 6/24/05) +! +! NOTES: +! (1 ) Remove references to CO-OH simulation and to CMN_DIAG (bmy, 6/24/05) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LCHEM + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM, ITS_A_CH4_SIM + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: AS, LMAX + + !================================================================= + ! INIT_DIAG_OH begins here! + !================================================================= + + ! Initialize + DO_SAVE_OH = .FALSE. + + ! Return if we are not doing chemistry + IF ( .not. LCHEM ) RETURN + + ! Set vertical levels and decide whether to print CH3CCl3 + ! lifetime or just mean mass-weighted OH concentration + IF ( ITS_A_FULLCHEM_SIM() ) THEN + + ! Fullchem: tropopshere only + LMAX = LLTROP + DO_SAVE_OH = .TRUE. + + ELSE IF ( ITS_A_CH4_SIM() ) THEN + + ! CH4: all levels + LMAX = LLPAR + DO_SAVE_OH = .TRUE. + + ENDIF + + ! Echo info + WRITE( 6, 100 ) DO_SAVE_OH + 100 FORMAT( /, 'Turn on Mean OH diagnostic (ND23)? :', L5 ) + + ! Return if we aren't saving mean OH + IF ( .not. DO_SAVE_OH ) RETURN + + !================================================================= + ! Allocate arrays + !================================================================= + + ! Air mass array + ALLOCATE( AIR_MASS( IIPAR, JJPAR, LMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AIR_MASS' ) + AIR_MASS = 0d0 + + ! OH mass array + ALLOCATE( OH_MASS( IIPAR, JJPAR, LMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OH_MASS' ) + OH_MASS = 0d0 + + ! OH LOSS array + ALLOCATE( OH_LOSS( IIPAR, JJPAR, LMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OH_LOSS' ) + OH_LOSS = 0d0 + + ALLOCATE( OHCH4_LOSS( IIPAR, JJPAR, LMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OHCH4_LOSS' ) + OHCH4_LOSS = 0d0 + + ALLOCATE( CH4_MASS( IIPAR, JJPAR, LMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'CH4_MASS' ) + CH4_MASS = 0d0 + + ALLOCATE( CH4_TROPMASS( IIPAR, JJPAR, LMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'CH4_TROPMASS' ) + CH4_TROPMASS = 0d0 + + ALLOCATE( CH4_EMIS( IIPAR, JJPAR, LMAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'CH4_EMIS' ) + CH4_EMIS = 0d0 + + ! Return to calling program + END SUBROUTINE INIT_DIAG_OH + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG_OH +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG_OH deallocates all module arrays. (bmy, 7/20/04) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG_OH begins here! + !================================================================= + IF ( ALLOCATED( OH_MASS ) ) DEALLOCATE( OH_MASS ) + IF ( ALLOCATED( AIR_MASS ) ) DEALLOCATE( AIR_MASS ) + IF ( ALLOCATED( OH_LOSS ) ) DEALLOCATE( OH_LOSS ) + IF ( ALLOCATED( OHCH4_LOSS ) ) DEALLOCATE( OHCH4_LOSS ) + IF ( ALLOCATED( CH4_MASS ) ) DEALLOCATE( CH4_MASS ) + IF ( ALLOCATED( CH4_TROPMASS ) ) DEALLOCATE( CH4_TROPMASS ) + IF ( ALLOCATED( CH4_EMIS ) ) DEALLOCATE( CH4_EMIS ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG_OH + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG_OH_MOD diff --git a/code/diag_pl_mod.f b/code/diag_pl_mod.f new file mode 100644 index 0000000..0aec46e --- /dev/null +++ b/code/diag_pl_mod.f @@ -0,0 +1,1310 @@ +! $Id: diag_pl_mod.f,v 1.2 2010/03/09 15:03:46 daven Exp $ + MODULE DIAG_PL_MOD +! +!****************************************************************************** +! Module DIAG_PL_MOD contains variables and routines which are used to +! compute the production and loss of chemical families in SMVGEAR chemistry. +! (bmy, 7/20/04, 11/18/08) +! +! Module Variables: +! ============================================================================ +! (1 ) DO_SAVE_PL (LOGICAL ) : Flag to turn on prod/loss diagnostic +! (2 ) DO_SAVE_O3 (LOGICAL ) : Flag to save out P(Ox), L(Ox) for TagOx sim +! (3 ) MAXMEM (INTEGER ) : Max # of members per family +! (4 ) MMAXFAM (INTEGER ) : Shadow variable for max # of families +! (5 ) NFAM (INTEGER ) : Number of prod/loss families in "input.geos" +! (6 ) YYYYMMDD (INTEGER ) : Current date +! (7 ) COUNT (INTEGER ) : Counter for timesteps per day +! (8 ) FAM_NMEM (INTEGER ) : Number of members w/in each prod/loss family +! (9 ) TAUb (REAL*8 ) : TAU value at start of GEOS-CHEM simulation +! (10) TAUe (REAL*8 ) : TAU value at end of GEOS-CHEM simulation +! (11) TAU0 (REAL*8 ) : TAU value at start of diagnostic interval +! (12) TAU1 (REAL*8 ) : TAU value at end of diagnostic interval +! (13) AD65 (REAL*8 ) : Array for prod/loss diagnostic (a.k.a. ND65) +! (14) PL24H (REAL*8 ) : Array for saving P(Ox), L(Ox) (a.k.a. ND20) +! (15) FAM_PL (REAL*8 ) : Array to archive prod & loss from SMVGEAR +! (16) FAM_COEF (REAL*8 ) : Coefficient for each prod/loss family member +! (17) FILENAME (CHAR*255) : Name of output file for saving P(Ox) & L(Ox) +! (18) FAM_NAME (CHAR*14 ) : Array for name of each prod/loss family +! (19) FAM_TYPE (CHAR*14 ) : Type of each prod/loss family +! (20) FAM_MEMB (CHAR*14 ) : Array of members in each prod/loss family +! +! Module Routines: +! ============================================================================ +! (1 ) SETJFAM : Initializes SMVGEAR arrays for prod/loss diag +! (2 ) SETPL : Copies prod/loss families into SMVGEAR arrays +! (3 ) DO_DIAG_PL : Driver routine for prod/loss diags (ND65, ND20) +! (4 ) DIAG20 : Driver routine for saving O3 P/L (a.k.a. ND20) +! (5 ) WRITE20 : Writes P(Ox) and L(Ox) to bpch file format +! (6 ) ITS_TIME_FOR_WRITE20 : Returns T if it's time to save files to disk +! (7 ) GET_NFAM : Returns number of defined P/L families +! (8 ) GET_FAM_NAME : Returns name of each P/L family +! (9 ) GET_FAM_MWT : Returns molecular weight for each P/L family +! (10) INIT_DIAG_PL : Allocates & zeroes all module arrays +! (11) CLEANUP_DIAG_PL : Deallocates all module arrays +! +! GEOS-CHEM modules referenced by "diag_pl_mod.f": +! ============================================================================ +! (1 ) bpch2_mod.f : Module containing routines for binary punch file I/O +! (2 ) comode_mod.f : Module containing SMVGEAR allocatable arrays +! (3 ) directory_mod.f : Module containing GEOS-CHEM data & met field dirs +! (4 ) error_mod.f : Module containing I/O error and NaN check routines +! (5 ) file_mod.f : Module containing file unit numbers & error checks +! (6 ) grid_mod.f : Module containing horizontal grid information +! (7 ) time_mod.f : Module containing routines for computing time & date +! (8 ) tracer_mod.f : Module containing GEOS-CHEM tracer array STT etc. +! (9 ) tracerid_mod.f : Module containing pointers to tracers & emissions +! +! NOTES: +! (1 ) Add TAUe as a module variable. Bug fixes: Make sure WRITE20 uses the +! global FILENAME, and also write to disk on the last timestep before +! the end of the simulation. (bmy, 11/15/04) +! (2 ) Added routine ITS_TIME_FOR_WRITE20 (bmy, 3/3/05) +! (3 ) Added functions GET_NFAM, GET_FAM_MWT, GET_FAM_NAME (bmy, 5/2/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 ) Bug fix in DIAG20 (phs, 1/22/07) +! (7 ) Now use LD65 as the vertical dimension instead of LLTROP or LLTROP_FIX +! in DO_DIAG_PL, DIAG20, and WRITE20 (phs, bmy, 12/4/07) +! (8 ) Now make COUNT a 3-D array (phs, 11/18/08) +! (9 ) Minor fix in DIAG20 (dbj, bmy, 10/26/09) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "diag_pl_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: AD65 + PUBLIC :: DO_SAVE_PL + PUBLIC :: FAM_PL + + ! ... and these routines + PUBLIC :: DO_DIAG_PL + PUBLIC :: GET_FAM_MWT + PUBLIC :: GET_FAM_NAME + PUBLIC :: GET_NFAM + PUBLIC :: SETJFAM + PUBLIC :: SETPL + PUBLIC :: INIT_DIAG_PL + PUBLIC :: CLEANUP_DIAG_PL + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + LOGICAL :: DO_SAVE_PL + LOGICAL :: DO_SAVE_O3 + INTEGER, PARAMETER :: MAXMEM = 10 + INTEGER, PARAMETER :: MMAXFAM = 40 ! MAXFAM=40 in "CMN_SIZE" + INTEGER :: NFAM + INTEGER :: YYYYMMDD + REAL*8 :: TAUb, TAUe, TAU0, TAU1 + CHARACTER(LEN=255) :: FILENAME + + ! Arrays + INTEGER, ALLOCATABLE :: FAM_NMEM(:), COUNT(:,:,:) + REAL*4, ALLOCATABLE :: AD65(:,:,:,:) + REAL*8, ALLOCATABLE :: FAM_PL(:,:,:,:) + REAL*8, ALLOCATABLE :: FAM_COEF(:,:) + REAL*8, ALLOCATABLE :: PL24H(:,:,:,:) + CHARACTER(LEN=14), ALLOCATABLE :: FAM_NAME(:) + CHARACTER(LEN=14), ALLOCATABLE :: FAM_TYPE(:) + CHARACTER(LEN=14), ALLOCATABLE :: FAM_MEMB(:,:) + + !================================================================= + ! MODULE ROUTINES -- follow beneath the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE SETJFAM( NACTIVE, NINAC ) +! +!****************************************************************************** +! Subroutine SETJFAM stores info into SMVGEAR arrays for the ND65 prod/loss +! diagnostic. (ljm, bmy, 1999, 7/20/04) +! +! Arguments as Input/Output: +! ============================================================================ +! (1 ) NACTIVE (INTEGER) : Number of active SMVGEAR species +! (2 ) NINAC (INTEGER) : Number of inactive SMVGEAR species +! +! NOTES: +! (1 ) Replace NAMESPEC with NAMEGAS for SMVGEAR II. Added comment header +! and updated comments. Now references IU_FILE and IOERROR from +! F90 module "file_mod.f". Now trap I/O errors using routine IOERROR. +! Make DEFMR a parameter for safety's sake. Need to increment NACTIVE +! for SMVGEAR II or else the last species will be overwritten w/ the +! first ND65 family. Set NCS = NCSURBAN, since we have defined our +! GEOS-CHEM mechanism in the urban slot of SMVGEAR II.(bmy, 4/21/03) +! (2 ) Bundled into "diag65_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters +# include "comode.h" ! SMVGEAR II arrays + + ! Arguments + INTEGER, INTENT(INOUT) :: NACTIVE, NINAC + + ! Local variables + INTEGER :: F, J, JGAS0, JGAS + + !================================================================= + ! SETJFAM begins here! + !================================================================= + + ! Need increment NACTIVE for SMVGEAR II or else the last species + ! will be overwritten w/ the first ND65 family (bmy, 4/18/03) + NACTIVE = NACTIVE + 1 + JGAS0 = NACTIVE + + ! Set NCS = NCSURBAN, since we have defined our GEOS-CHEM + ! mechanism in the urban slot of SMVGEAR II. (bmy, 4/21/03) + NCS = NCSURBAN + + !================================================================= + ! Read in family names for prod and loss. Assume these + ! families are active. Assume initial mixing ratio = 0d0. + ! Note that when setjfam is called, nactive = active species +1. + !================================================================= + + ! Loop over families + DO F = 1, NFAM + + ! Update variables + JGAS = NACTIVE + NTSPEC(NCS) = NACTIVE + IGAS - NINAC + NAMEGAS(JGAS) = FAM_NAME(F) + QBKCHEM(JGAS,NCS) = 0d0 + NACTIVE = NACTIVE + 1 + + ENDDO + + !================================================================= + ! Write out family names to "smv2.log" file + !================================================================= + WRITE( IO93, '(/,a)' ) REPEAT( '=', 79 ) + WRITE( IO93, '(a)' ) 'Families for prod or loss output:' + WRITE( IO93, '(a,/)' ) REPEAT( '=', 79 ) + WRITE( IO93, '(10(a7,1x))' ) ( TRIM( NAMEGAS(J) ), J=JGAS0,JGAS ) + + ! Return to calling program + END SUBROUTINE SETJFAM + +!------------------------------------------------------------------------------ + + SUBROUTINE SETPL +! +!****************************************************************************** +! Subroutine SETPL flags the reactions and species which contribute to +! production or loss for a given ND65 prodloss diagnostic family. +! (ljm, bey, 1999; bmy, 5/1/03) +! +! NOTES: +! (1 ) Now references "file_mod.f" and "error_mod.f". Also now use IOERROR +! to trap I/O errors, and ERROR_STOP to stop the run and deallocate +! all module arrays. NAMESPEC is now NAMEGAS for SMVGEAR II. Now +! uses F90 declaration syntax. Set NCS = NCSURBAN for now, since we +! have defined our GEOS-CHEM mechanism in the urban slot of SMVGEAR II +! Updated comments. (bmy, 5/1/03) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP, GEOS_CHEM_STOP + +# include "CMN_SIZE" +# include "comode.h" + + ! Parameters + INTEGER, PARAMETER :: MAXPL=100, MAXMEM=10 + + ! Local variables + INTEGER :: F, ICOUNT, I, J, INDEX, IOS + INTEGER :: K, M, N, NK, NREAC, NPROD, NPOS + INTEGER :: IREAC1, IREAC2, IREAC3 + INTEGER :: IPROD1, IPROD2, IPROD3 + INTEGER :: NFAMMEM(MAXFAM) + INTEGER :: IFAMMEM(MAXMEM,MAXFAM) + INTEGER :: ITEMPREAC(NMRPROD) + INTEGER :: NNPL(MAXFAM) + INTEGER :: NKPL(MAXPL,MAXFAM) + INTEGER :: IPLREAC(NMRPROD,MAXPL,MAXFAM) + REAL*8 :: PL + REAL*8 :: COEFMEM(MAXMEM,MAXFAM) + REAL*8 :: COEFPL(MAXPL,MAXFAM) + CHARACTER(LEN=5) :: EXTRACHAR + + !================================================================= + ! SETPL begins here! + !================================================================= + + ! Set NCS = NCSURBAN for now, since we have defined our GEOS-CHEM + ! mechanism in the urban slot of SMVGEAR II. (bmy, 4/21/03) + NCS = NCSURBAN + + ! Initialize + ICOUNT = 0 + + !================================================================= + ! Process family information + !================================================================= + + ! Set NFAMILIES in "comode.h" + NFAMILIES = NFAM + + ! Loop over families + DO F = 1, NFAM + + !---------------- + ! Error checks + !---------------- + + ! # of families + IF ( F > MAXFAM ) THEN + CALL ERROR_STOP( 'Too many ND65 families!', 'setpl.f' ) + ENDIF + + ! # of members + IF ( FAM_NMEM(F) > MAXMEM ) THEN + CALL ERROR_STOP( 'Too many family members!', 'setpl.f' ) + ENDIF + + !----------------- + ! Family name + !----------------- + DO J = 1, NSPEC(NCS) + IF ( NAMEGAS(J) == FAM_NAME(F) ) IFAM(F) = J + ENDDO + + !----------------- + ! Family type + !----------------- + PORL(F) = FAM_TYPE(F) + + ! Convert PORL to lower case if necessary + IF ( PORL(F) == 'PROD' ) PORL(F) = 'prod' + IF ( PORL(F) == 'LOSS' ) PORL(F) = 'loss' + + ! Write to "smv2.log" + WRITE( IO93, 104 ) F, FAM_NAME(F), PORL(F), FAM_NMEM(F) + 104 FORMAT(/, 'Family ', i2, ' is ' ,a5, ' ', a4, + & ' with ', i2, ' members' ) + + WRITE( IO93, 105 ) + 105 FORMAT( 'ind', 2x, 'species', 1x, 'jnum', 2x, 'coef' ) + + !------------------ + ! Family members + !------------------ + DO M = 1, FAM_NMEM(F) + + ! Coefficient of each member + COEFMEM(M,F) = FAM_COEF(M,F) + + ! Store each family member in IFAMMEM + DO J = 1, NSPEC(NCS) + IF ( NAMEGAS(J) == FAM_MEMB(M,F) ) IFAMMEM(M,F) = J + ENDDO + + ! Write to "smv2.log" + WRITE( IO93, '(i2,3x,a5,2x,i3,2x,f5.1 )') + & F, FAM_MEMB(M,F), IFAMMEM(M,F), COEFMEM(M,F) + ENDDO + ENDDO + + !================================================================= + ! Now determine which reactions are sources or sinks of the + ! specified families. Amend the IRM array accordingly. + !================================================================= + DO N = 1, NFAMILIES + NNPL(N) = 0 + ENDDO + + ! Loop over all rxns (NTRATES = # of kinetic + photo rxns) + DO NK = 1, NTRATES(NCS) + + ! If this rxn hasn't been turned off... + IF ( LSKIP(NK,NCS) == 0 ) THEN + + ! Index of first reactant + IREAC1 = IRM(1,NK,NCS) + + ! Index of first product + IPROD1 = IRM(NPRODLO,NK,NCS) + + ! Skip emission rxns + IF ( NAMEGAS(IREAC1) == 'EMISSION' ) GOTO 150 + + ! Skip drydep rxns + DO N = 1, NDRYDEP(NCS) + IF ( NK == NKDRY(N,NCS) ) GOTO 150 + ENDDO + + !=========================================================== + ! For this rxn, loop over all prod/loss diagnostic families + !=========================================================== + DO N = 1, NFAMILIES + + ! Initialize for each family + PL = 0 + NPROD = 0 + ICOUNT = 0 + ITEMPREAC = 0 + + !======================================================== + ! For each rxn, loop over reactants and products + ! and compute how many moles are gained and lost + !======================================================== + DO I = 1, NPRODHI + + ! Increment product count (1st 4 slots are reactants) + IF ( I > 4 ) ICOUNT = ICOUNT + 1 + + ! Skip blank entries + IF ( IRM(I,NK,NCS) /= 0 ) THEN + + ! Store reactant index for later use + ITEMPREAC(I) = IRM(I,NK,NCS) + + ! Ensure NPROD skips over the reactant slots of IRM + IF ( I > 4 ) NPROD = NPROD + 1 + IF ( NPROD < ICOUNT ) NPROD = ICOUNT + + ! Loop over all family members + DO J = 1, FAM_NMEM(N) + + ! Test for product or reactant + IF ( IRM(I,NK,NCS) == IFAMMEM(J,N) ) THEN + + !============================================ + ! PRODUCT: The # of moles that prodloss + ! family N gains is the # of moles that + ! species M contributes to family N (i.e. + ! COEFMEM(J,N) ) times the # of moles of + ! species M gained in the reaction (i.e. + ! FKOEF(I,NK,NCS) ). + !============================================ + IF ( I >= NPRODLO ) THEN + PL = PL + COEFMEM(J,N) * FKOEF(I,NK,NCS) + ENDIF + + !============================================ + ! REACTANT: The # of moles that prodloss + ! family N loses is the # of moles that + ! species M contributes to family N (i.e. + ! COEFMEM(J,N) ). Here FKOEF is almost + ! always 1 for reactants. + !============================================ + IF ( I < NPRODLO ) THEN + PL = PL - COEFMEM(J,N) + ENDIF + ENDIF + ENDDO + ENDIF + ENDDO + + !======================================================== + ! If there is a production or loss for prodloss family + ! N, then update IRM and the other arrays + !======================================================== + IF ( ( PL > 0 .AND. PORL(N) == 'prod' ) .OR. + & ( PL < 0 .AND. PORL(N) == 'loss' ) ) THEN + + ! # of prod or loss rxns for family N + NNPL(N) = NNPL(N) + 1 + + ! Error check + IF ( NNPL(N) .GT. MAXPL ) THEN + CALL ERROR_STOP( 'Number of rxns exceeds MAXPL!', + & 'setpl.f' ) + ENDIF + + ! Index of IRM for one beyond the next product + NPOS = NPRODLO + NPROD + + ! Store # of each rxn in NKPL for output below + NKPL(NNPL(N),N) = NK + + ! Store P/L coeff for each rxn in COEFPL for output below + COEFPL(NNPL(N),N) = PL + + ! Store the family name as the "last" product of the + ! of the rxn -- in the (NPRODLO+NPROD)th slot of IRM + IRM(NPOS,NK,NCS) = IFAM(N) + + ! Also store the total prod/loss of family N + ! in the (NPRODLO+NPROD)th of the FKOEF array + FKOEF(NPOS,NK,NCS) = ABS( PL ) + + ! Loop over all reactants and products + DO I = 1, NMRPROD + + ! Zero any negative reactant/product indices + IF ( ITEMPREAC(I) < 0 ) ITEMPREAC(I) = 0 + + ! 3-body rxn??? + IF ( ITEMPREAC(3) > 0 ) THEN + WRITE( 6, 1190 ) NK + 1190 FORMAT( 'SETPL: Problem with rxn # ',i4 ) + CALL GEOS_CHEM_STOP + ENDIF + + ! Save reactants and products for this + ! reaction in IPLREAC for output below + IPLREAC(I,NNPL(N),N) = ITEMPREAC(I) + ENDDO + ENDIF + ENDDO + ENDIF + + !------------------------------- + ! Skip emission & drydep rxns + !------------------------------- + 150 CONTINUE + ENDDO + + !================================================================= + ! Write out prod or loss reactions to "smv2.log" + !================================================================= + WRITE( IO93, '(/,a)' ) REPEAT( '=', 79 ) + WRITE( IO93, '(a)' ) 'Here are the prod and loss reactions' + WRITE( IO93, '(a)' ) REPEAT( '=', 79 ) + + ! Loop over P/L diagnostic families + DO N = 1, NFAMILIES + + ! Write family header + WRITE( IO93, 587 ) NAMEGAS(IFAM(N)), PORL(N), NNPL(N) + 587 FORMAT( /, 'Family ',a5,' ',a4,' -- no of rxns is ',i3, 5x, + & 'coefficient') + + ! Loop over prod/loss reactions + DO I = 1, NNPL(N) + + ! Rxn number + NK = NKPL(I,N) + + ! Reactant indices + IREAC1 = IPLREAC(1,I,N) + IREAC2 = IPLREAC(2,I,N) + + ! Product indices + IPROD1 = IPLREAC( NPRODLO, I,N) + IPROD2 = IPLREAC((NPRODLO+1),I,N) + IPROD3 = IPLREAC((NPRODLO+2),I,N) + + ! Character to denote 3 or more products + EXTRACHAR = ' ' + IF ( IPROD3 .GT. 0 ) EXTRACHAR = '+ ...' + + ! Test for kinetic or photo rxns + IF ( NK .LE. NRATES(NCS) ) THEN + + !---------------------- + ! Write kinetic rxns + !---------------------- + WRITE(IO93,588) I, NK, NAMEGAS(IREAC1), + & NAMEGAS(IREAC2), NAMEGAS(IPROD1), + & NAMEGAS(IPROD2), EXTRACHAR, COEFPL(I,N) + + 588 FORMAT(I3,1X,I3,1X,A5,' + ',A5,' = ',A5,' + ',A5, + & A5,1X,ES13.6) + + ELSE + + !---------------------- + ! Write photo rxns + !---------------------- + WRITE(IO93,589) I, NK, NAMEGAS(IREAC1), + & NAMEGAS(IPROD1), NAMEGAS(IPROD2), + & EXTRACHAR, COEFPL(I,N) + + 589 FORMAT(I3,1X,I3,1X,A5,' + hv = ',A5,' + ',A5, + & A5,1X,1P1E13.6) + + ENDIF + +!### !### Debug +!### WRITE( 6, '(i4,1x,16(a,'':'')))' ) +!### & NK, ( TRIM(NAMEGAS(IRM(J,NK,NCS))), J=1,16 ) +!### WRITE( 6, '(i4,1x,4f4.1,''/'',12f4.1)' ) +!### & NK, ( FKOEF(J,NK,NCS), J=1,16 ) + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE SETPL + +!------------------------------------------------------------------------------ + + SUBROUTINE DO_DIAG_PL +! +!***************************************************************************** +! Subroutine DO_DIAG_PL saves info on production and loss of families +! into the FAM_PL diagnostic array. (bey, bmy, 3/16/00, 12/4/07) +! +! NOTES: +! (1 ) Now bundled into "prod_loss_diag_mod.f" (bmy, 7/20/04) +! (2 ) Now only loop up thru LD65 levels (bmy, 12/4/07) +! (3 ) Set FAM_PL to zero in the stratosphere (phs, 11/17/08) +!***************************************************************************** +! + ! References to F90 modules + USE COMODE_MOD, ONLY : CSPEC, JLOP + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! LD65 +# include "comode.h" ! SMVGEAR II arrays + + ! Local variables + INTEGER :: I, J, L, JLOOP, N + + !================================================================= + ! DO_DIAG_PL begins here! + ! + ! If ND65 is turned on, then archive P-L for specified families + ! and store in the AD65 array. + ! + ! Make sure that memory has already been allocated to arrays + ! FAMPL, JLOP, and CSPEC. + !================================================================= + + ! If we are not saving + IF ( .not. DO_SAVE_PL ) RETURN + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N, JLOOP ) +!$OMP+SCHEDULE( DYNAMIC ) + DO N = 1, NFAMILIES + DO L = 1, LD65 + DO J = 1, NLAT + DO I = 1, NLONG + + ! JLOOP is the 1-D grid box index for SMVGEAR arrays + JLOOP = JLOP(I,J,L) + + ! If this is a valid grid box + IF ( JLOOP > 0 ) THEN + + ! Copy the concentration for the "fake" prodloss family + ! (which have been appended to the SMVGEAR species list) + ! to the FAM_PL diagnostic array. Units are [molec/cm3/s]. + FAM_PL(I,J,L,N) = CSPEC(JLOOP,IFAM(N)) / CHEMINTV + + ! Zero each "fake" ND65 prod/loss family for next iteration + CSPEC(JLOOP,IFAM(N)) = 0.0d0 + + ! Also save into the AD65 diagnostic array + AD65(I,J,L,N) = AD65(I,J,L,N) + FAM_PL(I,J,L,N) + + ELSE + + ! avoid surprises in DIAG20, which uses all FAM_PL boxes + FAM_PL(I,J,L,N) = 0.0d0 + + ENDIF + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !================================================================= + ! Also call DIAG20, which will save out the P(Ox) and L(Ox) + ! from the fullchem simulation for a future tagged Ox run + !================================================================= + + IF ( DO_SAVE_O3 ) CALL DIAG20 + + ! Return to calling program + END SUBROUTINE DO_DIAG_PL + +!------------------------------------------------------------------------------ + + SUBROUTINE DIAG20 +! +!****************************************************************************** +! Subroutine DIAG20 computes production and loss rates of O3, and +! then calls subroutine WRITE20 to save the these rates to disk. +! (bey, bmy, 6/9/99, 12/4/07) +! +! By saving, the production and loss rates from a full-chemistry run, +! a user can use these archived rates to perform a quick O3 chemistry +! run at a later time. +! +! DIAG20 assumes that ND65 (P-L diagnostics) have been turned on. +! +! NOTES: +! (1 ) Now bundled into "diag20_mod.f" (bmy, 7/20/04) +! (2 ) Now also write to disk when it is the last timestep before the end of +! the run. Now references GET_TAUE from "time_mod.f". (bmy, 11/15/04) +! (3 ) Now call function ITS_TIME_FOR_WRITE20 to determine if the next +! chemistry timestep is the start of a new day. Remove reference +! to GET_TAUe and GET_TS_CHEM. Now archive P(Ox) and L(Ox) first +! and then test if we have to save the file to disk. (bmy, 3/3/05) +! (4 ) Now references XNUMOL from "tracer_mod.f" (bmy, 10/25/05) +! (5 ) Now use LLTROP_FIX instead of LLTROP (phs, 1/22/07) +! (6 ) Now use LD65 instead of LLTROP_FIX (phs, bmy, 12/4/07) +! (7 ) Now take care of boxes that switch b/w stratospheric and tropospheric +! regimes (phs, 11/17/08) +!****************************************************************************** +! + ! References to F90 modules + USE COMODE_MOD, ONLY : JLOP + USE DIRECTORY_MOD, ONLY : O3PL_DIR + USE ERROR_MOD, ONLY : ERROR_STOP + USE TIME_MOD, ONLY : EXPAND_DATE, GET_NYMD + USE TIME_MOD, ONLY : GET_TAU, GET_TAUb + USE TIME_MOD, ONLY : ITS_A_NEW_DAY, TIMESTAMP_STRING + USE TRACER_MOD, ONLY : STT, XNUMOL + USE TRACERID_MOD, ONLY : IDTOX + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! LD65 + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL :: DO_WRITE + INTEGER :: I, J, L, N, JLOOP + REAL*8 :: P_Ox, L_Ox + CHARACTER(LEN=16) :: STAMP + + !================================================================= + ! DIAG20 begins here! + !================================================================= + + ! Error check + IF ( IDTOX == 0 ) THEN + CALL ERROR_STOP( 'IDTOX = 0!', 'DIAG20 ("diag20_mod.f")' ) + ENDIF + + ! First-time initialization + IF ( FIRST ) THEN + + ! Starting time of run + TAUb = GET_TAUb() + + ! Get time of run at 1st timestep + TAU0 = TAUb + + ! Reset first-time flag + FIRST = .FALSE. + + ENDIF + + !================================================================= + ! Archive P(Ox) and L(Ox) over the course of an entire day + !================================================================= + + ! Echo info + STAMP = TIMESTAMP_STRING() + WRITE( 6, 120 ) STAMP + 120 FORMAT( ' - DIAG20: Archiving P(Ox) & L(Ox) at ', a ) + + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, P_Ox, L_Ox, JLOOP ) + DO L = 1, LD65 + DO J = 1, JJPAR + DO I = 1, IIPAR + + !------------- + ! Counter + !------------- + + ! JLOOP is the 1-D grid box index for SMVGEAR arrays + JLOOP = JLOP(I,J,L) + + ! If this is a valid grid box, increment counter + IF ( JLOOP > 0 ) COUNT(I,J,L) = COUNT(I,J,L) + 1 + + !------------- + ! Production + !------------- + + ! Convert P(Ox) from [molec/cm3/s] to [kg/cm3/s] + P_Ox = FAM_PL(I,J,L,1) / XNUMOL(IDTOX) + + ! Store P(Ox) [kg/cm3/s] in PL24H array + PL24H(I,J,L,1) = PL24H(I,J,L,1) + P_Ox + + !------------- + ! Loss + !------------- + + ! Convert Ox mass from [kg] to [molec] + L_Ox = STT(I,J,L,IDTOX) * XNUMOL(IDTOX) + + ! Divide L(Ox) [molec/cm3/s] by Ox mass [molec] + ! in order to get L(Ox) in [1/cm3/s] + L_Ox = FAM_PL(I,J,L,2) / L_Ox + + ! Store L(Ox) [1/cm3/s] in PL24H array + PL24H(I,J,L,2) = PL24H(I,J,L,2) + L_Ox + + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !================================================================= + ! Write data to disk and zero counters for next timestep + !================================================================= + + ! Check to see if the next chemistry timestep is the start of a + ! new day. If so then we need to write to disk. (bmy, 3/3/05) + IF ( ITS_TIME_FOR_WRITE20( TAU1 ) ) THEN + + ! Compute average daily values +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N ) + DO N = 1, 2 + DO L = 1, LD65 + DO J = 1, JJPAR + DO I = 1, IIPAR + IF ( COUNT(I,J,L) /= 0 ) + $ PL24H(I,J,L,N) = PL24H(I,J,L,N) / COUNT(I,J,L) + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Get YYYYMMDD date for this day + YYYYMMDD = GET_NYMD() + + ! Replace YYYYMMDD in filename w/ the actual date + FILENAME = 'rate.YYYYMMDD' + CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) + + ! Then prefix FILENAME w/ the data directory name + FILENAME = TRIM( O3PL_DIR ) // FILENAME + + ! Echo info + WRITE( 6, 110 ) TRIM( FILENAME ) + 110 FORMAT( ' - DIAG20: Writing ', a ) + + ! Write P(Ox) and L(Ox) to disk + CALL WRITE20 + +!------------------------------------------------------------ +! Prior to 10/26/09 +! Now just zero arrays w/o loop indices (dbj, bmy, 10/26/09) +! ! Zero counter +! COUNT(I,J,L) = 0 +! +! ! Zero PL24H array +!!$OMP PARALLEL DO +!!$OMP+DEFAULT( SHARED ) +!!$OMP+PRIVATE( I, J, L, N ) +! DO N = 1, 2 +! DO L = 1, LD65 +! DO J = 1, JJPAR +! DO I = 1, IIPAR +! PL24H(I,J,L,N) = 0d0 +! ENDDO +! ENDDO +! ENDDO +! ENDDO +!!$OMP END PARALLEL DO +!------------------------------------------------------------ + + ! Zero arrays + COUNT = 0 + PL24H = 0d0 + + ! Reset for the next day + TAU0 = TAU1 + ENDIF + + ! Return to calling program + END SUBROUTINE DIAG20 + +!------------------------------------------------------------------------------ + + SUBROUTINE WRITE20 +! +!****************************************************************************** +! Subroutine WRITE20 saves production and loss rates to disk, where they +! will be later read by subroutine CHEMO3. (bey, bmy, 6/9/99, 12/4/07) +! +! NOTES: +! (1 ) Now bundled into "diag20_mod.f" (bmy, 7/20/04) +! (2 ) Bug fix: remove declaration of FILENAME which masked the global +! declaration (bmy, 11/15/04) +! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (4 ) Now only write up to LD65 levels (phs, bmy, 12/4/07) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : BPCH2, GET_HALFPOLAR + USE BPCH2_MOD, ONLY : GET_MODELNAME, OPEN_BPCH2_FOR_WRITE + USE FILE_MOD, ONLY : IU_ND20 + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! LD65 + + ! Local variables + INTEGER :: I, J, L, N, IOS + INTEGER :: IFIRST, JFIRST, LFIRST + INTEGER :: HALFPOLAR + INTEGER, PARAMETER :: CENTER180 = 1 + REAL*4 :: LONRES, LATRES + REAL*4 :: ARRAY(IIPAR,JJPAR,LLTROP) + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=40) :: RESERVED + CHARACTER(LEN=80) :: TITLE + + !================================================================= + ! WRITE20 begins here! + !================================================================= + + ! Define various parameters for the BPCH file + TITLE = 'GEOS-CHEM archived P(O3) and L(O3) rates for Tag Ox' + CATEGORY = 'PORL-L=$' + RESERVED = '' + LONRES = DISIZE + LATRES = DJSIZE + MODELNAME = GET_MODELNAME() + HALFPOLAR = GET_HALFPOLAR() + IFIRST = 1 + GET_XOFFSET( GLOBAL=.TRUE. ) + JFIRST = 1 + GET_YOFFSET( GLOBAL=.TRUE. ) + LFIRST = 1 + + ! Open BPCH file for writing + CALL OPEN_BPCH2_FOR_WRITE( IU_ND20, FILENAME, TITLE ) + + !================================================================= + ! Save P(O3) to disk + !================================================================= + + ! Cast to REAL*4 +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) + DO L = 1, LD65 + DO J = 1, JJPAR + DO I = 1, IIPAR + ARRAY(I,J,L) = PL24H(I,J,L,1) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Unit string + UNIT = 'kg/cm3/s' + + ! Save P(O3) to BPCH file + CALL BPCH2( IU_ND20, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 1, + & UNIT, TAU0, TAU1, RESERVED, + & IIPAR, JJPAR, LD65 , IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD65) ) + + !================================================================= + ! Save L(O3) to disk + !================================================================= + + ! Cast to REAL*4 +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L ) + DO L = 1, LD65 + DO J = 1, JJPAR + DO I = 1, IIPAR + ARRAY(I,J,L) = PL24H(I,J,L,2) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Unit string + UNIT = '1/cm3/s' + + ! Save L(O3) to BPCH file + CALL BPCH2( IU_ND20, MODELNAME, LONRES, LATRES, + & HALFPOLAR, CENTER180, CATEGORY, 2, + & UNIT, TAU0, TAU1, RESERVED, + & IIPAR, JJPAR, LD65, IFIRST, + & JFIRST, LFIRST, ARRAY(:,:,1:LD65) ) + + ! Close BPCH file + CLOSE( IU_ND20 ) + + ! Return to calling program + END SUBROUTINE WRITE20 + +!------------------------------------------------------------------------------ + + FUNCTION ITS_TIME_FOR_WRITE20( TAU_W ) RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function ITS_TIME_FOR_WRITE_DIAG51 returns TRUE if it's time to write +! the ND20 ozone P/L rate file to disk. We test the time at the next +! chemistry timestep so that we can write to disk properly. +! (bmy, 3/3/05) +! +! Arguments as Output: +! ============================================================================ +! (1 ) TAU_W (REAL*8) : TAU value at time of writing to disk +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_HOUR, GET_MINUTE, GET_TAU + USE TIME_MOD, ONLY : GET_TAUb, GET_TAUe, GET_TS_CHEM, GET_TS_DYN + + ! Arguments + REAL*8, INTENT(OUT) :: TAU_W + + ! Local variables + LOGICAL :: ITS_TIME + REAL*8 :: TAU, HOUR, CHEM, DYN + + !================================================================= + ! ITS_TIME_FOR_WRITE20 begins here! + !================================================================= + + ! Initialize + ITS_TIME = .FALSE. + + ! Current TAU, Hour, and Dynamic Timestep [hrs] + TAU = GET_TAU() + HOUR = ( GET_MINUTE() / 60d0 ) + GET_HOUR() + CHEM = ( GET_TS_CHEM() / 60d0 ) + DYN = ( GET_TS_DYN() / 60d0 ) + + ! If first timestep, return FALSE + IF ( TAU == GET_TAUb() ) RETURN + + ! If the next chemistry timestep is the hour of day + ! when we have to save to disk, return TRUE + IF ( MOD( HOUR + CHEM, 24d0 ) == 0 ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + CHEM + RETURN + ENDIF + + ! If the next dyn timestep is the + ! end of the run, return TRUE + IF ( TAU + DYN == GET_TAUe() ) THEN + ITS_TIME = .TRUE. + TAU_W = TAU + DYN + RETURN + ENDIF + + ! Return to calling program + END FUNCTION ITS_TIME_FOR_WRITE20 + +!------------------------------------------------------------------------------ + + FUNCTION GET_NFAM() RESULT( N_FAM ) +! +!****************************************************************************** +! Function GET_NFAM returns the number of defined P/L families. (bmy, 5/2/05) +! +! NOTES: +!****************************************************************************** +! + ! Local variables + INTEGER :: N_FAM + + !================================================================= + ! GET_N_FAM begins here! + !================================================================= + N_FAM = NFAM + + ! Return to calling program + END FUNCTION GET_NFAM + +!------------------------------------------------------------------------------ + + FUNCTION GET_FAM_NAME( N ) RESULT( NAME ) +! +!****************************************************************************** +! Function GET_FAM_NAME returns the name of the Nth P/L family. (bmy, 5/2/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) N (INTEGER) : Number of the P/L family for which to return the name +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP + + ! Arguments + INTEGER, INTENT(IN) :: N + + ! Local variables + CHARACTER(LEN=255) :: MSG, NAME + + !================================================================= + ! GET_FAM_NAME begins here! + !================================================================= + + ! Error check + IF ( N < 1 .or. N > NFAM ) THEN + MSG = 'Invalid ND65 family number!' + CALL ERROR_STOP( MSG, 'GET_FAM_NAME ("diag_pl_mod.f")' ) + ENDIF + + ! Get name + NAME = TRIM( FAM_NAME( N ) ) + + ! Return to calling program + END FUNCTION GET_FAM_NAME + +!------------------------------------------------------------------------------ + + FUNCTION GET_FAM_MWT( N ) RESULT( MWT ) +! +!****************************************************************************** +! Function GET_FAM_NAME returns the name of the Nth P/L family. (bmy, 5/2/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) N (INTEGER) : Number of the P/L family for which to return the name +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE CHARPAK_MOD, ONLY : TRANUC + USE ERROR_MOD, ONLY : ERROR_STOP + USE TRACER_MOD, ONLY : N_TRACERS, TRACER_MW_KG, TRACER_NAME + + ! Arguments + INTEGER, INTENT(IN) :: N + + ! Local variables + INTEGER :: T + REAL*8 :: MWT + CHARACTER(LEN=255) :: MSG, PL_NAME, T_NAME + + !================================================================= + ! GET_FAM_NAME begins here! + !================================================================= + + ! Error check + IF ( N < 1 .or. N > NFAM ) THEN + MSG = 'Invalid ND65 family number!' + CALL ERROR_STOP( MSG, 'GET_FAM_MWT ("diag_pl_mod.f")' ) + ENDIF + + ! Initialize the MWT + MWT = 0d0 + + ! Get name of this P/L family + PL_NAME = TRIM( FAM_NAME( N ) ) + + ! Convert to uppercase + CALL TRANUC( PL_NAME ) + + ! Skip the 1st character, which is always P or l + PL_NAME = PL_NAME( 2:LEN_TRIM( PL_NAME ) ) + + !================================================================= + ! Match the name of the P/L family with the GEOS-CHEM tracer name + ! so that we can find the molecular weight. This scheme assumes + ! that each P/L family is a transported tracer. This may not + ! always be true but this is a quick & dirty assumption. + !================================================================= + + ! Loop over all CTM tracers + DO T = 1, N_TRACERS + + ! Tracer name + T_NAME = TRACER_NAME( T ) + + ! Convert to uppercase + CALL TRANUC( T_NAME ) + + ! If we have a name match, return the molecular wt + IF ( TRIM( PL_NAME ) == TRIM( T_NAME ) ) THEN + MWT = TRACER_MW_KG( T ) + EXIT + ENDIF + ENDDO + + ! Return to calling program + END FUNCTION GET_FAM_MWT + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DIAG_PL( DOPL, SAVEO3, N_FAM, NAME, + & TYPE, NMEM, MEMB, COEF ) +! +!****************************************************************************** +! Subroutine INIT_DIAG_PL takes values read from the GEOS-CHEM input file +! and saves to module variables w/in "diag65_mod.f" (bmy, 7/20/04, 12/4/07) +! +! Arguments as Input: +! ============================================================================ +! (1 ) N_FAM (INTEGER ) : Number of prod/loss families +! (1 ) NAME (CHARACTER) : Prod/loss family name +! (2 ) TYPE (CHARACTER) : Prod/loss family type +! (3 ) NMEM (INTEGER ) : Number of members w/in the prod/loss family +! (4 ) MEMB (CHARACTER) : Names for each prod/loss family member +! (5 ) COEF (REAL*8 ) : Coefficients for each prod/loss family member +! +! NOTES: +! (1 ) Now allocate arrays up to LD65 levels (phs, bmy, 12/4/07) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE TRACER_MOD, ONLY : ITS_A_FULLCHEM_SIM + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! ND65, LD65 +# include "comode.h" ! LFAMILY, NFAMILIES + + ! Arguments + LOGICAL, INTENT(IN) :: DOPL, SAVEO3 + INTEGER, INTENT(IN) :: N_FAM + INTEGER, INTENT(IN) :: NMEM(MAXFAM) + REAL*8, INTENT(IN) :: COEF(MAXMEM,MAXFAM) + CHARACTER(LEN=14), INTENT(IN) :: NAME(MAXFAM) + CHARACTER(LEN=14), INTENT(IN) :: TYPE(MAXFAM) + CHARACTER(LEN=14), INTENT(IN) :: MEMB(MAXMEM,MAXFAM) + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DIAG65 begins here! + !================================================================= + + ! Turn on prod loss diagnostic? + DO_SAVE_PL = DOPL + + ! Save out P(Ox), L(Ox) for future tagged Ox simulation? + DO_SAVE_O3 = SAVEO3 + + ! Number of prod/loss families + NFAM = N_FAM + + ! Define NFAMILIES from "comode.h" for backwards compatibility + NFAMILIES = NFAM + + ! Define LFAMILY from "comode.h" for backwards compatibility + LFAMILY = ( DO_SAVE_PL .and. NFAM > 0 ) + + ! Return if there are no prod/loss families + ! or if we have turned off this diagnostic + IF ( .not. LFAMILY ) THEN + DO_SAVE_PL = .FALSE. + DO_SAVE_O3 = .FALSE. + NFAMILIES = 0 + NFAM = 0 + ND65 = 0 + RETURN + ENDIF + + ! Define number of vertical levels to save + IF ( ITS_A_FULLCHEM_SIM() ) THEN + LD65 = MIN( ND65, LLTROP ) + ELSE + LD65 = MIN( ND65, LLPAR ) + ENDIF + + !================================================================= + ! Allocate arrays + !================================================================= + ALLOCATE( AD65( IIPAR, JJPAR, LD65, NFAM ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'AD65' ) + + ALLOCATE( FAM_NMEM( MAXFAM ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FAM_NMEM' ) + FAM_NMEM = 0 + + ALLOCATE( FAM_COEF( MAXMEM, MAXFAM ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FAM_COEF' ) + FAM_COEF = 0d0 + + ALLOCATE( FAM_NAME( MAXFAM ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FAM_NAME' ) + FAM_NAME = '' + + ALLOCATE( FAM_TYPE( MAXFAM ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FAM_TYPE' ) + FAM_TYPE = '' + + ALLOCATE( FAM_MEMB( MAXMEM, MAXFAM ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FAM_COEF' ) + FAM_MEMB = '' + + ALLOCATE( COUNT( IIPAR, JJPAR, LD65 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'COUNT' ) + COUNT = 0 + + ! Only allocate FAM_PL for a fullchem simulation + IF ( ITS_A_FULLCHEM_SIM() ) THEN + ALLOCATE( FAM_PL( IIPAR, JJPAR, LD65, NFAM ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FAM_PL' ) + ENDIF + + ! Allocate PL24H if we are also saving out the P(Ox) + ! and L(Ox) + IF ( DO_SAVE_O3 ) THEN + ALLOCATE( PL24H( IIPAR, JJPAR, LD65, 2 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'PL24H' ) + PL24H = 0d0 + ENDIF + + !================================================================= + ! Assign values from read from GEOS-CHEM input file + !================================================================= + FAM_NMEM(:) = NMEM(:) + FAM_COEF(:,:) = COEF(:,:) + FAM_NAME(:) = NAME(:) + FAM_TYPE(:) = TYPE(:) + FAM_MEMB(:,:) = MEMB(:,:) + + ! End of calling program + END SUBROUTINE INIT_DIAG_PL + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DIAG_PL +! +!****************************************************************************** +! Subroutine CLEANUP_DIAG_PL deallocates all module arrays. (bmy, 7/20/04) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DIAG65 begins here! + !================================================================= + IF ( ALLOCATED( AD65 ) ) DEALLOCATE( AD65 ) + IF ( ALLOCATED( FAM_COEF ) ) DEALLOCATE( FAM_COEF ) + IF ( ALLOCATED( FAM_NAME ) ) DEALLOCATE( FAM_NAME ) + IF ( ALLOCATED( FAM_NMEM ) ) DEALLOCATE( FAM_NMEM ) + IF ( ALLOCATED( FAM_MEMB ) ) DEALLOCATE( FAM_MEMB ) + IF ( ALLOCATED( FAM_PL ) ) DEALLOCATE( FAM_PL ) + IF ( ALLOCATED( FAM_TYPE ) ) DEALLOCATE( FAM_TYPE ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DIAG_PL + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DIAG_PL_MOD diff --git a/code/diagoh.f b/code/diagoh.f new file mode 100644 index 0000000..c0b02e7 --- /dev/null +++ b/code/diagoh.f @@ -0,0 +1,86 @@ +! $Id: diagoh.f,v 1.1 2009/06/09 21:51:51 daven Exp $ + SUBROUTINE DIAGOH +! +!****************************************************************************** +! Subroutine DIAGOH saves chemical diagnostic quantities for +! the ND43 chemical diagnostics. (bmy, 5/1/98, 1/13/03) +! +! NOTES: +! (1 ) Now use F90 syntax for declarations (bmy, 3/29/99) +! (2 ) Cosmetic changes (bmy, 3/29/99) +! (3 ) AD43 and DIAGCHLORO are now declared allocatable in "diag_mod.f". +! Also eliminate obsolete code. (bmy, 11/29/99) +! (4 ) LTNO, LTOH are now allocatable arrays in "diag_mod.f" (bmy, 3/17/00) +! (5 ) Don't save OH into STT(:,:,:NTRACER+2) anymore. The SAVEOH +! array is now used to save OH concentrations for diagnostics. +! Also revised out-of-date comments. (bmy, 4/24/00) +! (6 ) Also save out NO2 and HO2 for use w/ the ND43 diagnostic. +! Now also reference LTNO2, LTHO2 arrays from "diag_mod.f". +! Updated comments, cosmetic changes. (rvm, bmy, 2/27/02) +! (7 ) Removed obsolete reference to DIAGCHLORO (bmy, 8/2/02) +! (8 ) Now save NO3 [molec/cm3] as AD43(:,:,:,5) (bmy, 1/13/03) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY: AD43, LTNO, LTOH, LTNO2, LTHO2, LTNO3 + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! Diagnostic switches & arrays +# include "CMN_O3" ! SAVEOH, SAVENO + + ! Local variables + INTEGER :: I, J, L + REAL*8 :: OH, NO, HO2, NO2, NO3 + + !================================================================= + ! DIAGOH begins here! + ! + ! ND43 diagnostic: Save OH, HO2, NO3 between HR1_OH and HR2_OH + ! Save NO, NO2 between times HR1_NO and HR2_NO + ! + ! Store the following chemical diagnostics into the AD43 array: + ! AD43(:,:,:,1) = OH [molec/cm3/s] + ! AD43(:,:,:,2) = NO [v/v] + ! AD43(:,:,:,3) = HO2 [v/v] + ! AD43(:,:,:,4) = NO2 [v/v] + ! AD43(:,:,:,5) = NO3 [v/v] + !================================================================= + IF ( ND43 > 0 ) THEN + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, OH, NO, HO2, NO2, NO3 ) + DO L = 1, LD43 + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Save OH as AD43(:,:,:,1) + OH = SAVEOH(I,J,L) * LTOH(I,J) + AD43(I,J,L,1) = AD43(I,J,L,1) + OH + + ! Save NO as AD43(:,:,:,2) + NO = SAVENO(I,J,L) * LTNO(I,J) + AD43(I,J,L,2) = AD43(I,J,L,2) + NO + + ! Save HO2 as AD43(:,:,:,3) + HO2 = SAVEHO2(I,J,L) * LTHO2(I,J) + AD43(I,J,L,3) = AD43(I,J,L,3) + HO2 + + ! Save NO2 as AD43(:,:,:,4) + NO2 = SAVENO2(I,J,L) * LTNO2(I,J) + AD43(I,J,L,4) = AD43(I,J,L,4) + NO2 + + ! Save NO3 as AD43(:,:,:,5) + NO3 = SAVENO3(I,J,L) * LTNO3(I,J) + AD43(I,J,L,5) = AD43(I,J,L,5) + NO3 + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ENDIF + + ! Return to calling program + END SUBROUTINE DIAGOH diff --git a/code/directory_mod.f b/code/directory_mod.f new file mode 100644 index 0000000..f9295d8 --- /dev/null +++ b/code/directory_mod.f @@ -0,0 +1,53 @@ +! $Id: directory_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE DIRECTORY_MOD +! +!****************************************************************************** +! Module DIRECTORY_MOD contains the directory path variables used by +! GEOS-CHEM. (bmy, 7/20/04, 10/24/05) +! +! Module Variables: +! ============================================================================ +! (1 ) DATA_DIR (CHAR*255) : Main DAO met field directory +! (2 ) DATA_DIR_1x1 (CHAR*255) : Root data dir for 1x1 emission fields +! (2 ) GCAP_DIR (CHAR*255) : Subdir where GCAP met data are stored +! (3 ) GEOS_1_DIR (CHAR*255) : Subdir where GEOS-1 met data are stored +! (4 ) GEOS_S_DIR (CHAR*255) : Subdir where GEOS-STRAT met data are stored +! (5 ) GEOS_3_DIR (CHAR*255) : Subdir where GEOS-3 met data are stored +! (6 ) GEOS_4_DIR (CHAR*255) : Subdir where GEOS-4 met data are stored +! (7 ) GEOS_5_DIR (CHAR*255) : Subdir where GEOS-5 met data are stored +! (8 ) TEMP_DIR (CHAR*255) : Temporary directory for unzipping met dat +! (9 ) RUN_DIR (CHAR*255) : Run directory for GEOS-CHEM +! (10) OH_DIR (CHAR*255) : Dir containing OH files are stored +! (11) O3PL_DIR (CHAR*255) : Dir containing archived O3 P/L rate files +! (12) TPBC_DIR (CHAR*255) : TPCORE boundary conditions dir (nested grid) +! +! NOTES: +! (1 ) Added variables GCAP_DIR and GEOS_5_DIR (swu, bmy, 5/25/05) +! (2 ) Added DATA_DIR_1x1 (bmy, 10/24/05) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE VARIABLES + !================================================================= + CHARACTER(LEN=255) :: DATA_DIR + CHARACTER(LEN=255) :: DATA_DIR_1x1 + CHARACTER(LEN=255) :: GCAP_DIR + CHARACTER(LEN=255) :: GEOS_1_DIR + CHARACTER(LEN=255) :: GEOS_S_DIR + CHARACTER(LEN=255) :: GEOS_3_DIR + CHARACTER(LEN=255) :: GEOS_4_DIR + CHARACTER(LEN=255) :: GEOS_5_DIR + CHARACTER(LEN=255) :: GEOS_FP_DIR !! (lzh,04/09/2014) + CHARACTER(LEN=255) :: TEMP_DIR + CHARACTER(LEN=255) :: RUN_DIR + CHARACTER(LEN=255) :: OH_DIR + CHARACTER(LEN=255) :: O3PL_DIR + CHARACTER(LEN=255) :: TPBC_DIR + CHARACTER(LEN=255) :: TPBC_DIR_NA ! (lzh, 02//01/2015, update nested runs) + CHARACTER(LEN=255) :: TPBC_DIR_EU + CHARACTER(LEN=255) :: TPBC_DIR_CH + + ! End of module + END MODULE DIRECTORY_MOD diff --git a/code/drydep_mod.f b/code/drydep_mod.f new file mode 100644 index 0000000..66a807f --- /dev/null +++ b/code/drydep_mod.f @@ -0,0 +1,4180 @@ +! $Id: drydep_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE DRYDEP_MOD +! +!****************************************************************************** +! Module DRYDEP_MOD contains variables and routines for the GEOS-CHEM dry +! deposition scheme. (bmy, 1/27/03, 9/18/07) +! +! Module Variables: +! ============================================================================ +! (1 ) MAXDEP (INTEGER) : Maximum number of drydep species +! (2 ) NNTYPE (INTEGER) : Max # of landtypes / grid box +! (3 ) NNPOLY (INTEGER) : Number of drydep polynomial coefficients +! (4 ) NNVEGTYPE(INTEGER) : Number of Olson land types +! (5 ) XCKMAN (REAL*8 ) : Von Karman constant? +! (6 ) DRYDHNO3 (INTEGER) : Internal flag for location of HNO3 in DEPVEL +! (7 ) DRYDNO2 (INTEGER) : Internal flag for location of NO2 in DEPVEL +! (8 ) DRYDPAN (INTEGER) : Internal flag for location of PAN in DEPVEL +! (9 ) NUMDEP (INTEGER) : Actual number of drydep species +! (10) NWATER (INTEGER) : Number of Olson's surface types that are water +! (11) AIROSOL (LOGICAL) : Array flags to denote aerosol drydep species +! (12) IDEP (INTEGER) : ID #'s for dry deposition surface types +! (13) IRAC (INTEGER) : ??? resistance for drydep land type +! (14) IRCLO (INTEGER) : ??? resistance for drydep land type +! (15) IRCLS (INTEGER) : ??? resistance for drydep land type +! (16) IRGSO (INTEGER) : ??? resistance for drydep land type +! (17) IRGSS (INTEGER) : ??? resistance for drydep land type +! (18) IRI (INTEGER) : Internal resistance for drydep land types +! (19) IRLU (INTEGER) : Cuticular resistance for drydep land types +! (20) IVSMAX (INTEGER) : ??? resistance for drydep land type +! (21) IWATER (INTEGER) : ID #'s for Olson surface types that are water +! (22) IZO (INTEGER) : Roughness heights for each Olson surface type +! (23) NDVZIND (INTEGER) : Index array for ordering drydep species in DEPVEL +! (24) NTRAIND (INTEGER) : Stores tracer numbers of drydep species +! (25) DEPSAV (REAL*8 ) : Array containing dry deposition frequencies [s-1] +! (26) PBLFRAC (REAL*8 ) : Array for multiplicative factor for drydep freq +! (27) DRYCOEFF (REAL*8 ) : Polynomial coefficients for dry deposition +! (28) HSTAR (REAL*8 ) : Henry's law constant +! (29) F0 (REAL*8 ) : Reactivity factor for biological oxidation +! (30) XMW (REAL*8 ) : Molecular weight of drydep species [kg] +! (32) A_RADI (REAL*8 ) : Radius of aerosol for size-resolved drydep [um] +! (33) A_DEN (REAL*8 ) : Density of aerosol for size-res'd drydep [kg/m3] +! (33) DEPNAME (CHAR*14) : Names of dry deposition species +! +! Module Routines: +! ============================================================================ +! (1 ) DO_DRYDEP : Dry deposition driver routine +! (2 ) DVZ_MINVAL : Sets minimum drydep velocities for SULFATE tracers +! (3 ) METERO : Computes meterological fields for dry deposition +! (4 ) DRYFLX : Applies drydep losses from SMVGEAR to tracer array +! (5 ) DRYFLXRnPbBe : Applies drydep losses to 210Pb and 7Be +! (6 ) DRYFLXH2HD : Applies drydep losses to H2 and HD +! (7 ) DEPVEL : Computes dry deposition velocities (by D. Jacob) +! (8 ) DIFFG : Computes diffusion coefficient for a gas +! (9 ) MODIN : Reads inputs for DEPVEL from "drydep.table" +! (10) RDDRYCF : Reads drydep polynomial coeffs from "drydep.coef" +! (11) AERO_SFCRSI : Computes dust sfc resistance ff Seinfeld et al 86 +! (12) AERO_SFCRSII : Conputes dust sfc resistance ff Zhang et al 2001 +! (13) INIT_DRYDEP : Initializes and allocates module arrays +! (14) CLEANUP_DRYDEP : Deallocates module arrays +! +! GEOS-CHEM modules referenced by "drydep_mod.f": +! ============================================================================ +! (1 ) comode_mod.f : Module w/ SMVGEAR allocatable arrays +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) diag_mod.f : Module w/ GEOS-CHEM diagnostic arrays +! (4 ) directory_mod.f : Module w/ GEOS-CHEM data & met field dirs +! (4 ) error_mod.f : Module w/ NaN, other error check routines +! (5 ) file_mod.f : Module w/ file unit #'s and error checks +! (6 ) logical_mod.f : Module w/ GEOS-CHEM logical switches +! (7 ) pbl_mix_mod.f : Module w/ routines for PBL height & mixing +! (8 ) pressure_mod.f : Module w/ routines to compute P(I,J,L) +! (9 ) tracer_mod.f : Module w/ GEOS-CHEM tracer array etc. +! (10) tracerid_mod.f : Module w/ pointers to tracers & emissions +! +! References: +! ============================================================================ +! (1 ) Baldocchi, D.D., B.B. Hicks, and P. Camara, "A canopy stomatal +! resistance model for gaseous deposition to vegetated surfaces", +! Atmos. Environ. 21, 91-101, 1987. +! (2 ) Brutsaert, W., "Evaporation into the Atmosphere", Reidel, 1982. +! (3 ) Businger, J.A., et al., "Flux-profile relationships in the atmospheric +! surface layer", J. Atmos. Sci., 28, 181-189, 1971. +! (4 ) Dwight, H.B., "Tables of integrals and other mathematical data", +! MacMillan, 1957. +! (5 ) Guenther, A., and 15 others, A global model of natural volatile +! organic compound emissions, J. Geophys. Res., 100, 8873-8892, 1995. +! (6 ) Hicks, B.B., and P.S. Liss, "Transfer of SO2 and other reactive +! gases across the air-sea interface", Tellus, 28, 348-354, 1976. +! (7 ) Jacob, D.J., and S.C. Wofsy, "Budgets of reactive nitrogen, +! hydrocarbons, and ozone over the Amazon forest during the wet season", +! J. Geophys. Res., 95, 16737-16754, 1990. +! (8 ) Jacob, D.J., et al, "Deposition of ozone to tundra", J. Geophys. Res., +! 97, 16473-16479, 1992. +! (9 ) Levine, I.N., "Physical Chemistry, 3rd ed.", McGraw-Hill, +! New York, 1988. +! (10) Munger, J.W., et al, "Atmospheric deposition of reactive nitrogen +! oxides and ozone in a temperate deciduous forest and a sub-arctic +! woodland", J. Geophys. Res., in press, 1996. +! (11) Walcek, C.J., R.A. Brost, J.S. Chang, and M.L. Wesely, "SO2, sulfate, +! and HNO3 deposition velocities computed using regional landuse and +! meteorological data", Atmos. Environ., 20, 949-964, 1986. +! (12) Wang, Y.H., paper in preparation, 1996. +! (13) Wesely, M.L, "Improved parameterizations for surface resistance to +! gaseous dry deposition in regional-scale numerical models", +! Environmental Protection Agency Report EPA/600/3-88/025, +! Research Triangle Park (NC), 1988. +! (14) Wesely, M. L., Parameterization of surface resistance to gaseous dry +! deposition in regional-scale numerical models. Atmos. Environ., 23 +! 1293-1304, 1989. +! (15) Price, H., L. Jaeglé, A. Rice, P. Quay, P.C. Novelli, R. Gammon, +! Global Budget of Molecular Hydrogen and its Deuterium Content: +! Constraints from Ground Station, Cruise, and Aircraft Observations, +! submitted to J. Geophys. Res., 2007. +!! +! NOTES: +! (1 ) Bug fix: Do not assume NO2 is the 2nd drydep species. This causes +! a mis-indexing for CANOPYNOX. Now archive ND44 diagnostic in kg for +! Radon runs in routine DRYFLXRnPbBe; convert to kg/s in diag3.f +! (bmy, 1/27/03) +! (2 ) Now references "grid_mod.f" and the new "time_mod.f". Renamed DRYDEP +! routine to DO_DRYDEP for consistency w/ other drivers called from +! the MAIN program. (bmy, 2/11/03) +! (3 ) Added error check in DRYFLX for SMVGEAR II (bmy, 4/28/03) +! (4 ) Added drydep of N2O5. Now added PBLFRAC array, which is the fraction +! of each level below the PBL top. Also now compute drydep throughout +! the entire PBL, in order to prevent short-lived species such as HNO3 +! from being depleted in the shallow GEOS-3 surface layer. +! (rjp, bmy, 7/21/03) +! (5 ) Bug fix for GEOS-4 in DRYFLXRnPbBe (bmy, 12/2/03) +! (6 ) Now made CFRAC, RADIAT local variables in DO_DRYDEP (bmy, 12/9/03) +! (7 ) Now enclose AD44 in !$OMP CRITICAL block for drydep flux (bmy, 3/24/04) +! (8 ) Now handle extra carbon & dust tracers (rjp, tdf, bmy, 4/1/04) +! (9 ) Added routines AERO_SFCRS1, AERO_SFCRSII. Increased MAXDEP to 25. +! Now handles extra carbon & dust tracers. (rjp, tdf, bmy, 4/1/04) +! (10) Increased MAXDEP to 26. Added A_RADI and A_DEN module variables. +! Other modifications for size-resolved drydep. (rjp, bec, bmy, 4/20/04) +! (11) Increased MAXDEP to 35 and handle extra SOA tracers (rjp, bmy, 7/13/04) +! (12) Now references "logical_mod.f", "directory_mod.f", and "tracer_mod.f" +! (bmy, 7/20/04) +! (13) Add Hg2, HgP as drydep tracers (eck, bmy, 12/8/04) +! (14) Updated for AS, AHS, LET, NH4aq, SO4aq (cas, bmy, 1/6/05) +! (15) Now references "pbl_mix_mod.f". Removed PBLFRAC array. (bmy, 2/22/05) +! (16) Now include SO4s, NITs tracers. Now accounts for hygroscopic growth +! of seasalt aerosols when computing aerodynamic resistances. +! (bec, bmy, 4/13/05) +! (17) Now modified for GEOS-5 and GCAP met fields (bmy, 5/25/05) +! (18) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (19) Now change Reynold's # criterion from 1 to 0.1 in DEPVEL. Also +! change Henry's law constant for Hg2. Also increase MAXDEP from +! 35 to 37. (eck, djj, bmy, 2/1/06) +! (20) Bug fix in INIT_DRYDEP (bmy, 4/17/06) +! (21) Now bundle function DIFFG into "drydep_mod.f". Also updated for SOG4 +! and SOA4 tracers. Bug fix in INIT_DRYDEP. (dkh, bmy, 5/24/06) +! (22) Fix typo in INIT_DRYDEP (dkh, bmy, 6/23/06) +! (23) Add H2 and HD as drydep tracers. Added subroutine DRYFLXH2HD for H2HD +! offline sim (phs, 9/18/07) +! (24) Extra error check for small RH in AERO_SFCRII (phs, 6/11/08) +! (25) Added 15 more dry deposition species (tmf, 7/31/08) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these variables ... + PUBLIC :: DEPNAME + PUBLIC :: DEPSAV + PUBLIC :: MAXDEP + PUBLIC :: NUMDEP + PUBLIC :: NTRAIND + PUBLIC :: SHIPO3DEP + + ! ... and these routines + PUBLIC :: CLEANUP_DRYDEP + PUBLIC :: DO_DRYDEP + PUBLIC :: DRYFLX + PUBLIC :: DRYFLXH2HD + PUBLIC :: DRYFLXRnPbBe + PUBLIC :: DVZ_MINVAL + PUBLIC :: INIT_DRYDEP + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Parameters + INTEGER, PARAMETER :: MAXDEP = 50 + INTEGER, PARAMETER :: NNTYPE = 15 ! NTYPE from "CMN_SIZE" + INTEGER, PARAMETER :: NNPOLY = 20 ! NPOLY from "CMN_SIZE" + INTEGER, PARAMETER :: NNVEGTYPE = 74 ! NVEGTYPE from "CMN_SIZE" + REAL*8, PARAMETER :: XCKMAN = 0.4d0 + + ! Scalars + INTEGER :: DRYDHNO3, DRYDNO2, DRYDPAN + INTEGER :: NUMDEP, NWATER + ! Add max number of radius bins for sea salt (jaegle 5/11/11) + INTEGER, PARAMETER :: NR_MAX = 200 + + ! Arrays + LOGICAL :: AIROSOL(MAXDEP) + INTEGER :: IDEP(NNVEGTYPE) + INTEGER :: IRAC(NNTYPE) + INTEGER :: IRCLO(NNTYPE) + INTEGER :: IRCLS(NNTYPE) + INTEGER :: IRGSS(NNTYPE) + INTEGER :: IRGSO(NNTYPE) + INTEGER :: IRI(NNTYPE) + INTEGER :: IRLU(NNTYPE) + INTEGER :: IVSMAX(NNTYPE) + INTEGER :: IZO(NNVEGTYPE) + INTEGER :: IWATER(NNVEGTYPE) + INTEGER :: NDVZIND(MAXDEP) + INTEGER :: NTRAIND(MAXDEP) + REAL*8, ALLOCATABLE :: DEPSAV(:,:,:) + REAL*8 :: DRYCOEFF(NNPOLY) + REAL*8 :: HSTAR(MAXDEP) + REAL*8 :: F0(MAXDEP) + REAL*8 :: XMW(MAXDEP) + REAL*8 :: A_RADI(MAXDEP) + REAL*8 :: A_DEN(MAXDEP) + CHARACTER(LEN=14) :: DEPNAME(MAXDEP) + ! Add arrays for diameters and volume distribution of sea salt aerosols + ! (jaegle 5/11/11) + REAL*8, ALLOCATABLE :: DMID(:) + REAL*8, ALLOCATABLE :: SALT_V(:) + + ! Allocatable arrays + REAL*8, ALLOCATABLE :: SHIPO3DEP(:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DO_DRYDEP +! +!****************************************************************************** +! Subroutine DO_DRYDEP is the driver for the GEOS-CHEM dry deposition scheme. +! DO_DRYDEP calls DEPVEL to compute deposition velocities [m/s], which are +! then converted to [cm/s]. Drydep frequencies are also computed. +! (lwh, gmg, djj, 1989, 1994; bmy, 2/11/03, 5/25/05) +! +! DAO met fields passed via "dao_mod.f": +! ============================================================================ +! (1 ) AD (REAL*8 ) : Array for dry air mass at each grid box [kg] +! (2 ) AZO (REAL*8 ) : Array for surface roughness heights [m] +! (3 ) ALBD (REAL*8 ) : Array for surface albedo [m] +! (5 ) SUNCOS (REAL*8 ) : Array for COSINE( solar zenith angle ) [unitless] +! (6 ) T (REAL*8 ) : Array for grid box temperature [K] +! (7 ) USTAR (REAL*8 ) : Array for grid box friction velocity [m/s] +! +! Other important quantities: +! ============================================================================ +! (1 ) LSNOW (LOGICAL) : Array to flag whether there is snow/ice on the sfc. +! (2 ) CZ1 (REAL*8 ) : Midpoint height of first model level [m] +! (3 ) OBK (REAL*8 ) : Array for Monin-Obhukov Length [m] +! (4 ) TC0 (REAL*8 ) : Array for grid box surface temperature [K] +! (5 ) ZH (REAL*8 ) : Array for PBL heights at each grid box [m] +! (6 ) DVEL (REAL*8 ) : Array containing drydep velocities [m/s] +! (7 ) CFRAC (REAL*8 ) : Array containing column cloud frac [unitless] +! (8 ) RADIAT (REAL*8 ) : Array containing solar radiation [W/m2] +! (9 ) RHB (REAL*8 ) : Array containing relative humidity [unitless] +! +! References (see full citations above): +! ============================================================================ +! (1 ) Wesely, M. L., 1989 +! (2 ) Jacob, D.J., and S.C. Wofsy, 1990 +! +! NOTES: +! (1 ) Remove SUNCOS, USTAR, AZO, OBK from the arg list; now reference these +! as well as AD and T from "dao_mod.f". Cleaned up code and updated +! comments. Now only order tracer numbers into NTRAIND on the first +! call. Now force double-precision with "D" exponents. Now also +! reference IDTNOX, IDTOX, etc. from "tracerid_mod.f". Bundled into +! "drydep_mod.f" (bmy, 11/19/02) +! (2 ) Now make sure that the PBL depth (THIK) is greater than or equal to +! the thickness of the first layer. Now initialize PBLFRAC array on +! each call. (rjp, bmy, 7/21/03) +! (3 ) Now declare CFRAC, RADIAT, AZO, USTAR as local variables, which are +! returned by METERO. CFRAC and RADIAT have also been deleted from +! "CMN_DEP". (bmy, 12/9/03) +! (4 ) Now use explicit formula for IJLOOP to allow parallelization. +! Also reference LPRT from "logical_mod.f" (bmy, 7/20/04) +! (5 ) Now use routines from "pbl_mix_mod.f" to get PBL quantities, instead +! of re-computing them here. Removed PBLFRAC array. Removed reference +! to "pressure_mod.f". Removed reference to header file CMN. +! Parallelize DO-loops. (bmy, 2/22/05) +! (6 ) Now define RHB as a local array, which is defined in METERO and then +! passed to DEPVEL. (bec, bmy, 4/13/05) +! (7 ) Now dimension AZO for GEOS or GCAP met fields. Remove obsolete +! variables. (swu, bmy, 5/25/05) +! (8 ) Remove reference to TRACERID_MOD, it's not needed (bmy, 10/3/05) +!****************************************************************************** +! + ! Reference to F90 modules + USE DIAG_MOD, ONLY : AD44 + USE DAO_MOD, ONLY : AD, ALBD, BXHEIGHT, SUNCOS + USE ERROR_MOD, ONLY : DEBUG_MSG + USE LOGICAL_MOD, ONLY : LPRT + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! ND44 +# include "CMN_DEP" ! IREG, ILAND, IUSE, etc. +# include "CMN_GCTM" ! Physical constants + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL :: LSNOW(MAXIJ) + INTEGER :: I, J, L, N, IJLOOP, NN, NDVZ + REAL*8 :: THIK, DVZ + REAL*8 :: CZ1(MAXIJ), TC0(MAXIJ) + REAL*8 :: ZH(MAXIJ), OBK(MAXIJ) + REAL*8 :: CFRAC(MAXIJ), RADIAT(MAXIJ) + REAL*8 :: USTAR(MAXIJ), RHB(MAXIJ) + REAL*8 :: DVEL(MAXIJ,MAXDEP) + ! add pressure and 10m wind (jaegle 5/11/11) + REAL*8 :: PRESSU(MAXIJ), W10(MAXIJ) + + ! Dimension AZO for GCAP or GEOS met fields (swu, bmy, 5/25/05) +#if defined( GCAP ) + REAL*8 :: AZO(NTYPE) +#else + REAL*8 :: AZO(MAXIJ) +#endif + + !================================================================= + ! DO_DRYDEP begins here! + !================================================================= + + ! Read drydep coeff's and land types on first call + IF ( FIRST ) THEN + CALL RDDRYCF + CALL MODIN + ! Calls INIT_WEIGHTSS to calculate the volume distribution of + ! sea salt aerosols (jaegle 5/11/11) + CALL INIT_WEIGHTSS + FIRST = .FALSE. + ENDIF + + ! Call METERO to obtain meterological fields (all 1-D arrays) + ! Added SLP as PRESSU and 10m windspeed as W10 (jaegle 5/11/11) + CALL METERO( CZ1, TC0, OBK, CFRAC, RADIAT, + & AZO, USTAR, ZH, LSNOW, RHB, PRESSU, W10 ) + + !================================================================= + ! Call DEPVEL to compute dry deposition velocities [m/s] + ! Added PRESSU, W10 as arguments (jaegle 5/11/11 + !================================================================= + CALL DEPVEL( MAXIJ, RADIAT, TC0, SUNCOS, F0, HSTAR, + & XMW, AIROSOL, USTAR, CZ1, OBK, CFRAC, + & ZH, LSNOW, DVEL, AZO, RHB, + & PRESSU, W10 ) + + !================================================================= + ! Compute dry deposition frequencies; archive diagnostics + !================================================================= +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, IJLOOP, THIK, N, NN, NDVZ, DVZ ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! 1-D grid box index + IJLOOP = ( (J-1) * IIPAR ) + I + + ! THIK = thickness of surface layer [m] + THIK = BXHEIGHT(I,J,1) + + ! Now we calculate drydep throughout the entire PBL. + ! Make sure that the PBL depth is greater than or equal + ! to the thickness of the 1st layer (rjp, bmy, 7/21/03) + THIK = MAX( ZH(IJLOOP), THIK ) + + ! Loop over drydep species + DO N = 1, NUMDEP + + ! GEOS-CHEM tracer number + NN = NTRAIND(N) + + ! Index of drydep species in the DVEL array + ! as passed back from subroutine DEPVEL + NDVZ = NDVZIND(N) + + ! Dry deposition velocity [cm/s] + DVZ = DVEL(IJLOOP,NDVZ) * 100.d0 + + ! Set minimum velocity for sulfate tracers + DVZ = DVZ_MINVAL( NN, LSNOW(IJLOOP), DVZ ) + + ! Dry deposition frequency [1/s] + DEPSAV(I,J,N) = ( DVZ / 100.d0 ) / THIK + + ! ND44 diagnostic: drydep velocity [cm/s] + IF ( ND44 > 0 ) THEN + AD44(I,J,N,2) = AD44(I,J,N,2) + DVZ + ENDIF + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !### Debug + IF ( LPRT ) CALL DEBUG_MSG( '### DO_DRYDEP: after dry dep' ) + + ! Return to calling program + END SUBROUTINE DO_DRYDEP + +!------------------------------------------------------------------------------ + + FUNCTION DVZ_MINVAL( N, LSNOW, DVZ ) RESULT( NEWDVZ ) +! +!****************************************************************************** +! Function DVZ_MINVAL sets minimum values for drydep velocities for +! SULFATE TRACERS, according to Mian Chin's GOCART model. +! (rjp, bmy, 11/21/02, 10/3/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) N (INTEGER) : Tracer number +! (2 ) LSNOW (LOGICAL) : Flag for denoting snow/ice +! (3 ) DVZ (REAL*8 ) : Deposition velocity [cm/s] +! +! NOTES: +! (1 ) Don't put a min drydep value on H2O2 for offline run (rjp, bmy,3/31/03) +! (2 ) Remove reference to CMN, it's obsolete (bmy, 7/20/04) +! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +!****************************************************************************** +! + ! References to F90 modules + USE TRACERID_MOD, ONLY : IDTMSA, IDTNH3, IDTNH4 + USE TRACERID_MOD, ONLY : IDTNIT, IDTSO2, IDTSO4 + +# include "CMN_SIZE" ! Size parameters! + + ! Arguments + INTEGER, INTENT(IN) :: N + LOGICAL, INTENT(IN) :: LSNOW + REAL*8, INTENT(IN) :: DVZ + + ! Function value + REAL*8 :: NEWDVZ + + !================================================================= + ! DVZ_MINVAL begins here! + !================================================================= + + !--------------------------------------- + ! SO2, NH3, offline H2O2 + ! Min Vd = 2.0e-1 [cm/s] over ice/snow + ! = 3.0e-1 [cm/s] over land + !--------------------------------------- + IF ( N == IDTSO2 .or. N == IDTNH3 ) THEN + + IF ( LSNOW ) THEN + NEWDVZ = MAX( DVZ, 2.0d-1 ) + ELSE + NEWDVZ = MAX( DVZ, 3.0d-1 ) + ENDIF + + !--------------------------------------- + ! SO4, MSA, NH4, NIT + ! Min Vd = 1.0e-2 [cm/s] + !--------------------------------------- + ELSE IF ( N == IDTSO4 .or. N == IDTMSA .or. + & N == IDTNH4 .or. N == IDTNIT ) THEN + + NEWDVZ = MAX( DVZ, 1.0d-2 ) + + !--------------------------------------- + ! Other drydep species: do nothing + !--------------------------------------- + ELSE + NEWDVZ = DVZ + + ENDIF + + ! Return to calling program + END FUNCTION DVZ_MINVAL + +!------------------------------------------------------------------------------ + + SUBROUTINE METERO( CZ1, TC0, OBK, CFRAC, RADIAT, + & AZO, USTR, ZH, LSNOW, RHB, PRESSU, W10 ) +! +!****************************************************************************** +! Subroutine METERO calculates meteorological constants needed for the +! dry deposition velocity module. (lwh, gmg, djj, 1989, 1994; bmy, 10/3/05) +! +! Arguments as Output: +! ============================================================================ +! (1 ) CZ1 (REAL*8 ) : Midpoint height of first model level [m] +! (2 ) TC0 (REAL*8 ) : Array for grid box surface temperature [K] +! (3 ) OBK (REAL*8 ) : Array for the Monin-Obhukov length [m] +! (4 ) CFRAC (REAL*8 ) : Array for the column cloud fraction [unitless] +! (5 ) RADIAT (REAL*8 ) : Array for the solar radiation @ ground [W/m2] +! (6 ) AZO (REAL*8 ) : Array for the roughness heights [m] +! (7 ) USTR (REAL*8 ) : Array for the friction velocity [m/s] +! (8 ) ZH (REAL*8 ) : Height of the mixed layer (aka PBL) [m] +! (9 ) LSNOW (LOGICAL) : Flag to denote ice & snow (ALBEDO < 0.4) +! (10) RHB (REAL*8 ) : Relative humidity at surface [unitless] +! (11) PRESSU (REAL*8 ) : Sea level pressure [Pa] +! (12) W10M (REAL*8) : 10 meter windspeed [m/s] +! +! References (see full citations above): +! ============================================================================ +! (1 ) Wesely, M. L., 1989. +! (2 ) Jacob, D.J., and S.C. Wofsy, 1990 +! +! NOTES: +! (1 ) Now reference GET_PEDGE from "pressure_mod.f". Now reference T from +! "dao_mod.f". Removed obsolete code & comments, and added new +! documentation header. Now force double precision with "D" +! exponents. Now compute OBK here as well. Bundled into F90 module +! "drydep_mod.f" (bmy, 11/20/02) +! (2 ) Now reference CLDFRC, RADSWG, ZO, USTAR from "dao_mod.f". Also now +! pass CFRAC, RADIAT, AZO, USTR back to the calling routine +! via the arg list. (bmy, 12/9/03) +! (3 ) Now use explicit formula for IJLOOP to allow parallelization +! (bmy, 7/20/04) +! (4 ) Now compute ZH and LSNOW here instead of w/in DO_DRYDEP. Parallelize +! DO-loops. Now use BXHEIGHT from "dao_mod.f" instead of computing +! the thickness of the 1st level here. Remove reference to +! "pressure_mod.f". Remove reference to T from "dao_mod.f". Now +! reference ALBD from "dao_mod.f" (bmy, 2/22/05) +! (5 ) Now references RH from "dao_mod.f". Now passes relative humidity +! from the surface layer back via RHB argument. (bec, bmy, 4/13/05) +! (6 ) Now call GET_OBK from "dao_mod.f" to get the M-O length for both +! GEOS or GCAP met fields. Remove local computation of M-O length +! here. Also now dimension AZO appropriately for GCAP or GEOS met +! fields. Remove obsolete variables. (swu, bmy, 5/25/05) +! (7 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (8 ) Add sea level pressure and 10m windspeed as arguments (jaegle 5/11/11) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : ALBD, BXHEIGHT, CLDFRC, GET_OBK + USE DAO_MOD, ONLY : RADSWG, RH, TS, USTAR, Z0 + ! Add SLP (jaegle 5/11/11) + USE DAO_MOD, ONLY : SLP + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_m + +# include "CMN_SIZE" ! Size parameters +# include "CMN_GCTM" ! Physical constants + + ! Arguments + LOGICAL, INTENT(OUT) :: LSNOW(MAXIJ) + REAL*8, INTENT(OUT) :: CZ1(MAXIJ) + REAL*8, INTENT(OUT) :: TC0(MAXIJ) + REAL*8, INTENT(OUT) :: OBK(MAXIJ) + REAL*8, INTENT(OUT) :: CFRAC(MAXIJ) + REAL*8, INTENT(OUT) :: RADIAT(MAXIJ) + REAL*8, INTENT(OUT) :: RHB(MAXIJ) + REAL*8, INTENT(OUT) :: USTR(MAXIJ) + REAL*8, INTENT(OUT) :: ZH(MAXIJ) + ! add the following 2 outputs (jaegle 5/5/11) + REAL*8, INTENT(OUT) :: PRESSU(MAXIJ) + REAL*8, INTENT(OUT) :: W10(MAXIJ) + + ! Dimension AZO for GCAP or GEOS met fields (swu, bmy, 5/25/05) +#if defined( GCAP ) + REAL*8, INTENT(OUT) :: AZO(NTYPE) +#else + REAL*8, INTENT(OUT) :: AZO(MAXIJ) +#endif + + ! Local variables + INTEGER :: I, J, IJLOOP + REAL*8 :: THIK + + ! External functions + REAL*8, EXTERNAL :: XLTMMP + ! Surface wind speed (jaegle, 5/11/11) + REAL*8, EXTERNAL :: SFCWINDSQR + + !================================================================= + ! METERO begins here! + !================================================================= + +#if defined( GCAP ) + ! For GCAP: AZO (roughness ht) is a function of Olson land type + ! instead of lat/lon location. Zero AZO here; AZO will be + ! computed internally w/in routine DEPVEL (swu, bmy, 5/25/05) + AZO(:) = 0d0 +#endif + + ! Loop over surface grid boxes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, IJLOOP, THIK ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! 1-D grid box index + IJLOOP = ( (J-1) * IIPAR ) + I + + ! THIK = thickness of layer 1 [m] + THIK = BXHEIGHT(I,J,1) + + ! Midpoint height of first model level [m] + CZ1(IJLOOP) = THIK / 2.0d0 + + !============================================================== + ! Return meterological quantities as 1-D arrays for DEPVEL + !============================================================== + +#if !defined( GCAP ) + ! For GEOS: Roughness height [m] is a function of lat/lon + AZO(IJLOOP) = Z0(I,J) +#endif + + ! Column cloud fraction [unitless] + CFRAC(IJLOOP) = CLDFRC(I,J) + + ! Set logical LSNOW if snow and sea ice (ALBEDO > 0.4) + LSNOW(IJLOOP) = ( ALBD(I,J) > 0.4 ) + + ! Monin-Obhukov length [m] + OBK(IJLOOP) = GET_OBK( I, J ) + + ! Solar insolation @ ground [W/m2] + RADIAT(IJLOOP) = RADSWG(I,J) + + ! Surface temperature [K] + TC0(IJLOOP) = TS(I,J) + + ! Friction velocity [m/s] + USTR(IJLOOP) = USTAR(I,J) + + ! Mixed layer depth [m] + ZH(IJLOOP) = GET_PBL_TOP_m( I, J ) + + ! Relative humidity @ surface [unitless] (bec, bmy, 4/13/05) + !RHB(IJLOOP) = MIN( 0.99d0, RH(I,J,1) * 1.d-2 ) + ! changed to 98% due to vapor pressure lowering above sea sater (Lewis & Schwartz, 2004) + ! jaegle (5/11/11) + RHB(IJLOOP) = MIN( 0.98d0, RH(I,J,1) * 1.d-2 ) + + ! Sea level pressure (jaegle 5/11/11). + ! SLP is in hPa, convert from hPa to Pa for PRESSU. + PRESSU(IJLOOP) = SLP(I,J) * 1.d2 + + ! 10m windspeed (jaegle 5/11/11) + W10(IJLOOP) = SQRT( SFCWINDSQR(I,J) ) + + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE METERO + +!------------------------------------------------------------------------------ + + SUBROUTINE DRYFLX +! +!****************************************************************************** +! Subroutine DRYFLX sets up the dry deposition flux diagnostic for tracers +! which are part of the SMVGEAR mechanism. (bmy, bdf, 4/20/99, 3/24/04) +! +! NOTES: +! (1 ) Bug fix -- now skip tracers for which NTDEP(N) is zero, in order +! to avoid array-out-of-bounds errors. (bmy, 5/2/00) +! (2 ) Now reference the CSPEC array from "comode_mod.f" instead of from +! common block header "comode.h". (bmy, 7/11/00) +! (3 ) Also reference JLOP and VOLUME from "comode_mod.f" (bmy, 10/19/00) +! (4 ) Updated comments, cosmetic changes (bmy, 3/14/02) +! (5 ) Replaced all instances of IM with IIPAR and JM with JJPAR, in order +! to prevent namespace confusion for the new TPCORE (bmy, 6/25/02) +! (6 ) Removed reference to "comtrid.h", "CMN_SAV", "CMN_DEP", and "CMN_O3", +! these are not used in this routine. Also bundled into "drydep_mod.f" +! for more convenient packaging. (bmy, 11/19/02) +! (7 ) Replaced DXYP(JREF)*1d4 with routine GET_AREA_CM2 of "grid"mod.f". +! Also removed references to JREF and FLUXRUL. Now use function +! GET_TS_CHEM from "time_mod.f". (bmy, 2/11/03) +! (8 ) Now references ERROR_STOP from "error_mod.f" (bmy, 4/28/03) +! (9 ) Now sum drydep fluxes throughout the entire PBL. Added L variable. +! AREA_CM2 has now been made into a lookup table. Now implement a +! parallel DO loop for efficiency. (rjp, bmy, 7/21/03) +! (10) Now bracket AD44 with a !$OMP CRITICAL block in order to avoid +! multiple threads writing to the same element (bmy, 3/24/04) +! (11) Now reference GET_FRAC_UNDER_PBLTOP and GET_PBL_MAX_L from +! "pbl_mix_mod.f". Remove reference to CMN. (bmy, 2/22/05) +!****************************************************************************** +! + ! References to F90 modules + USE COMODE_MOD, ONLY : CSPEC, JLOP, VOLUME + USE DIAG_MOD, ONLY : AD44 + USE ERROR_MOD, ONLY : ERROR_STOP + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE PBL_MIX_MOD, ONLY : GET_FRAC_UNDER_PBLTOP, GET_PBL_MAX_L + USE TIME_MOD, ONLY : GET_TS_CHEM + USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! Diagnostic switches & arrays +# include "comode.h" ! CSPEC + + ! Local variables + INTEGER :: I, J, JJ, JLOOP, L, L_PBLTOP, N, NK, NN + REAL*8 :: DTCHEM, PBL_MAX, TDRYFX, AREA_CM2(JJPAR) + + !================================================================= + ! DRYFLX begins here! + !================================================================= + + ! Return unless we have turned on ND44 drydep diagnostic + IF ( ND44 == 0 ) RETURN + + ! There is only drydep in the surface layer, which + ! is accounted for in the "URBAN" chemistry slot + NCS = NCSURBAN + + ! Chemistry timestep [s] + DTCHEM = GET_TS_CHEM() * 60d0 + + ! Highest extent of the PBL [model layers] + PBL_MAX = GET_PBL_MAX_L() + + !================================================================= + ! ND44 diagnostic: Dry deposition flux [molec/cm2/s] + ! + ! NOTE: DRYFLX will only archive the dry deposition fluxes for + ! tracers which are SMVGEAR species. Fluxes for sulfate tracers + ! will be updated in "sulfate_mod.f". (bmy, 11/19/02) + !================================================================= + + ! Save grid box surface area [cm2] in a lookup table (bmy, 7/23/03) + DO J = 1, JJPAR + AREA_CM2(J) = GET_AREA_CM2(J) + ENDDO + + ! Loop over dry deposition species +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N, NK, JJ, JLOOP, TDRYFX ) +!$OMP+SCHEDULE( DYNAMIC ) + DO N = 1, NUMDEP + + ! Index for drydep species #N, from SMVGEAR + NK = NTDEP(N) + + ! If NK <= 0, then skip to the next tracer. + ! This avoids array-out-of-bounds errors (bmy, 5/2/00) + IF ( NK <= 0 ) CYCLE + + ! Index for drydep flux in CSPEC array + JJ = IRM(NPRODLO+1,NK,NCS) + + ! Error check JJ -- can't be zero + IF ( JJ <= 0 ) THEN + CALL ERROR_STOP( 'Drydep species mis-indexing!', + & 'DRYFLX ("error_mod.f")' ) + ENDIF + + ! Loop over grid boxes + DO L = 1, PBL_MAX + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Only deal w/ boxes w/in the boundary layer + IF ( GET_FRAC_UNDER_PBLTOP( I, J, L ) > 0d0 + & .and. ITS_IN_THE_TROP(I,J,L) ) THEN + + ! 1-D grid box index for CSPEC & VOLUME + JLOOP = JLOP(I,J,L) + + ! Dry dep flux [molec] for species N = + ! CSPEC(JLOOP,JJ) * VOLUME(JLOOP) + ! [molec/cm3] * [cm3] + TDRYFX = CSPEC(JLOOP,JJ) * VOLUME(JLOOP) + + ! Convert TDRYFX from [molec] to [molec/cm2/s] + TDRYFX = TDRYFX / ( AREA_CM2(J) * DTCHEM ) + +!$OMP CRITICAL + ! Save into AD44 diagnostic array + IF ( ND44 > 0 ) THEN + AD44(I,J,N,1) = AD44(I,J,N,1) + TDRYFX + ENDIF +!$OMP END CRITICAL + + ENDIF + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DRYFLX + +!------------------------------------------------------------------------------ + + SUBROUTINE DRYFLXRnPbBe +! +!****************************************************************************** +! Subroutine DRYFLXRnPbBe removes dry deposition losses from the STT tracer +! array and archives deposition fluxes to the ND44 diagnostic. +! (hyl, bmy, bdf, 4/2/99, 5/25/05) +! +! NOTES: +! (1 ) Now eliminate DEPFLUX from CMN_SAV, in order to save memory. +! DEPFLUX is now a local variable (bdf, 4/2/99) +! (2 ) Now make DEPFLUX of dimension (IIPAR,JJPAR,MAXDEP) (bmy, 4/2/99) +! (3 ) Now use an allocatable array for the ND44 diagnostic. +! Also made cosmetic changes, updated comments. (bmy, 3/16/00) +! (4 ) Eliminate obsolete code and ND63 diagnostic (bmy, 4/12/00) +! (5 ) Added to module "RnPbBe_mod.f". Also made cosmetic changes +! and updated comments (bmy, 6/14/01) +! (6 ) Updated comments (bmy, 3/29/02) +! (7 ) Replace all instances of IM, JM, IMX, JMX, with IIPAR, JJPAR, IGLOB, +! and JGLOB. Now replaced DEPFLUX array w/ AMT_LOST scalar +! variable. Also make sure that the amount of tracer lost to drydep +! is now accurately accounted in the ND44 diagnostic. (bmy, 8/7/02) +! (8 ) Now call GEOS_CHEM_STOP or ERROR_STOP (from "error_mod.f") when +! stopping the run w/ an error condition. (bmy, 10/15/02) +! (9 ) Now moved from "RnPbBe_mod.f" to "drydep_mod.f". (bmy, 1/27/03) +! (10) Now use function GET_TS_CHEM from "time_mod.f" (bmy, 2/11/03) +! (11) Now compute drydep fluxes throughout the entire PBL. Now references +! PBLFRAC. Added L_PBLTOP variable. (bmy, 7/21/03) +! (12) Now follow GEOS-3 algorithm for GEOS-4 model (bmy, 12/2/03) +! (13) Now reference STT from "tracer_mod.f" and LDRYD from "logical_mod.f" +! (bmy, 7/20/04) +! (14) Now modified for GEOS-5 and GCAP met fields (swu, bmy, 5/25/05) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : AD44 + USE ERROR_MOD, ONLY : ERROR_STOP, GEOS_CHEM_STOP + USE LOGICAL_MOD, ONLY : LDRYD + 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 + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! ND44 +# include "CMN_DEP" ! Dry deposition variables + + ! Local variables + INTEGER :: I, J, L, PBL_MAX, N, NN + REAL*8 :: DTCHEM, FRACLOST, F_UNDER_TOP, AMT_LOST + + !================================================================= + ! DRYFLXRnPbBe begins here!! + !================================================================= + + ! Return if drydep is turned off + IF ( .not. LDRYD ) RETURN + + ! Chemistry timestep in seconds + DTCHEM = GET_TS_CHEM() * 60d0 + + ! Maximum extent of the PBL [model layers] + PBL_MAX = GET_PBL_MAX_L() + + ! Loop over drydep species +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, L, N, NN, F_UNDER_TOP, FRACLOST, AMT_LOST ) + DO N = 1, NUMDEP + + ! Tracer index in STT that corresponds to drydep species N + ! If invalid, then cycle + NN = NTRAIND(N) + IF ( NN == 0 ) CYCLE + + ! Loop over grid boxes + DO L = 1, PBL_MAX + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Fraction of box (I,J,L) under PBL top [unitless] + F_UNDER_TOP = GET_FRAC_UNDER_PBLTOP( I, J, L ) + + ! FRACLOST is the fraction of tracer lost. PBLFRAC is + ! the fraction of layer L located totally w/in the PBL. + FRACLOST = DEPSAV(I,J,N) * F_UNDER_TOP * DTCHEM + + !=========================================================== + ! Proceed as follows: + ! -------------------------------- + ! (a) If FRACLOST < 0, then stop the run. + ! + ! (b) If FRACLOST > 1, use an exponential loss to + ! avoid negative tracer + ! + ! (c) If FRACLOST is in the range (0-1), then use the + ! the regular formula (STT * FRACLOST) to compute + ! loss from dry deposition. + !===================================================== + + ! Stop the run on negative FRACLOST! + IF ( FRACLOST < 0 ) THEN + CALL ERROR_STOP( 'FRACLOST < 0', 'dryflxRnPbBe' ) + ENDIF + + ! AMT_LOST = amount of tracer lost to drydep [kg] + IF ( FRACLOST > 1 ) THEN + AMT_LOST = STT(I,J,L,NN) * ( 1d0 - EXP(-FRACLOST) ) + ELSE + AMT_LOST = STT(I,J,L,NN) * FRACLOST + ENDIF + + ! ND44 diagnostic: drydep flux [kg/s] + IF ( ND44 > 0 ) THEN +!$OMP CRITICAL + AD44(I,J,N,1) = AD44(I,J,N,1) + ( AMT_LOST/DTCHEM ) +!$OMP END CRITICAL + ENDIF + + ! Subtract AMT_LOST from the STT array [kg] + STT(I,J,L,NN) = STT(I,J,L,NN) - AMT_LOST + + ENDDO + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DRYFLXRnPbBe + +!------------------------------------------------------------------------------ + + SUBROUTINE DRYFLXH2HD +! +!****************************************************************************** +! Subroutine DRYFLXH2HD removes dry deposition losses from the tracer +! array and archives deposition fluxes AND VELOCITY to the ND44 diagnostic. +! (adapted from DRYFLX v5-05, jaegle 11/02/2005). +! +! NOTES: +! (1) Now deposit through the PBL. Commented but kept code related to soil +! temperature (phs, 5/16/07) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : AD44 + USE ERROR_MOD, ONLY : ERROR_STOP, GEOS_CHEM_STOP + USE TIME_MOD, ONLY : GET_TS_CHEM + USE GRID_MOD, ONLY : GET_AREA_CM2, GET_XOFFSET, GET_YOFFSET + USE DAO_MOD, ONLY : T, TS, ALBD + USE TRACER_MOD, ONLY : STT + USE LOGICAL_MOD, ONLY : LDRYD + USE DAO_MOD, ONLY : BXHEIGHT + USE PBL_MIX_MOD, ONLY : GET_PBL_TOP_m + USE PBL_MIX_MOD, ONLY : GET_FRAC_UNDER_PBLTOP, GET_PBL_MAX_L + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! Diagnostic switches & arrays +# include "CMN_VEL" ! IJLAND +# include "CMN_DEP" ! Dry deposition variables +# include "commsoil.h" ! Soil pulsing & wetness variables + + ! Local variables + INTEGER :: I, J, L, N, NN, M, PBL_MAX + INTEGER :: IJLOOP, I0, J0, IREF, JREF, K, STYP + INTEGER :: JLOP(IIPAR,JJPAR,1), NTYP(IIPAR,JJPAR) + REAL*8 :: DTCHEM, FRACLOST, AMT_LOST + REAL*8 :: THIK, DRYF, SVEL, FSOIL, AREA_CM2 + REAL*8 :: SOIL_H2, SOIL_HD, TMMP, STEMP(IIPAR,JJPAR) + REAL*8 :: MLD + REAL*8 :: F_UNDER_TOP + + ! External functions, for calculating soil temperature + REAL*8, EXTERNAL :: SOILTEMP, XLTMMP + + !================================================================= + ! DRYFLXH2HD begins here!! + !================================================================= + + ! Chemistry timestep in seconds + DTCHEM = GET_TS_CHEM() * 60d0 + + ! Call soiltype to determine whether soil is dry or + ! wet for all land grid-boxes + CALL SOILTYPE + + ! Only do the following if DRYDEP is turned on + IF ( .not. LDRYD ) RETURN + + ! Maximum extent of the PBL [model layers] + PBL_MAX = GET_PBL_MAX_L() + + ! Need nested-grid offsets for soiltemp code + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + + ! Initalize + IJLOOP = 0 + DO J = 1, JJPAR + DO I = 1, IIPAR + IJLOOP = IJLOOP + 1 + JLOP(I,J,1) = IJLOOP + ENDDO + ENDDO + + + ! Loop over drydep species + DO N = 1, NUMDEP + + ! Tracer index in STT that corresponds to drydep species N + ! If invalid, then cycle + NN = NTRAIND(N) + IF ( NN == 0 ) CYCLE + + ! Loop over layers (most efficient if moved below?) + DO L = 1, PBL_MAX + + ! reset STEMP (could be a scalar -depends on future usage-) + ! STEMP = 0 ! Not use yet + + ! Loop over each land grid-box + DO M = 1, NLAND + IREF = INDEXSOIL(1,M) + JREF = INDEXSOIL(2,M) + I = IREF - I0 + J = JREF - J0 + IJLOOP = JLOP(I,J,1) + + ! Fraction of grid box that is ocean + FSOIL = FRCLND(I,J) + + + ! Only apply dry deposition over land surfaces which + ! are not covered with ice or desert (albedo < 0.4) + ! and if we are in the window simulation. + IF ( (I.GE.1) .AND. (I.LE.IIPAR) .AND. + & (J.GE.1) .AND. (J.LE.JJPAR) .AND. + & (FSOIL > 0.d0) .AND. (ALBD(I,J) < 0.4d0) ) THEN + + ! Grid box area in cm2 + AREA_CM2 = GET_AREA_CM2( J ) + +! !=========================================================== +! ! Get SOIL TEMPerature from function SOILTEMP(I,J,M,NTYP) +! ! Right now Surface Temp is used instead. +! ! So commented for now (phs, 3/5/07) +! !=========================================================== +! TMMP = XLTMMP(I,J,IJLOOP) - 273.15 +! +! ! Loop over landtype +! DO K = 1, IREG(IREF,JREF) +! +! ! NCONSOIL Converts from Olson type -> soil type +! STYP = NCONSOIL(ILAND(IREF,JREF,K)+1) +! +! ! Temperature factor +! ! STEMP(I,J) is the weighted soil temperature in +! ! gridbox i,j for all the soil types +! ! IUSE is the fraction ((per mil) of box covered by land types +! STEMP(I,J) = STEMP(I,J) + +! & SOILTEMP(I,J,M,STYP,TMMP)* +! & DBLE(IUSE(IREF,JREF,K))/1000.D0 +! +! !write(*,*)'TEst',TMMP, TS(I,J)-273.15, STEMP(I,J) +! ENDDO +! + + ! SVEL [cm/s] is the air-to-soil transfer velocity + ! Use uniform value of 3.94d-2 cm/s over land + ! not covered by snow or desert. + SVEL = 3.94d-2 + + + ! if soil temperature is below freezing reduce dep vel + ! by 1/2, and additional 1/2 below -15C(hup, 6/21/2005) + ! for now use surface temperature (TS) instead of + ! air temperature (T) jaegle, 12/12/2005 + IF (TS(I,J) <= 273.15d0) SVEL = SVEL / 2.0d0 + IF (TS(I,J) <= 258.15d0) SVEL = SVEL / 2.0d0 + + ! if desert, set deposition velocity to zero by multiplying + ! dep vel by the fraction covered by desert(hup, 5/1/2006) + ! IJLAND+1 is the Olson Land type index + ! 51: desert 52: desert set SVEL = 0 + ! IJUSE is the fraction of the grid square occupied by surface K + ! in units of per mil (IJUSE=500 -> 50% of the grid square). + DO K = 1, IREG(IREF,JREF) + + NTYP(I,J) = IJLAND(IJLOOP, K) + 1 + + IF (NTYP(I,J) .eq. 52 .or. NTYP(I,J) .eq. 51) THEN + SVEL = SVEL*(1-(IJUSE(IJLOOP,K)/1.d3)) + ENDIF + + ENDDO + + ! For HD add soil fractionation with + ! an alpha coefficient of 0.943 Gerst & Quay, 2001 + IF (N .eq. 2) SVEL = SVEL * 0.943 + + + ! Get THIK (cannot use ZH variable, since + ! DO_DRYDEP, METERO, and DEPVEL are not called in H2/HD sims) + + ! Fraction of box (I,J,L) under PBL top [unitless] + F_UNDER_TOP = GET_FRAC_UNDER_PBLTOP( I, J, L ) + + ! Mixed layer depth [m] + MLD = GET_PBL_TOP_m( I, J ) + + ! THIK = thickness of surface layer [m] + THIK = BXHEIGHT(I,J,1) + THIK = MAX( MLD, THIK ) + + + ! Dry deposition frequency [1/s] + DRYF = ( SVEL / 100.d0 ) / THIK + + ! FRACLOST = Fraction of species lost to drydep [unitless] + FRACLOST = DRYF * DTCHEM * F_UNDER_TOP + + !======================================================== + ! Proceed as follows: + ! ------- + ! (a) If FRACLOST < 0, then stop the run. + ! + ! (b) If FRACLOST > 1, use an exponential loss to + ! avoid negative tracer + ! + ! (c) If FRACLOST is in the range (0-1), then use the + ! regular formula (STT * FRACLOST) to compute + ! the loss from dry deposition. + !======================================================== + + ! Stop the run on negative FRACLOST! + IF ( FRACLOST < 0 ) THEN + CALL ERROR_STOP( 'FRACLOST < 0', 'dryflxH2HD' ) + ENDIF + + + ! AMT_LOST = amount of tracer lost to drydep [kg] + IF ( FRACLOST > 1 ) THEN + AMT_LOST = STT(I,J,L,NN) * ( 1d0 - EXP(-FRACLOST) ) + & * FSOIL + ELSE + AMT_LOST = STT(I,J,L,NN) * FRACLOST * FSOIL + ENDIF + + + ! ND44 diagnostic: drydep flux [kg/s] + ! ND44 diagnostic: drydep velocity [cm/s] + IF ( ND44 > 0 ) THEN + AD44(I,J,N,1) = AD44(I,J,N,1) + ( AMT_LOST/DTCHEM ) + AD44(I,J,N,2) = AD44(I,J,N,2) + SVEL * FSOIL + ENDIF + + + ! Subtract AMT_LOST from the STT array [kg] + STT(I,J,L,NN) = STT(I,J,L,NN) - AMT_LOST + + + ENDIF ! I and J within bounds, ALBD<0.4 and FSOIL>0 + ENDDO ! M = LAND GRID BOXES + ENDDO ! PBL layers + ENDDO ! NUMDEP = Number of species that drydep + + + ! Return to calling program + END SUBROUTINE DRYFLXH2HD + +!------------------------------------------------------------------------------ + + SUBROUTINE DEPVEL( NPTS, RADIAT, TEMP, SUNCOS, F0, HSTAR, + & XMW, AIROSOL, USTAR, CZ1, OBK, CFRAC, + & ZH, LSNOW, DVEL, ZO, RHB, + & PRESSU, W10 ) + + ! References to F90 modules (bmy, 3/8/01) + USE ERROR_MOD, ONLY : IT_IS_NAN + +C Subroutine computes the dry deposition velocities using +C a resistance-in-series model. +C +C** Contact: D.J. Jacob, Harvard U. (djj@io.harvard.edu) +C** Modularized by G.M. Gardner, Harvard U. +C** Version 3.2: 5/27/97 +C** Version 3.2.1: 3/4/99 -- bug fix in expression for RT +C** Version 3.2.2: 3/26/99 -- bug fix: specify a large Ra for aerosols +C** Version 3.2.3: 11/12/99 -- change Reynolds # criterion from 10 to 1 +C -- force double precision w/ "D" exponents +C** Version 3.3: 5/8/00 -- bug fixes, cleanup, updated comments. +C** Version 3.4: 1/22/03 -- remove hardwire for CANOPYNOX +C** Version 3.5 7/21/03 -- Remove cap of surface resistance in RLUXX +C** Version 3.6 4/01/04 -- Now do drydep of DUST aerosol tracers +C** Version 3.7 4/20/04 -- Now also do drydep of SEASALT aerosol tracers +C** Version 3.8 4/13/05 -- Accounts for hygroscopic growth of SEASALT +C** aerosol tracers. DUST aerosol tracers do +C** not grow hygroscopically. Added RHB as +C** an input argument. +C** Version 3.9 5/25/05 -- Now restore GISS-specific code for GCAP model +C** Version 3.9.1 11/17/05 -- change Reynolds # criterion from 1 to 0.1 +C Updates: +C +Updated to use actual Sea level pressure instead of 1000 hPa (jaegle 5/11/11) +C +Modified to used Slinn & Slinn (1980) over Ocean surfaces (jaegle 5/11/11) +C +C*********************************************************************** +C Changes from Version 3.2 to Version 3.3: *** +C * We now suppress dry deposition over aerodynamically smooth *** +C surfaces. The previous algorithm yielded negative numbers *** +C when u* was very small (due to the logarithm going negative). *** +C See the comments below for more information. *** +C * Now eliminate obsolete variables ZLMO and SIH from the code. *** +C * Obsolete comments have been updated or removed. *** +C*********************************************************************** +C Changes from version 3.1 to version 3.2: *** +C * In unstable atmospheres with |ZLMO| < ZO, as can happen *** +C occasionally under very low wind conditions with tall canopies, *** +C application of Monin-Obukhov similarity yields negative values *** +C for RA. This was a problem in version 3.1. In fact, *** +C Monin-Obukhov similarity does not apply under such conditions, *** +C so we now set RA to zero and let the boundary *** +C resistance RB define the overall aerodynamic resistance. Since *** +C RB varies inversely with U* it will impose a large aerodynamic *** +C resistance under very low wind conditions. *** +C * The range of applicability of stability correction functions *** +C to Monin-Obukhov similarity has been extended to *** +C -2.5 < z/zMO < 1.5, based on Figure 2 of Businger et al. [1971].*** +C The range used to be -1 < z/zMO < 1 in version 3.1. *** +C*********************************************************************** +C +C Literature cited: +C Baldocchi, D.D., B.B. Hicks, and P. Camara, A canopy stomatal +C resistance model for gaseous deposition to vegetated surfaces, +C Atmos. Environ. 21, 91-101, 1987. +C Brutsaert, W., Evaporation into the Atmosphere, Reidel, 1982. +C Businger, J.A., et al., Flux-profile relationships in the atmospheric +C surface layer, J. Atmos. Sci., 28, 181-189, 1971. +C Dwight, H.B., Tables of integrals and other mathematical data, +C MacMillan, 1957. +C Guenther, A., and 15 others, A global model of natural volatile +C organic compound emissions, J. Geophys. Res., 100, 8873-8892, 1995. +C Hicks, B.B., and P.S. Liss, Transfer of SO2 and other reactive +C gases across the air-sea interface, Tellus, 28, 348-354, 1976. +C Jacob, D.J., and S.C. Wofsy, Budgets of reactive nitrogen, +C hydrocarbons, and ozone over the Amazon forest during the wet season, +C J. Geophys. Res., 95, 16737-16754, 1990. +C Jacob, D.J., and 9 others, Deposition of ozone to tundra, +C J. Geophys. Res., 97, 16473-16479, 1992. +C Levine, I.N., Physical Chemistry, 3rd ed., McGraw-Hill, New York, 1988. +C Munger, J.W., and 8 others, Atmospheric deposition of reactive +C nitrogen oxides and ozone in a temperate deciduous forest and a +C sub-arctic woodland, J. Geophys. Res., in press, 1996. +C Walcek, C.J., R.A. Brost, J.S. Chang, and M.L. Wesely, SO2, sulfate, and +C HNO3 deposition velocities computed using regional landuse and +C meteorological data, Atmos. Environ., 20, 949-964, 1986. +C Wang, Y.H., paper in preparation, 1996. +C Wesely, M.L, Improved parameterizations for surface resistance to +C gaseous dry deposition in regional-scale numerical models, +C Environmental Protection Agency Report EPA/600/3-88/025, +C Research Triangle Park (NC), 1988. +C Wesely, M.L., same title, Atmos. Environ., 23, 1293-1304, 1989. +C +C*********************************************************************** +C +C Need as landtype input for each grid square (I,J) see (RDLAND & CMN_VEL): +C IJREG(JLOOP) - # of landtypes in grid square +C IJLAND(IJLOOP,LDT) - Land type ID for element LDT =1, IJREG(IJLOOP) +C (could be from any source - mapped to deposition +C surface ID in input unit 65) +C IJUSE(IJLOOP,LDT) - Fraction ((per mil) of gridbox area occupied by +C land type element LDT +C +C Need as leaf area index see (RDLAI & CMN_VEL): +C XYLAI(IJLOOP,LDT) - Leaf Area Index of land type element LDT +C +C Need as meteorological input for each grid square(I,J) (passed): +C RADIAT(IJLOOP) - Solar radiation in W m-2 +C TEMP(IJLOOP) - Surface air temperature in K +C SUNCOS(IJLOOP) - Cosine of solar zenith angle +C LSNOW(IJLOOP) - Logical for snow and sea ice +C RHB(IJLOOP) - Relative humidity at the surface +C PRESSU(IJLOOP) - Sea level pressure +C W10(IJLOOP) - 10m wind speed +C +C Need as input for each species K (passed): +C F0(K) - reactivity factor for oxidation of biological substances +C HSTAR(K) - Henry's Law constant +C XMW(K) - Molecular weight (kg/mole) of species K +C (used to calculate molecular diffusivities) +C AIROSOL(K) - LOGICAL flag (T = aerosol species; +C F = gas-phase species) +C +C Also need to call the following subroutines to read drydep input data: +C "modin.f" - reads Olson land types, dry deposition land types, +C and roughness heights from "drydep.table". +C (NOTE: For GEOS model, roughness heights are taken +C from met field input instead of from "drydep.table"). +C "rddrycf.f - reads drydep polynomial coeff's from file "drydep.coef" +C "rdlai.f" - reads Leaf Area Indices from files "lai**.global" +C "rdland.f" - reads Olson land types from file "vegtype.global" +C +C Some variables used in the subroutine (passed): +C LRGERA(IJLOOP) T -> stable atmosphere; a high aerodynamic resistance +C (RA=1.E4 m s-1) is imposed; else RA is calculated +C USTAR(IJLOOP) - Friction velocity (m s-1) +C CZ1(IJLOOP) - Altitude (m) at which deposition velocity is computed +C OBK(IJLOOP) - Monin-Obukhov length (m): set to 1.E5 m under neutral +C conditions +C CFRAC(IJLOOP) - Fractional cloud cover +C ZH(IJLOOP) - Mixing depth (m) +C +C Some variables used in the subroutine: +C MAXDEP - the maximum number of species for which the dry +C deposition calculation is done +C ZO(LDT) - Roughness height (m) for specific surface type indexed +C by LDT +C RSURFC(K,LDT) - Bulk surface resistance (s m-1) for species K to +C surface LDT +C C1X(K) - Total resistance to deposition (s m-1) for species K +C +C Returned: +C DVEL(IJLOOP,K) - Deposition velocity (m s-1) of species K +C*********************************************************************** + +# include "CMN_SIZE" +# include "CMN_VEL" +# include "commsoil.h" + + INTEGER NPTS + REAL*8 RADIAT(MAXIJ),TEMP(MAXIJ),SUNCOS(MAXIJ) + REAL*8 USTAR(MAXIJ),CZ1(MAXIJ) + REAL*8 OBK(MAXIJ),CFRAC(MAXIJ),ZH(MAXIJ) + REAL*8 DVEL(MAXIJ,MAXDEP) + + ! Added relative humidity array (bec, bmy, 4/13/05) + REAL*8 :: RHB(MAXIJ) + ! Added SLP and W10 array (jaegle,5/5/11) + REAL*8 :: PRESSU(MAXIJ),W10(MAXIJ) + + REAL*8 RI(NTYPE),RLU(NTYPE),RAC(NTYPE),RGSS(NTYPE), + 1 RGSO(NTYPE),RCLS(NTYPE),RCLO(NTYPE), + 2 RSURFC(MAXDEP,NTYPE) + + REAL*8 C1X(MAXDEP),VD(MAXDEP),VK(MAXDEP) + +#if defined( GCAP ) + ! For the GISS/GCAP model, ZO is a function of land type + ! and is of dimension NTYPE (swu, bmy, 5/25/05) + REAL*8 ZO(NTYPE) +#else + ! For GEOS-CTM, ZO is now of size MAXIJ and is passed via + ! the argument list, since it is a DAO met field. (bmy, 11/10/99) + REAL*8 ZO(MAXIJ) +#endif + + LOGICAL LDEP(MAXDEP) + LOGICAL AIROSOL(MAXDEP) + REAL*8 F0(MAXDEP),HSTAR(MAXDEP),XMW(MAXDEP) + + LOGICAL LRGERA(MAXIJ) + + REAL*8 VDS + REAL*8 CZ,C1,RT,XNU,RAD0,RIX,GFACT,GFACI + REAL*8 RDC,RLUXX,RGSX,RCL,DTMP1,DTMP2,DTMP3,DTMP4 + REAL*8 CZH,CKUSTR,REYNO,CORR1,CORR2,Z0OBK + REAL*8 RA,RB,DUMMY1,DUMMY2,DUMMY3,DUMMY4 + REAL*8 XMWH2O,DAIR,TEMPK,TEMPC + INTEGER IOLSON,II,IW + INTEGER K,IJLOOP,LDT + REAL*8 RCLX,RIXX,BIOFIT + REAL*8 PRESS + DATA PRESS /1.5D5/ +C +C Logical for snow and sea ice +C + + LOGICAL LSNOW(MAXIJ) +C*********************************************************************** +C +C +C** If LDEP(K)=F, species does not deposit. +C** Deposition is applied only to species with LDEP=T. + + DO K = 1,NUMDEP + LDEP(K) = (HSTAR(K).GT.0.D0 .OR. F0(K).GT.0.D0 + & .OR. AIROSOL(K)) + ENDDO + + DO K = 1,NUMDEP + DO IJLOOP =1,NPTS + DVEL(IJLOOP,K) = 0.0D0 + ENDDO + ENDDO +C*********************************************************************** +C* +C* Begin section for computing deposition velocities +C* +C* + ! Add parallel DO-loop (bmy, 2/22/05) +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( IJLOOP, CZ, TEMPK, TEMPC, K, VD ) +!$OMP+PRIVATE( LDT, RSURFC, C1, XNU, RT, IOLSON ) +!$OMP+PRIVATE( II, RI, RLU, RAC, RGSS, RGSO ) +!$OMP+PRIVATE( RCLS, RCLO, RAD0, RIX, GFACT, GFACI ) +!$OMP+PRIVATE( RDC, XMWH2O, RIXX, RLUXX, RGSX, RCLX ) +!$OMP+PRIVATE( DTMP1, DTMP2, DTMP3, DTMP4, VDS, CZH ) +!$OMP+PRIVATE( CKUSTR, REYNO, CORR1, CORR2, Z0OBK, RA ) +!$OMP+PRIVATE( DUMMY1, DUMMY2, DUMMY3, DUMMY4, DAIR, RB ) +!$OMP+PRIVATE( C1X, VK ) + DO 560 IJLOOP =1,NPTS + +C** CZ is Altitude (m) at which deposition velocity is computed + CZ = CZ1(IJLOOP) +C** TEMPK and TEMPC are surface air temperatures in K and in C + TEMPK = TEMP(IJLOOP) + TEMPC = TEMP(IJLOOP)-273.15D0 +C* Initialize variables + DO K = 1,NUMDEP + VD(K) = 0.0D0 + DO LDT = 1,NTYPE + RSURFC(K,LDT) = 0.D0 + END DO + END DO + +C** Calculate the kinematic viscosity XNU (m2 s-1) of air +C** as a function of temperature. +C** The kinematic viscosity is used to calculate the roughness heights over +C** water surfaces and to diagnose whether such surfaces are aerodynamically +C** rough or smooth using a Reynolds number criterion. +C** The expression for the temperature dependence of XNU +C** is from the FORTRAN code in Appendix II of Wesely [1988]; +C** I wasn't able to find an original reference but it seems benign enough. + C1 = TEMPK/273.15D0 + XNU = 0.151D0*(C1**1.77D0)*1.0D-04 + +C* Compute bulk surface resistance for gases. +C* +C* Adjust external surface resistances for temperature; +C* from Wesely [1989], expression given in text on p. 1296. +C* +C* BUG FIX! Wesely [1989] gives RT = 1000.0*EXP(-TEMPC-4.0) +C* so the inner parentheses are not needed (bmy, 3/4/99) +C* RT = 1000.0*EXP(-(TEMPC-4.0)) + RT = 1000.0D0*EXP(-TEMPC-4.0D0) +C* +C Get surface resistances - loop over land types LDT +C*************************************************************************** +C* The land types within each grid square are defined using the Olson +C* land-type database. Each of the Olson land types is assigned a +C* corresponding "deposition land type" with characteristic values of surface +C* resistance components. There are 74 Olson land-types but only 11 deposition +C* land-types (i.e., many of the Olson land types share the same deposition +C* characteristics). Surface resistance components for the "deposition land +C* types" are from Wesely [1989] except for tropical forests [Jacob and Wofsy, +C* 1990] and for tundra [Jacob et al., 1992]. All surface resistance +C* components are normalized to a leaf area index of unity. +C* +C* Olson land types, deposition land types, and surface resistance components +C* are read from file 'drydep.table'; check that file for further details. +C**************************************************************************** + DO 170 LDT = 1,IJREG(IJLOOP) + IF (IJUSE(IJLOOP,LDT) .EQ. 0) GOTO 170 + IOLSON = IJLAND(IJLOOP,LDT)+1 + II = IDEP(IOLSON) +C +C** If the surface to be snow or ice; +C** set II to 1 instead. +C + IF(LSNOW(IJLOOP)) II=1 + +C* Read the internal resistance RI (minimum stomatal resistance for water +C* vapor,per unit area of leaf) from the IRI array; a '9999' value means no +C* deposition to stomata so we impose a very large value for RI. + + RI(LDT) = DBLE(IRI(II)) + IF (RI(LDT) .GE. 9999.D0) RI(LDT) = 1.D12 + +C** Cuticular resistances IRLU read in from 'drydep.table' +C** are per unit area of leaf; +C** divide them by the leaf area index to get a cuticular resistance for the +C** bulk canopy. If IRLU is '9999' it means there are no cuticular +C** surfaces on which to deposit so we impose a very large value for RLU. + IF (IRLU(II) .GE. 9999 .OR. + & XYLAI(IJLOOP,LDT).LE.0.D0) THEN + RLU(LDT) = 1.D6 + ELSE + RLU(LDT)= DBLE(IRLU(II))/XYLAI(IJLOOP,LDT)+RT + ENDIF +C** The following are the remaining resistances for the Wesely +C** resistance-in-series model for a surface canopy +C** (see Atmos. Environ. paper, Fig.1). + RAC(LDT) = MAX(DBLE(IRAC(II)), 1.D0) + IF (RAC(LDT) .GE. 9999.D0) RAC(LDT) = 1.D12 + RGSS(LDT) = MAX(DBLE(IRGSS(II)) + RT ,1.D0) + IF (RGSS(LDT) .GE. 9999.D0) RGSS(LDT) = 1.D12 + RGSO(LDT) = MAX(DBLE(IRGSO(II)) + RT ,1.D0) + IF (RGSO(LDT) .GE. 9999.D0) RGSO(LDT) = 1.D12 + RCLS(LDT) = DBLE(IRCLS(II)) + RT + IF (RCLS(LDT) .GE. 9999.D0) RCLS(LDT) = 1.D12 + RCLO(LDT) = DBLE(IRCLO(II)) + RT + IF (RCLO(LDT) .GE. 9999.D0) RCLO(LDT) = 1.D12 +C*************************************************************************** +C* +C* Adjust stomatal resistances for insolation and temperature: +C* +C* Temperature adjustment is from Wesely [1989], equation (3). +C* +C* Light adjustment by the function BIOFIT is described by Wang [1996]. +C* It combines +C* - Local dependence of stomal resistance on the intensity I of light +C* impinging the leaf; this is expressed as a mutliplicative +C* factor I/(I+b) to the stomatal resistance where b = 50 W m-2 +C* (equation (7) of Baldocchi et al. [1987]) +C* - radiative transfer of direct and diffuse radiation in the +C* canopy using equations (12)-(16) from Guenther et al. [1995] +C* - separate accounting of sunlit and shaded leaves using +C* equation (12) of Guenther et al. [1995] +C* - partitioning of the radiation at the top of the canopy into direct +C* and diffuse components using a parameterization to results from +C* an atmospheric radiative transfer model [Wang, 1996] +C* The dependent variables of the function BIOFIT are the leaf area +C* index (XYLAI), the cosine of zenith angle (SUNCOS) and the fractional +C* cloud cover (CFRAC). The factor GFACI integrates the light +C* dependence over the canopy depth; sp even though RI is input per +C* unit area of leaf it need not be scaled by LAI to yield a bulk +C* canopy value because that's already done in the GFACI formulation. +C*************************************************************************** + + RAD0 = RADIAT(IJLOOP) + RIX = RI(LDT) + IF (RIX .GE. 9999.D0) GO TO 150 + GFACT = 100.0D0 + IF (TEMPC .GT. 0.D0 .AND. TEMPC .LT. 40.D0) + * GFACT = 400.D0/TEMPC/(40.0D0-TEMPC) + GFACI = 100.D0 + IF (RAD0.GT.0.D0 .AND. XYLAI(IJLOOP,LDT).GT.0.D0) THEN + GFACI=1.D0/BIOFIT(DRYCOEFF,XYLAI(IJLOOP,LDT), + * SUNCOS(IJLOOP),CFRAC(IJLOOP)) + ENDIF + + RIX = RIX*GFACT*GFACI + 150 CONTINUE +C* +C* Compute aerodynamic resistance to lower elements in lower part +C* of the canopy or structure, assuming level terrain - +C* equation (5) of Wesely [1989]. +C* + RDC = 100.D0*(1.0D0+1000.0D0/(RAD0 + 10.D0)) +C* +C* Loop over species; species-dependent corrections to resistances +C* are from equations (6)-(9) of Wesely [1989]. +C* + DO 160 K = 1,NUMDEP +C** exit for non-depositing species or aerosols. + IF (.NOT. LDEP(K) .OR. AIROSOL(K)) GOTO 155 + XMWH2O = 18.D-3 +! RIXX = RIX*DIFFG(TEMPK,PRESS,XMWH2O)/ +! C DIFFG(TEMPK,PRESS,XMW(K)) +C* Replace PRESS with actual sea level pressure (PRESSU) (jaegle 5/11/11) + RIXX = RIX*DIFFG(TEMPK,PRESSU(IJLOOP),XMWH2O)/ + C DIFFG(TEMPK,PRESSU(IJLOOP),XMW(K)) + C + 1.D0/(HSTAR(K)/3000.D0+100.D0*F0(K)) + RLUXX = 1.D12 + IF (RLU(LDT).LT.9999.D0) + C RLUXX = RLU(LDT)/(HSTAR(K)/1.0D+05 + F0(K)) +C* +C* To prevent virtually zero resistance to species with huge HSTAR, such +C* as HNO3, a minimum value of RLUXX needs to be set. The rationality +C* of the existence of such a minimum is demonstrated by the observed +C* relationship between Vd(NOy-NOx) and Ustar in Munger et al.[1996]; +C* Vd(HNO3) never exceeds 2 cm s-1 in observations. The +C* corresponding minimum resistance is 50 s m-1. This correction +C* was introduced by J.Y. Liang on 7/9/95. +C* + !----------------------------------------------------------- + ! Prior to 7/21/03: + ! Remove the cap of surface resistance (rjp, bmy, 7/21/03) + !IF(RLUXX.LT. 50.D0) RLUXX= 50.D0 + !----------------------------------------------------------- +C + RGSX = 1.D0/(HSTAR(K)/1.0D+05/RGSS(LDT) + + 1 F0(K)/RGSO(LDT)) + RCLX = 1.D0/(HSTAR(K)/1.0D+05/RCLS(LDT) + + 1 F0(K)/RCLO(LDT)) +C* +C** Get the bulk surface resistance of the canopy, RSURFC, from the network +C** of resistances in parallel and in series (Fig. 1 of Wesely [1989]) + DTMP1=1.D0/RIXX + DTMP2=1.D0/RLUXX + DTMP3=1.D0/(RAC(LDT)+RGSX) + DTMP4=1.D0/(RDC+RCLX) + RSURFC(K,LDT) = 1.D0/(DTMP1 + DTMP2 + DTMP3 + DTMP4) +C Save the within canopy depvel of NOx, used in calculating the +C canopy reduction factor for soil emissions. + ! Remove hardwire for CANOPYNOX (bmy, 1/24/03) + IF ( K == DRYDNO2 ) THEN + CANOPYNOX(IJLOOP,LDT)=DTMP1+DTMP2+DTMP3+DTMP4 + ENDIF +C** get surface deposition velocity for aerosols if needed; +C** equations (15)-(17) of Walcek et al. [1986] + 155 IF (.NOT. AIROSOL(K)) GOTO 160 + + !=========================================================== + ! The difference between sea-salt and dust tracers below + ! is whether or not we account for hygroscopic growth. + ! Seasalt (yes), Dust (no) (bec, bmy, 4/13/05 ) + !=========================================================== + + IF ( ( DEPNAME(K) == 'SALA' ) .OR. + & ( DEPNAME(K) == 'SALC' ) .OR. + & ( DEPNAME(K) == 'SO4S' ) .OR. + & ( DEPNAME(K) == 'NITS' ) ) THEN + + !===================================================== + ! Use size-resolved dry deposition calculations for + ! seasalt aerosols. We need to account for the + ! hygroscopic growth of the aerosol particles. + ! (rjp, bec, bmy, 4/13/05) + !===================================================== + +!--------------------------------------------------------------------------- +! NOTE: We need to add a new subroutine if you want to use the +! Seinfeld 1986 mechanism (bec, bmy, 4/13/05) +! ! [Seinfeld, 1986] +! RSURFC(K,LDT) = +! & AERO_sfcRsI(K, II, PRESS*1D-3, TEMPK, USTAR(IJLOOP)) +!--------------------------------------------------------------------------- + + ! [Zhang et al., 2001] + ! Modified to use actual slp in instead of fixed value + ! also added W10 (10m windspeed) (jaegle 5/11/11) +! RSURFC(K,LDT) = +! & AERO_SFCRSII( K, II, PRESS*1D-3, +! & TEMPK, USTAR(IJLOOP), RHB(IJLOOP) ) + RSURFC(K,LDT) = + & AERO_SFCRSII( K, II, PRESS*1D-3, + & TEMPK, USTAR(IJLOOP), RHB(IJLOOP), + & W10(IJLOOP) ) + + ELSE IF ( ( DEPNAME(K) == 'DST1' ) .OR. + & ( DEPNAME(K) == 'DST2' ) .OR. + & ( DEPNAME(K) == 'DST3' ) .OR. + & ( DEPNAME(K) == 'DST4' ) ) THEN + + !===================================================== + ! Use size-resolved dry deposition calculations for + ! dust aerosols only. Do not account for hygroscopic + ! growth of the dust aerosol particles. + ! (rjp, bec, bmy, 4/13/05) + !===================================================== + +! ! [Seinfeld, 1986] +! RSURFC(K,LDT) = +! & DUST_sfcRsI(K, II, PRESS*1D-3, TEMPK, USTAR(IJLOOP)) + + ! [Zhang et al., 2001] + ! Modified to use actual slp (jaegle 5/11/11) + RSURFC(K,LDT) = +! & DUST_SFCRSII(K, II, PRESS*1D-3, TEMPK, USTAR(IJLOOP)) + & DUST_SFCRSII(K, II, PRESSU(IJLOOP)*1D-3, TEMPK, + & USTAR(IJLOOP)) + + ELSE + + !===================================================== + ! Replace original code to statement 160 here: only + ! do this for non-size-resolved tracers where + ! AIROSOL(K)=T. (rjp, tdf, bec, bmy, 4/20/04) + !===================================================== + VDS = 0.002D0*USTAR(IJLOOP) + IF (OBK(IJLOOP) .LT. 0.0D0) THEN + VDS = VDS*(1.D0+(-300.D0/OBK(IJLOOP))**0.6667D0) + ENDIF +C*** + IF ( OBK(IJLOOP) .EQ. 0.0D0 ) + c WRITE(6,156) OBK(IJLOOP),IJLOOP,LDT + 156 FORMAT(1X,'OBK(IJLOOP)=',E11.2,1X,' IJLOOP =',I4, + c 1X,'LDT=',I3/) + CZH = ZH(IJLOOP)/OBK(IJLOOP) + IF (CZH.LT.-30.0D0) VDS = 0.0009D0*USTAR(IJLOOP)* + x (-CZH)**0.6667D0 +C* +C* Set VDS to be less than VDSMAX (entry in input file divided by 1.D4) +C* VDSMAX is taken from Table 2 of Walcek et al. [1986]. +C* Invert to get corresponding R + + RSURFC(K,LDT) = 1.D0/MIN(VDS, DBLE(IVSMAX(II))/1.D4) + ENDIF + 160 CONTINUE +C* + 170 CONTINUE +C* +C* Set max and min values for bulk surface resistances +C* + DO 190 K = 1,NUMDEP + IF (.NOT.LDEP(K)) GOTO 190 + DO 180 LDT = 1,IJREG(IJLOOP) + IF (IJUSE(IJLOOP,LDT) .EQ. 0) GOTO 180 + RSURFC(K,LDT)= MAX(1.D0, MIN(RSURFC(K,LDT), 9999.D0)) + 180 CONTINUE + 190 CONTINUE +C* +C* Loop through the different landuse types present in the grid square +C* + DO 500 LDT=1, IJREG(IJLOOP) + IF (IJUSE(IJLOOP,LDT) .EQ. 0) GOTO 500 + IOLSON = IJLAND(IJLOOP,LDT)+1 + +#if defined( GCAP ) +! NOTE: This section only applies to the GCAP/GISS model (swu, bmy, 5/25/05) +!** Get roughness heights; they are specified constants for each surface +!** type except over water where zo = f(u*). The latter dependence +!** is from equation (6) of Hicks and Liss [1976]. + DO 200 IW=1,NWATER + IF (IOLSON .NE. IWATER(IW)) GOTO 200 + ZO(LDT) = 1.4D-02*USTAR(IJLOOP)*USTAR(IJLOOP)/9.8D0 + 1 + 1.1D-01*XNU/USTAR(IJLOOP) + GOTO 210 + 200 CONTINUE + ZO(LDT) = DBLE(IZO(IOLSON))*1.D-4 + 210 CONTINUE +#endif + +C***** Get aerodynamic resistances Ra and Rb. *********************** +C The aerodynamic resistance Ra is integrated from altitude z0+d up to the +C altitude z1 at which the dry deposition velocity is to be referenced. +C The integration corrects for stability using Monin-Obukhov similarity +C formulas from Businger et al. [1971] which apply over the range +C -2.5 < z/zMO < 1.5 (see their Figure 2). +C Under very unstable conditions when z1 > -2.5 zMO, we assume that there is +C no resistance to transfer in the convective column between zMO and z1. +C Under very stable conditions when z1 > 1.5 zMO, we assume that vertical +C transfer in the column between zMO and z1 is strongly suppressed so +C that the deposition velocity at altitude z1 is very low. Under these +C conditions we just specify a very large Ra=1.E4 s m-1 (LRGERA = T). +C** +C The Reynolds number REYNO diagnoses whether a surface is +C aerodynamically rough (REYNO > 1) or smooth. +C +C NOTE: The criterion "REYNO > 1" was originally "REYNO > 10". +C See below for an explanation of why it was changed (hyl, 10/15/99) +C +C Surface is rough in all cases except over water with low wind speeds. +C In the smooth case, vertical transport IN THE SUBLAYER near the surface +C is limited by molecular diffusion and is therefore very slow; we assign +C a large value we assign a large value of Ra + Rb to account for this +C effect. [In Versions 3.2 and earlier we used the formulation for Ra + Rb +C given in Equation (12) of Walcek et al [1986] to calculate the aerodynamic +C resistance over smooth surfaces. However, that expression fails when +C u* is very small, as it yields negative values of Ra + Rb]. +C (djj, hyl, bmy, 5/8/00) +C** +C In the aerodynamically rough case, the expression for Ra is as +C given in equation (5) of Jacob et al. [1992]: +C +C Ra = (1/ku*)*int(from z0 to z1) (phi(x)/z)dz +C +C where x = (z-D)/zMO, z is the height above ground, and D is the +C displacement height which is typically 70-80% of the canopy height +C [Brutsaert, 1982]. We change the vertical coordinate so that z=0 at +C the displacement height; that's OK since for all practical applications +C z1 >> D. In this manner we don't need to assume any specific value for +C the displacement height. Applying the variable transformation +C z -> x = z/zMO, the equation above becomes +C +C Ra = (1/ku*)*int(from x0 to x1) (phi(x)/x)dx with x=z/zMO +C +C Here phi is a stability correction function originally formulated by +C Businger et al. [1971] and given in eqns 5a and 5b of Jacob et al. [1992]. +C For unstable conditions, +C +C phi(x) = a/sqrt(1-bx) where a=0.74, b = 9 +C +C The analytical solution to the integral is +C [Dwight, 1957, integral 192.11]: +C +C int(dx/(x*sqrt(1-bx))) = log(abs((sqrt(1-bx)-1)/(sqrt(1-bx)+1))) +C +C which yields the expression for Ra used in the code for unstable +C conditions. For stable conditions, +C +C phi(x) = a + bx where a=0.74, b = 4.7 +C +C and the analytical solution to the integral is +C +C int((a/x)+b)dx = a*ln(x) + bx +C +C which yields the expression of Ra used in the code for stable conditions. +C** +C The formulation of RB for gases is equation (12) of +C Walcek et al. [1986]. The parameterization for deposition of +C aerosols does not include an RB term so RB for aerosols is set +C to zero. +C********************************************************************* + CKUSTR = XCKMAN*USTAR(IJLOOP) + + ! Define REYNO for GCAP or GEOS met fields (swu, bmy, 5/25/05) +#if defined( GCAP ) + REYNO = USTAR(IJLOOP)*ZO(LDT)/XNU +#else + REYNO = USTAR(IJLOOP)*ZO(IJLOOP)/XNU +#endif + + IF ( OBK(IJLOOP) .EQ. 0.0D0 ) + c WRITE(6,211) OBK(IJLOOP),IJLOOP,LDT + 211 FORMAT(1X,'OBK(IJLOOP)=',E11.2,1X,' IJLOOP = ',I4,1X, + c 'LDT=',I3/) + CORR1 = CZ/OBK(IJLOOP) + + ! Define Z0OBK for GCAP or GEOS met fields (swu, bmy, 5/25/05) +#if defined( GCAP ) + Z0OBK = ZO(LDT)/OBK(IJLOOP) +#else + Z0OBK = ZO(IJLOOP)/OBK(IJLOOP) +#endif + + LRGERA(IJLOOP) = .FALSE. + IF (CORR1 .GT. 0.D0) THEN + IF (CORR1 .GT. 1.5D0) LRGERA(IJLOOP) = .TRUE. + ELSEIF(CORR1 .LE. 0.D0) THEN + IF (CORR1 .LE. -2.5D0) CORR1 = -2.5D0 + CORR2 = LOG(-CORR1) + ENDIF +C* + IF (CKUSTR.EQ.0.0D0) THEN + WRITE(6,212) IJLOOP,CKUSTR,XCKMAN,USTAR(IJLOOP) + 212 FORMAT(1X,'IJLOOP= ',I4,1X,'CKUSTR=',E10.1,1X, + x 'XCKMAN= ',E12.4,1X,'USTAR(IJLOOP)= ', + x E12.4) + CLOSE(98) + STOP ! debug + ENDIF +C +C +C...aerodynamically rough or smooth surface +C "In the classic study by Nikuradse (1933) the transition from smooth +C to rough was examined in pipe flow. He introduced a roughness Reynolds +C number Rr = U* Z0 / Nu and found the flow to be smooth for Rr < 0.13 +C and rough for Rr > 2.5 with a transition regime in between." +C (E.B. Kraus and J.A. Businger, Atmosphere-Ocean Interaction, second +C edition, P.144-145, 1994). Similar statements can be found in the books: +C Evaporation into the atmosphere, by Wilfried Brutsaert, P.59,89, 1982; +C or Seinfeld & Pandis, P.858, 1998. Here we assume a sudden transition +C point Rr = 1 from smooth to rough, following L. Merlivat (1978, The +C dependence of bulk evaporation coefficients on air-water interfacial +C conditions as determined by the isotopic method, J. Geophys. Res., +C Oceans & Atmos., 83, C6, 2977-2980). Also refer to Brutsaert's book, +C P.125. We used to use the criterion "REYNO > 10" for aerodynamically +C rough surface and now change to "REYNO > 1". (hyl, 10/15/99) +C +C 11/17/05: D. J. Jacob says to change the criterion for aerodynamically +C rough surface to REYNO > 0.1 (eck, djj, bmy, 11/17/05) + IF ( REYNO < 0.1d0 ) GOTO 220 + +C...aerodynamically rough surface. +C* + IF (CORR1.LE.0.0D0 .AND. Z0OBK .LT. -1.D0)THEN +C*... unstable condition; set RA to zero. (first implemented in V. 3.2) + RA = 0.D0 + ELSEIF (CORR1.LE.0.0D0 .AND. Z0OBK .GE. -1.D0) THEN +C*... unstable conditions; compute Ra as described above. + DUMMY1 = (1.D0 - 9D0*CORR1)**0.5D0 + DUMMY2 = (1.D0 - 9D0*Z0OBK)**0.5D0 + DUMMY3 = ABS((DUMMY1 - 1.D0)/(DUMMY1 + 1.D0)) + DUMMY4 = ABS((DUMMY2 - 1.D0)/(DUMMY2 + 1.D0)) + RA = 0.74D0* (1.D0/CKUSTR) * LOG(DUMMY3/DUMMY4) + + ELSEIF((CORR1.GT.0.0D0).AND.(.NOT.LRGERA(IJLOOP)))THEN +C*...moderately stable conditions (z/zMO <1); compute Ra as described above + RA = (1D0/CKUSTR) * + & (.74D0*LOG(CORR1/Z0OBK) + 4.7D0*(CORR1-Z0OBK)) + ELSEIF(LRGERA(IJLOOP)) THEN +C*... very stable conditions + RA = 1.D+04 + ENDIF +C* check that RA is positive; if RA is negative (as occasionally +C* happened in version 3.1) send a warning message. + + + + IF (CORR1.LT.0.0D0) THEN +C*... unstable conditions; compute Ra as described above. + !coef_a=1.d0 + !coef_b=15.d0 + DUMMY1 = (1.D0 - 15.D0*CORR1)**0.5D0 + DUMMY2 = (1.D0 - 15.D0*Z0OBK)**0.5D0 + DUMMY3 = ABS((DUMMY1 - 1.D0)/(DUMMY1 + 1.D0)) + DUMMY4 = ABS((DUMMY2 - 1.D0)/(DUMMY2 + 1.D0)) + RA = 1.D0 * (1.D0/CKUSTR) * LOG(DUMMY3/DUMMY4) + ELSEIF((CORR1.GE.0.0D0).AND.(CORR1.LE.1.0D0)) THEN + !coef_a=1.d0 + !coef_b=5.d0 + RA = (1D0/CKUSTR) * + & (1.D0*LOG(CORR1/Z0OBK) + 5.D0*(CORR1-Z0OBK)) + ELSE ! CORR1 .GT. 1.0D0 + !coef_a=5d0 + !coef_b=1.d0 + RA = (1D0/CKUSTR) * + & (5.D0*LOG(CORR1/Z0OBK) + 1.D0*(CORR1-Z0OBK)) + ENDIF + + + RA = MIN(RA,1.D4) + +#if defined( GCAP ) + ! Debug output for GISS/GCAP model (swu, bmy, 5/25/05) + IF (RA .LT. 0.) THEN + WRITE (6,1001) IJLOOP,RA,CZ,ZO(LDT),OBK(IJLOOP) + ENDIF +#else + ! For GEOS-CTM, We use ZO(MAXIJ), and IJLOOP is the index. + ! Also, if RA is < 0, set RA = 0 (bmy, 11/12/99) + IF (RA .LT. 0.D0) THEN + WRITE (6,1001) IJLOOP,RA,CZ,ZO(IJLOOP),OBK(IJLOOP) + RA = 0.0D0 + ENDIF +#endif + 1001 FORMAT('WARNING: RA < 0 IN SUBROUTINE DEPVEL', + & I10,4(1X,E12.5)) +C* Get total resistance for deposition - loop over species. + DO 215 K = 1,NUMDEP + IF (.NOT.LDEP(K)) GOTO 215 +C** DAIR is the thermal diffusivity of air; value of 0.2*1.E-4 m2 s-1 +C** cited on p. 16,476 of Jacob et al. [1992] + DAIR = 0.2D0*1.D-4 + RB = (2.D0/CKUSTR)* + x (DAIR/DIFFG(TEMPK,PRESS,XMW(K)))**0.667D0 + IF (AIROSOL(K)) RB=0.D0 + C1X(K) = RA + RB + RSURFC(K,LDT) + 215 CONTINUE + GOTO 240 + 220 CONTINUE +C** ... aerodynamically smooth surface +C** BUG FIX -- suppress drydep over smooth surfaces by setting Ra to a large +C** value (1e4). This prevents negative dry deposition velocities when u* +C** is very small (djj, bmy, 5/8/00) + DO 230 K = 1,NUMDEP + IF ( LDEP(K) ) THEN + RA = 1.0D4 + C1X(K) = RA + RSURFC(K,LDT) + ENDIF + 230 CONTINUE + + 240 CONTINUE +C* +C* IJUSE is the fraction of the grid square occupied by surface LDT +C* in units of per mil (IJUSE=500 -> 50% of the grid square). Add +C* the contribution of surface type LDT to the deposition velocity; +C* this is a loop over all surface types in the gridbox. +C* + DO 400 K = 1,NUMDEP + IF (.NOT.LDEP(K)) GOTO 400 + VK(K) = VD(K) + VD(K) = VK(K) +.001D0*DBLE(IJUSE(IJLOOP,LDT))/C1X(K) + 400 CONTINUE + 500 CONTINUE + +C** Load array DVEL + DO 550 K=1,NUMDEP + IF (.NOT.LDEP(K)) GOTO 550 + DVEL(IJLOOP,K) = VD(K) + + ! Now check for negative deposition velocity + ! before returning to calling program (bmy, 4/16/00) + ! Also call CLEANUP to deallocate arrays (bmy, 10/15/02) + IF ( DVEL(IJLOOP,K) < 0d0 ) THEN +!$OMP CRITICAL + PRINT*, 'DEPVEL: Deposition velocity is negative!' + PRINT*, 'Dep. Vel = ', DVEL(IJLOOP,K) + PRINT*, 'Species = ', K + PRINT*, 'IJLOOP = ', IJLOOP + PRINT*, 'RADIAT = ', RADIAT(IJLOOP) + PRINT*, 'TEMP = ', TEMP(IJLOOP) + PRINT*, 'SUNCOS = ', SUNCOS(IJLOOP) + PRINT*, 'USTAR = ', USTAR(IJLOOP) + PRINT*, 'CZ1 = ', CZ1(IJLOOP) + PRINT*, 'OBK = ', OBK(IJLOOP) + PRINT*, 'CFRAC = ', CFRAC(IJLOOP) + PRINT*, 'ZH = ', ZH(IJLOOP) + PRINT*, 'LRGERA = ', LRGERA(IJLOOP) + PRINT*, 'ZO = ', ZO(IJLOOP) + PRINT*, 'STOP in depvel.f!' + CALL CLEANUP + STOP +!$OMP END CRITICAL + ENDIF + + ! Now check for IEEE NaN (not-a-number) condition + ! before returning to calling program (bmy, 4/16/00) + ! Also call CLEANUP to deallocate arrays (bmy, 10/15/02) + IF ( IT_IS_NAN( DVEL(IJLOOP,K) ) ) THEN +!$OMP CRITICAL + PRINT*, 'DEPVEL: Deposition velocity is NaN!' + PRINT*, 'Dep. Vel = ', DVEL(IJLOOP,K) + PRINT*, 'Species = ', K + PRINT*, 'IJLOOP = ', IJLOOP + PRINT*, 'RADIAT = ', RADIAT(IJLOOP) + PRINT*, 'TEMP = ', TEMP(IJLOOP) + PRINT*, 'SUNCOS = ', SUNCOS(IJLOOP) + PRINT*, 'USTAR = ', USTAR(IJLOOP) + PRINT*, 'CZ1 = ', CZ1(IJLOOP) + PRINT*, 'OBK = ', OBK(IJLOOP) + PRINT*, 'CFRAC = ', CFRAC(IJLOOP) + PRINT*, 'ZH = ', ZH(IJLOOP) + PRINT*, 'LRGERA = ', LRGERA(IJLOOP) + PRINT*, 'ZO = ', ZO(IJLOOP) + CALL CLEANUP + STOP +!$OMP END CRITICAL + ENDIF + 550 CONTINUE + 560 CONTINUE +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE DEPVEL + +!------------------------------------------------------------------------------ + + FUNCTION DIFFG( TK, PRESS, XM ) RESULT( DIFF_G ) +! +!****************************************************************************** +! Function DIFFG calculates the molecular diffusivity [m2/s] in air for a +! gas X of molecular weight XM [kg] at temperature TK [K] and +! pressure PRESS [Pa]. (bmy, 5/16/06) +! +! We specify the molecular weight of air (XMAIR) and the hard-sphere molecular +! radii of air (RADAIR) and of the diffusing gas (RADX). The molecular +! radius of air is given in a Table on p. 479 of Levine [1988]. The Table +! also gives radii for some other molecules. Rather than requesting the user +! to supply a molecular radius we specify here a generic value of 2.E-10 m for +! all molecules, which is good enough in terms of calculating the diffusivity +! as long as molecule is not too big. +! +! Arguments as Input: +! ============================================================================ +! (1 ) TK (REAL*8) : Temperature [K] +! (2 ) PRESS (REAL*8) : Pressure [Pa] +! (3 ) XM (REAL*8) : Molecular weight of gas [kg] +! +! NOTES: +! (1 ) Originally was a standalone function; now bundled into drydep_mod.f. +! Also now force REAL*8 precision with D exponents. Now use F90 +! style syntax and updated comments. (bmy, 5/16/06) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: TK + REAL*8, INTENT(IN) :: PRESS + REAL*8, INTENT(IN) :: XM + + ! Local variables + REAL*8 :: AIRDEN, Z, DIAM, FRPATH, SPEED, DIFF_G + REAL*8, PARAMETER :: XMAIR = 28.8d-3 + REAL*8, PARAMETER :: RADAIR = 1.2d-10 + REAL*8, PARAMETER :: PI = 3.1415926535897932d0 + REAL*8, PARAMETER :: RADX = 1.5d-10 + REAL*8, PARAMETER :: RGAS = 8.32d0 + REAL*8, PARAMETER :: AVOGAD = 6.023d23 + + !================================================================= + ! DIFFG begins here! + !================================================================= + + ! Air density + AIRDEN = ( PRESS * AVOGAD ) / ( RGAS * TK ) + + ! DIAM is the collision diameter for gas X with air. + DIAM = RADX + RADAIR + + ! Calculate the mean free path for gas X in air: + ! eq. 8.5 of Seinfeld [1986]; + Z = XM / XMAIR + FRPATH = 1d0 /( PI * SQRT( 1d0 + Z ) * AIRDEN*( DIAM**2 ) ) + + ! Calculate average speed of gas X; eq. 15.47 of Levine [1988] + SPEED = SQRT( 8d0 * RGAS * TK / ( PI * XM ) ) + + ! Calculate diffusion coefficient of gas X in air; + ! eq. 8.9 of Seinfeld [1986] + DIFF_G = ( 3d0 * PI / 32d0 ) * ( 1d0 + Z ) * FRPATH * SPEED + + ! Return to calling program + END FUNCTION DIFFG + +!------------------------------------------------------------------------------ + + SUBROUTINE MODIN +! +!****************************************************************************** +! Subroutine MODIN reads Olson's data from the file "drydep.table". +! (bmy, 4/1/02, 7/20/04) +! +! NOTE: The roughness heights (IZO) from "drydep.table" are supplanted by +! the Z0 field from the DAO met field archive. The old GISS-II routines did +! not archive Z0 as a met field, so roughness heights for each land type +! were specified in this file. This is historical baggage, but we still +! need to keep IZO for compatibility w/ existing routine "depvel.f". +! +! References (see above for full citations): +! ============================================================================ +! (1 ) Wesely, M.L., 1988. +! (2 ) Wesely, M.L., 1989. +! +! NOTES: +! (1 ) MODIN is one of the original GEOS-CHEM subroutines, that go back +! to the days of the GISS-II code. This has been cleaned up and +! new comments added. Also use subroutine "ioerror.f" to trap +! I/O errors across all platforms . Now read the "drydep.table" file +! from the DATA_DIR/drydep_200203/ directory. (bmy, 4/1/02) +! (2 ) Remove obsolete code from April 2002. Now reference IU_FILE and +! IOERROR from "file_mod.f". Now use IU_FILE as the file unit +! number instead of IUNIT. (bmy, 6/27/02) +! (3 ) Now bundled into "drydep_mod.f". Changed NVEGTYPE to NNVEGTYPE. +! (bmy, 11/21/02) +! (4 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : IU_FILE, IOERROR + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: L, IOLSON, I, IOS, IUNIT + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! MODIN begins here! + !================================================================= + + ! Logical unit number + IUNIT = IU_FILE + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'drydep_200203/drydep.table' + + WRITE( 6, 50 ) TRIM( FILENAME ) + 50 FORMAT( ' - MODIN: Reading ', a ) + + ! Open file + OPEN( IUNIT, FILE=TRIM( FILENAME ), FORM='FORMATTED', + & STATUS='OLD', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'modin:1' ) + + ! Read 5 header comment lines + DO L = 1, 5 + READ( IUNIT, '(a)', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'modin:2' ) + ENDDO + + !================================================================= + ! For each of the NVEGTYPE Olson land types, read: + ! + ! IOLSON (INTEGER) : Olson surface type ID # + ! IDEP (INTEGER) : Drydep ID # corresponding to IOLSON + ! IZO (INTEGER) : Roughness height [1e-4 m] + !================================================================= + DO L = 1, NNVEGTYPE + READ( IUNIT, '(3i6)', IOSTAT=IOS ) + & IOLSON, IDEP(IOLSON), IZO(IOLSON) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'modin:3' ) + ENDDO + + ! Read comment line + READ( IUNIT, '(a)', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'modin:4' ) + + !================================================================= + ! For the water surface types, zO is input as 1.E-4 m but is + ! recalculated elsewhere as function of wind speed. Read the # + ! of Olson's surface types that are water (NWATER) and the + ! corresponding ID's (IWATER) + !================================================================= + READ( IUNIT, '(10i3)', IOSTAT=IOS ) NWATER, (IWATER(I),I=1,NWATER) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'modin:5' ) + + ! Read 3 lines of comments + DO L = 1, 3 + READ( IUNIT, '(a)', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'modin:6' ) + ENDDO + + !================================================================= + ! Read in resistances for each surface type (see "depvel.f") + ! IRI,IRLU,IRAC,IRGSS,IRGSO,IRCLS,IRCLO,IVSMAX + !================================================================= + DO L = 1, NNVEGTYPE + READ( IUNIT, '(9i5)', IOSTAT=IOS ) + & I, IRI(I), IRLU(I), IRAC(I), IRGSS(I), + & IRGSO(I), IRCLS(I), IRCLO(I), IVSMAX(I) + + IF ( IOS < 0 ) EXIT + IF ( IOS > 0 ) CALL IOERROR( IOS, IUNIT, 'modin:7' ) + ENDDO + + ! Close the file + CLOSE( IUNIT ) + + ! Return to calling program + END SUBROUTINE MODIN + +!------------------------------------------------------------------------------ + + SUBROUTINE RDDRYCF +! +!****************************************************************************** +! Subroutine RDDRYCF read polynomial coefficients from the "drydep.coef" +! file in the data directory (bmy, 7/6/01, 7/20/04) +! +! NOTES: +! (1 ) Use F90 syntax. Now read "drydep.coef" directly from DATA_DIR. +! Now use IOERROR to trap I/O errors. Updated comments and made +! cosmetic changes (bmy, 7/6/01) +! (2 ) Removed obsolete code from ages past (bmy, 9/4/01) +! (3 ) Now read the "drydep.coef" file from the DATA_DIR/drydep_200203/ +! directory. Make IUNIT a dynamic variable and not a parameter. +! (bmy, 3/29/02) +! (4 ) Removed obsolete code from March 2002. Now reference IU_FILE and +! IOERROR from "file_mod.f". Now use IU_FILE as the logical unit +! number. (bmy, 6/27/02) +! (5 ) Bundled into "drydep_mod.f" (bmy, 11/21/02) +! (6 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : IU_FILE, IOERROR + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: I, IOS + CHARACTER(LEN=80) :: DUM + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! RDDRYCF begins here! + !================================================================= + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'drydep_200203/drydep.coef' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - RDDRYCF: Reading ', a ) + + ! Open file + OPEN( IU_FILE, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='FORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'rddrycf:1' ) + + ! Read header line + READ( IU_FILE, '(a80)', IOSTAT=IOS ) DUM + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'rddrycf:2' ) + + ! Read polynomial coefficients + READ( IU_FILE,'(8(1pe10.2))', IOSTAT=IOS) (DRYCOEFF(I),I=1,NNPOLY) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'rddrycf:3' ) + + ! Close file + CLOSE( IU_FILE ) + + ! Return to calling program + END SUBROUTINE RDDRYCF + +!------------------------------------------------------------------------------ + + FUNCTION AERO_SFCRSII( K, II, PRESS, TEMP, USTAR, RHB, + & W10 ) RESULT(RS) +! +!****************************************************************************** +! Function AERO_SFCRSII computes the aerodynamic resistance of seasalt aerosol +! tracers according to Zhang et al 2001. We account for hygroscopic growth +! of the seasalt aerosol particles (rjp, tdf, bec, bmy, 4/1/04, 6/11/08) +! +! Arguments as Input: +! ============================================================================ +! (1 ) K (INTEGER) : Dry deposition tracer index (range: 1-NUMDEP) +! (2 ) II (INTEGER) : GEOS-CHEM surface type index +! (3 ) PRESS (REAL*8 ) : Pressure [kPa] (where 1 Kpa = 0.1 mb) +! (4 ) TEMP (REAL*8 ) : Temperature [K] +! (5 ) USTAR (REAL*8 ) : Friction Velocity [m/s] +! (6 ) RHB (REAL*8) : Relative humidity (fraction) +! (7 ) W10 (REAL*8) : 10m windspeed [m/s] +! +! Function Value +! ============================================================================ +! (6 ) Rs (REAL*8 ) : Surface resistance for dust particles [s/m] +! +! NOTES +! (1 ) Updated comments. Also now force double precision w/ "D" exponents. +! (bmy, 4/1/04) +! (2 ) Now limit relative humidity to [tiny(real*8),0.99] range for DLOG +! argument (phs, 6/11/08) +! (3 ) Bug fixes to the Gerber (1985) growth function (jaegle 5/11/11) +! (4) Update growth function to Lewis and Schwartz (2006) and density +! calculation based on Tang et al. (1997) (bec, jaegle 5/11/11) +! (5 ) Updates of sea salt deposition over water to follow the Slinn & Slinn (1980) +! formulation over water surface. Described in Jaegle et al. (ACP, 11, 2011) (jaegle 5/11/11) +!****************************************************************************** +! + ! References to F90 module + ! Added for size distribution (jaegle 5/11/11) + USE TRACER_MOD, ONLY : SALA_REDGE_um, SALC_REDGE_um + + ! Arguments + INTEGER, INTENT(IN) :: K ! INDEX OF NUMDEP + INTEGER, INTENT(IN) :: II ! Surface type index of GEOS-CHEM + REAL*8, INTENT(IN) :: PRESS ! Pressure in Kpa 1 mb = 100 pa = 0.1 kPa + REAL*8, INTENT(IN) :: TEMP ! Temperature (K) + REAL*8, INTENT(IN) :: USTAR ! Friction velocity (m/s) + REAL*8, INTENT(IN) :: RHB ! Relative humidity (fraction) + ! Added 10m windspeed (jaegle 5/11/11) + REAL*8, INTENT(IN) :: W10 ! 10 meter windspeed + + ! Function value + REAL*8 :: RS ! Surface resistance for particles [s/m] + + ! Local variables + INTEGER :: N + REAL*8, PARAMETER :: C1 = 0.7674d0, C2 = 3.079d0, + & C3 = 2.573d-11, C4 = -1.424d0 + + REAL*8, PARAMETER :: G0 = 9.8D0 + REAL*8, PARAMETER :: BETA = 2.d0 + REAL*8, PARAMETER :: BOLTZ = 1.381d-23 ! Boltzmann constant (J/K) + REAL*8, PARAMETER :: E0 = 3.d0 + REAL*8 :: AIRVS ! kinematic viscosity of Air (m^2/s) + REAL*8 :: DP ! Diameter of aerosol [um] + REAL*8 :: PDP ! Press * Dp + REAL*8 :: CONST ! Constant for settling velocity calculations + REAL*8 :: SLIP ! Slip correction factor + REAL*8 :: VISC ! Viscosity of air (Pa s) + REAL*8 :: DIFF ! Brownian Diffusion constant for particles (m2/s) + REAL*8 :: SC, ST ! Schmidt and Stokes number (nondim) + REAL*8 :: RHBL ! Relative humidity local + + ! replace RCM with RUM (radius in microns instead of cm) - jaegle 5/11/11 + !REAL*8 :: DIAM, DEN, RATIO_R, RWET, RCM + REAL*8 :: DIAM, DEN, RATIO_R, RWET, RUM + REAL*8 :: FAC1, FAC2 + REAL*8 :: EB, EIM, EIN, R1, AA, VTS + ! New variables added (jaegle 5/11/11) + REAL*8 :: SW + REAL*8 :: SALT_MASS, SALT_MASS_TOTAL, VTS_WEIGHT, DMIDW ! for weighting the settling velocity + REAL*8 :: D0, D1 !lower and upper bounds of sea-salt dry diameter bins + REAL*8 :: DEDGE + REAL*8 :: DEN1, WTP + INTEGER :: ID,NR + LOGICAL, SAVE :: FIRST = .TRUE. + + !increment of radius for integration of settling velocity (um) + REAL*8, PARAMETER :: DR = 5.d-2 + + ! Parameters for polynomial coefficients to derive seawater + ! density. From Tang et al. (1997) - jaegle 5/11/11 + REAL*8, PARAMETER :: A1 = 7.93d-3 + REAL*8, PARAMETER :: A2 = -4.28d-5 + REAL*8, PARAMETER :: A3 = 2.52d-6 + REAL*8, PARAMETER :: A4 = -2.35d-8 + REAL*8, PARAMETER :: EPSI = 1.0D-4 + + ! parameters for assumed size distribution of accumulation and coarse mode + ! sea salt aerosols, as described in Jaegle et al. (ACP, 11, 2011) (jaegle, 5/11/11) + ! 1) geometric dry mean diameters (microns) + REAL*8, PARAMETER :: RG_A = 0.085d0 + REAL*8, PARAMETER :: RG_C = 0.4d0 + ! 2) sigma of the size distribution + REAL*8, PARAMETER :: SIG_A = 1.5d0 + REAL*8, PARAMETER :: SIG_C = 1.8d0 + REAL*8, PARAMETER :: PI =3.14159D0 + +!======================================================================= +! # LUC [Zhang et al., 2001] GEOS-CHEM LUC (Corr. #) +!----------------------------------------------------------------------- +! 1 - Evergreen needleleaf trees Snow/Ice (12) +! 2 - Evergreen broadleaf trees Deciduous forest ( 4) +! 3 - Deciduous needleleaf trees Coniferous forest ( 1) +! 4 - Deciduous broadleaf trees Agricultural land ( 7) +! 5 - Mixed broadleaf and needleleaf trees Shrub/grassland (10) +! 6 - Grass Amazon forest ( 2) +! 7 - Crops and mixed farming Tundra ( 9) +! 8 - Desert Desert ( 8) +! 9 - Tundra Wetland (11) +! 10 - Shrubs and interrupted woodlands Urban (15) +! 11 - Wet land with plants Water (14) +! 12 - Ice cap and glacier +! 13 - Inland water +! 14 - Ocean +! 15 - Urban +!======================================================================= +! GEOS-CHEM LUC 1, 2, 3, 4, 5, 6, 7 8, 9,10,11 + INTEGER :: LUCINDEX(11) = (/12, 4, 1, 7,10, 2, 9, 8,11,15,14/) + INTEGER :: LUC + + !================================================================= + ! LUC 1, 2, 3, 4, 5, 6, 7, 8, + ! alpha 1.0, 0.6, 1.1, 0.8, 0.8, 1.2, 1.2, 50.0, + ! gamma 0.56, 0.58, 0.56, 0.56, 0.56, 0.54, 0.54, 0.54 + ! + ! LUC 9, 10, 11, 12, 13, 14, 15 + ! alpha 50.0, 1,3, 2.0, 50.0,100.0,100.0, 1.5 + ! gamma 0.54, 0.54, 0.54, 0.54, 0.50, 0.50, 0.56 + !================================================================= + + ! Now force to double precision (bmy, 4/1/04) + REAL*8 :: + & ALPHA(15) = (/ 1.0d0, 0.6d0, 1.1d0, 0.8d0, 0.8d0, + & 1.2d0, 1.2d0, 50.0d0, 50.0d0, 1.3d0, + & 2.0d0, 50.0d0, 100.0d0, 100.0d0, 1.5d0 /) + + ! Now force to double precision (bmy, 4/1/04) + REAL*8 :: + & GAMMA(15) = (/ 0.56d0, 0.58d0, 0.56d0, 0.56d0, 0.56d0, + & 0.54d0, 0.54d0, 0.54d0, 0.54d0, 0.54d0, + & 0.54d0, 0.54d0, 0.50d0, 0.50d0, 0.56d0 /) + +!...A unit is (mm) so multiply by 1.D-3 to (m) +! LUC 1, 2, 3, 4, 5, 6, 7, 8, +! SC1 2.0, 5.0, 2.0, 5.0, 5.0, 2.0, 2.0,-999., +! SC2 2.0, 5.0, 2.0, 5.0, 5.0, 2.0, 2.0,-999., +! A SC3 2.0, 5.0, 5.0, 10.0, 5.0, 5.0, 5.0,-999., +! SC4 2.0, 5.0, 5.0, 10.0, 5.0, 5.0, 5.0,-999., +! SC5 2.0, 5.0, 2.0, 5.0, 5.0, 2.0, 2.0,-999., + +! LUC 9, 10, 11, 12, 13, 14, 15 +! SC1 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! SC2 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! A SC3 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! SC4 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! SC5 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 + + REAL*8 :: A(15,5) + + REAL*8 :: Aavg(15) + + ! Now force to double precision (bmy, 4/1/04) + DATA A / 2.0d0, 5.0d0, 2.0d0, 5.0d0, 5.0d0, + & 2.0d0, 2.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 2.0d0, 5.0d0, 5.0d0, + & 2.0d0, 2.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 5.0d0, 10.0d0, 5.0d0, + & 5.0d0, 5.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 5.0d0, 10.0d0, 5.0d0, + & 5.0d0, 5.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 2.0d0, 5.0d0, 5.0d0, + & 2.0d0, 2.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0 / + + ! Annual average of A + Aavg(:) = (A(:,1)+A(:,2)+A(:,3)+A(:,4)+A(:,5))/5. + LUC = LUCINDEX(II) + AA = Aavg(LUC) * 1.D-3 + + !================================================================= + !...Ref. Zhang et al., AE 35(2001) 549-560 + !. + !...Model theroy + ! Vd = Vs + 1./(Ra+Rs) + ! where Vs is the gravitational settling velocity, + ! Ra is the aerodynamic resistance above the canopy + ! Rs is the surface resistance + ! Here we calculate Rs only.. + ! Rs = 1 / (Eo*Ustar*(Eb+Eim+Ein)*R1) + ! where Eo is an empirical constant ( = 3.) + ! Ustar is the friction velocity + ! Collection efficiency from + ! Eb, [Brownian diffusion] + ! Eim, [Impaction] + ! Ein, [Interception] + ! R1 is the correction factor representing the fraction + ! of particles that stick to the surface. + !======================================================================= + ! Eb is a funciont of Schmidt number, Eb = Sc^(-gamma) + ! Sc = v/D, v (the kinematic viscosity of air) + ! D (particle brownian diffusivity) + ! r usually lies between 1/2 and 2/3 + ! Eim is a function of Stokes number, St + ! St = Vs * Ustar / (g0 * A) for vegetated surfaces + ! St = Vs * Ustar * Ustar / v for smooth surface + ! A is the characteristic radius of collectors. + ! + ! 1) Slinn (1982) + ! Eim = 10^(-3/St) for smooth surface + ! Eim = St^2 / ( 1 + St^2 ) for vegetative canopies + ! 2) Peters and Eiden (1992) + ! Eim = ( St / ( alpha + St ) )^(beta) + ! alpha(=0.8) and beta(=2) are constants + ! 3) Giorgi (1986) + ! Eim = St^2 / ( 400 + St^2 ) for smooth surface + ! Eim = ( St / (0.6 + St) )^(3.2) for vegetative surface + ! 4) Davidson et al.(1982) + ! Eim = St^3 / (St^3+0.753*St^2+2.796St-0.202) for grassland + ! 5) Zhang et al.(2001) used 2) method with alpha varying with + ! vegetation type and beta equal to 2 + ! + ! Ein = 0.5 * ( Dp / A )^2 + ! + ! R1 (Particle rebound) = exp(-St^0.5) + !================================================================= + ! Update (jaegle 5/11/2011): The above formulation of Zhang et al (2001) + ! is valid for land surfaces and was originally based on the work + ! of Slinn (1982). Over water surfaces, the work of reference is that + ! of Slinn and Slinn (1980) who use the term "viscous sublayer" to + ! refer to the thin layer extending 0.1-1mm above the water surface. + ! Due to the proximity of the water, the RH in this layer is much higher + ! than the ambient RH in the surface layer. According to Lewis and + ! Schwartz (2004): "Relative humidities of 99% and 100% were considered + ! by Slinn and Slinn for the viscous sublayer, however near the ocean + ! surface RH would be limited to near 98% because of the vapor pressure + ! lowering of water over seawater due to the salt content". We will + ! thus use a constant value RH=98% over all ocean boxes. This affects + ! the growth of particles (the wet radius at RH=98% is x4 the dry radius) + ! and thus affects all the terms depending on particle size. + ! + ! Other updates for ocean surfaces: + ! a) Over ocean surfaces the formulation from Slinn & Slinn for the + ! resistance in the viscous layer is + ! Rs = 1 / (Cd/XCKMAN*U10m*(Eb+Eim)+VTS) + ! with Cd=(Ustar/U10m)**2, and VTS is the gravitational settling + ! in the viscous layer. Note that the gravitational settling calculated + ! here for the viscous layer is >> than the one calculated for the + ! surface layer in seasalt_mod.f because of the higher RH. + ! b) Eim = 10^(-3/St) based on Slinn and Slinn (1980) + ! + ! References: + ! LEWIS and SCHWARTZ (2004) "SEA SALT AEROSOL PRODUCTION, MECHANISMS, METHODS + ! AND MODELS" AGU monograph 152. + ! SLINN and SLINN (1980), "PREDICTIONS FOR PARTICLE DEPOSITION ON NATURAL-WATERS" + ! Atmos Environ (1980) vol. 14 (9) pp. 1013-1016. + ! SLINN (1982), "PREDICTIONS FOR PARTICLE DEPOSITION TO VEGETATIVE CANOPIES" + ! Atmos Environ (1982) vol. 16 (7) pp. 1785-1794. + !================================================================== + + ! Number of bins for sea salt size distribution + NR =INT((( SALC_REDGE_um(2) - SALA_REDGE_um(1) ) / DR ) + & + 0.5d0 ) + + !================================================================= + ! Define the volume size distribution of sea-salt. This only has + ! to be done once. We assume that sea-salt is the combination of a coarse mode + ! and accumulation model log-normal distribution functions + !================================================================= + !IF ( FIRST) THEN + + ! Lower edge of 0th bin + !DEDGE=SALA_REDGE_um(1) * 2d0 + + ! Loop over diameters + !DO ID = 1, NR + ! Diameter of mid-point in microns + ! DMID(ID) = DEDGE + ( DR ) + + ! Calculate the dry volume size distribution as the sum of two log-normal + ! size distributions. The parameters for the size distribution are + ! based on Reid et al. and Quinn et al. + ! The scaling factors 13. and 0.8 for acc and coarse mode aerosols are + ! chosen to obtain a realistic distribution + ! SALT_V (D) = dV/dln(D) [um3] +! SALT_V(ID) = PI / 6d0* (DMID(ID)**3) * ( +! & 13d0*exp(-0.5*( LOG(DMID(ID))-LOG(RG_A*2d0) )**2d0/ +! & LOG(SIG_A)**2d0 ) +! & /( sqrt(2d0 * PI) * LOG(SIG_A) ) + +! & 0.8d0*exp(-0.5*( LOG(DMID(ID))-LOG(RG_C*2d0) )**2d0/ +! & LOG(SIG_C)**2d0) +! & /( sqrt(2d0 * PI) * LOG(SIG_C) ) ) +! ! update the next edge +! DEDGE = DEDGE + DR*2d0 +! ENDDO +! +! ! Reset after the first time +! IF ( FIRST ) FIRST = .FALSE. +! ENDIF + + ! Particle radius [cm] + ! Bug fix: The Gerber [1985] growth should use the dry radius + ! in micromenters and not cm. Replace RCM with RUM (jaegle 5/11/11) + !RCM = A_RADI(K) * 1.d2 + RUM = A_RADI(K) * 1.d6 + + ! Exponential factors used for hygroscopic growth + ! Replace RCM with RUM (jaegle 5/11/11) + !FAC1 = C1 * ( RCM**C2 ) + !FAC2 = C3 * ( RCM**C4 ) + FAC1 = C1 * ( RUM**C2 ) + FAC2 = C3 * ( RUM**C4 ) + + + ! Aerosol growth with relative humidity in radius [m] + ! (Gerber, 1985) (bec, 12/8/04) + ! Added safety check for LOG (phs, 6/11/08) + RHBL = MAX( TINY(RHB), RHB ) + + ! Over oceans the RH in the viscous sublayer is set to 98%, following + ! Lewis and Schwartz (2004), see discussion above (jaegle 03/18/2010) + IF (LUC == 14) THEN + RHBL = 0.98 + ! Note that the Gerber formula overestimates the growth at 98%RH + ! use a constant factor of 4 instead (jaegle) + !RWET = 1d-6*RUM * 4.d0 + ! eliminate this + RWET = 1.d-6*(FAC1/(FAC2-LOG10(RHBL))+RUM**3.d0)**0.33333d0 + ELSE + !RWET = 0.01d0*(FAC1/(FAC2-DLOG(RHBL))+RCM**3.d0)**0.33d0 + RWET = 1.d-6*(FAC1/(FAC2-LOG10(RHBL))+RUM**3.d0)**0.33333d0 + ENDIF + + + ! Ratio dry over wet radii at the cubic power + RATIO_R = ( A_RADI(K) / RWET )**3.d0 + + ! Diameter of the wet aerosol [m] + DIAM = RWET * 2.d0 + + ! Density of the wet aerosol [kg/m3] (bec, 12/8/04) + !DEN = RATIO_R * A_DEN(K) + ( 1.d0 - RATIO_R ) * 1000.d0 + ! replace with formulation from Tang et al (1997) + ! Need to calculate the solute weight fraction, SW (%) + ! SW = mass of sea-salt/total mass of solution*100 + SW = 100.d0 * (A_DEN(K)*A_RADI(K)**3.d0) / + & (A_DEN(K)*A_RADI(K)**3.d0 + + & 1000d0*(RWET**3.d0-A_RADI(K)**3.d0)) + DEN = 1000.d0* (0.9971 + + & A1 * SW + A2 * SW**2.d0 + + & A3 * SW**3.d0 + A4 * SW**4.d0 ) + + + ! Dp [um] = particle diameter + DP = DIAM * 1.d6 + + ! Constant for settling velocity calculation + CONST = DEN * DIAM**2 * G0 / 18.d0 + + !================================================================= + ! # air molecule number density + ! num = P * 1d3 * 6.023d23 / (8.314 * Temp) + ! # gas mean free path + ! lamda = 1.d6/( 1.41421 * num * 3.141592 * (3.7d-10)**2 ) + ! # Slip correction + ! Slip = 1. + 2. * lamda * (1.257 + 0.4 * exp( -1.1 * Dp + ! & / (2. * lamda))) / Dp + !================================================================= + ! Note, Slip correction factor calculations following Seinfeld, + ! pp464 which is thought to be more accurate but more computation + ! required. + !================================================================= + + ! Slip correction factor as function of (P*dp) + PDP = PRESS * DP + SLIP = 1d0 + ( 15.60d0 + 7.0d0 * EXP( -0.059d0 * PDP) ) / PDP + + !================================================================= + ! Note, Eq) 3.22 pp 50 in Hinds (Aerosol Technology) + ! which produce slip correction factore with small error + ! compared to the above with less computation. + !================================================================= + + ! Viscosity [Pa s] of air as a function of temp (K) + VISC = 1.458d-6 * (TEMP)**(1.5d0) / (TEMP + 110.4d0) + + ! Kinematic viscosity (Dynamic viscosity/Density) + AIRVS= VISC / 1.2928d0 + + ! Settling velocity [m/s] + VTS = CONST * SLIP / VISC + + ! This settling velocity is for the mid-point of the size bin. + ! Need to integrate over the size bin, taking into account the + ! mass distribution of sea-salt and the dependence of VTS on aerosol + ! size. See WET_SETTLING in SEASALT_MOD.f for more details. (jaegle 5/11/11) + SALT_MASS_TOTAL = 0d0 + VTS_WEIGHT = 0d0 + ! Check what the min/max range of the SS size bins are + IF ( RUM .le. SALA_REDGE_um(2) ) THEN + D0 = SALA_REDGE_um(1)*2d0 + D1 = SALA_REDGE_um(2)*2d0 + ELSE + D0 = SALC_REDGE_um(1)*2d0 + D1 = SALC_REDGE_um(2)*2d0 + ENDIF + + + DO ID = 1, NR + ! Calculate mass of wet aerosol (Dw = wet diameter, D = dry diamter): + ! Overall = dM/dDw = dV/dlnD * Rwet/Rdry * DEN /Rw + IF (DMID(ID) .ge. D0 .and. DMID(ID) .le. D1 ) THEN + DMIDW = DMID(ID) * RWET/A_RADI(K) ! wet radius [um] + SALT_MASS = SALT_V(ID) * RWET/A_RADI(K) * DEN / + & (DMIDW*0.5d0) + VTS_WEIGHT = VTS_WEIGHT + + & SALT_MASS * VTS * (DMIDW/(RWET*1d6*2d0) )**2d0 * + & (2d0 * DR * RWET/A_RADI(K)) + SALT_MASS_TOTAL=SALT_MASS_TOTAL+SALT_MASS * + & (2d0 * DR * RWET/A_RADI(K)) + ENDIF + + ENDDO + + ! Final mass weighted setting velocity: + VTS = VTS_WEIGHT/SALT_MASS_TOTAL + + ! Brownian diffusion constant for particle (m2/s) + DIFF = BOLTZ * TEMP * SLIP + & / (3.d0 * 3.141592d0 * VISC * DIAM) + + ! Schmidt number + SC = AIRVS / DIFF + EB = 1.D0/SC**(gamma(LUC)) + + ! Stokes number + IF ( AA < 0d0 ) then + ST = VTS * USTAR * USTAR / ( AIRVS * G0 ) ! for smooth surface + EIN = 0D0 + ELSE + ST = VTS * USTAR / ( G0 * AA ) ! for vegetated surfaces + EIN = 0.5d0 * ( DIAM / AA )**2 + ENDIF + + ! Use the formulation of Slinn and Slinn (1980) for the impaction over + ! water surfaces (jaegle 5/11/11) + IF (LUC == 14) THEN + EIM = 10.d0**( -3.d0/ ST ) ! for water surfaces + ELSE + EIM = ( ST / ( ALPHA(LUC) + ST ) )**(BETA) + EIM = MIN( EIM, 0.6D0 ) + ENDIF + + IF (LUC == 11 .OR. LUC == 13 .OR. LUC == 14) THEN + R1 = 1.D0 + ELSE + R1 = EXP( -1D0 * SQRT( ST ) ) + ENDIF + + ! surface resistance for particle + ! Use the formulation of Slinn and Slinn (1980) for the impaction over + ! water surfaces (jaegle 5/11/11) + IF (LUC == 14) THEN + RS = 1.D0 / (USTAR**2.d0/ (W10*XCKMAN) * (EB + EIM ) + VTS) + ELSE + RS = 1.D0 / (E0 * USTAR * (EB + EIM + EIN) * R1 ) + ENDIF + + ! Return to calling program + END FUNCTION AERO_SFCRSII + +!------------------------------------------------------------------------------ +! + SUBROUTINE INIT_WEIGHTSS +! +!****************************************************************************** +! Subroutine that calculates the volume size distribution of sea-salt. This only has +! to be done once. We assume that sea-salt is the combination of a coarse mode +! and accumulation model log-normal distribution functions. The resulting +! arrays are: +! DMID = diameter of bin +! SALT_V = dV/dln(D) [in um3] +! +! jaegle 5/11/11 +****************************************************************************** +! + ! References to F90 modules + USE TRACER_MOD, ONLY : SALA_REDGE_um, SALC_REDGE_um + + ! Local variables + INTEGER :: N + + REAL*8 :: SALT_MASS, SALT_MASS_TOTAL, VTS_WEIGHT, DMIDW ! jaegle, for weighting the settling vel. + REAL*8 :: DEDGE + INTEGER :: ID,NR + + ! increment of radius for integration of settling velocity (um) + REAL*8, PARAMETER :: DR = 5.d-2 + + ! parameters for assumed size distribution of acc and coarse mode + ! sea salt aerosols + ! geometric dry mean diameters (microns) + REAL*8, PARAMETER :: RG_A = 0.085d0 + REAL*8, PARAMETER :: RG_C = 0.4d0 + ! sigma of the size distribution + REAL*8, PARAMETER :: SIG_A = 1.5d0 + REAL*8, PARAMETER :: SIG_C = 1.8d0 + REAL*8, PARAMETER :: PI =3.14159D0 + + + ! Number of bins between the lowest bound of of the accumulation mode + ! sea salt and the upper bound of the coarse mode sea salt. + NR =INT((( SALC_REDGE_um(2) - SALA_REDGE_um(1) ) / DR ) + & + 0.5d0 ) + + !================================================================= + ! Define the volume size distribution of sea-salt. This only has + ! to be done once. We assume that sea-salt is the combination of a coarse mode + ! and accumulation model log-normal distribution functions + !================================================================= + + ! Lower edge of 0th bin diameter [um] + DEDGE=SALA_REDGE_um(1) * 2d0 + + ! Loop over diameters + DO ID = 1, NR + + ! Diameter of mid-point in microns + DMID(ID) = DEDGE + ( DR ) + + ! Calculate the dry volume size distribution as the sum of two log-normal + ! size distributions. The parameters for the size distribution are + ! based on Reid et al. and Quinn et al. + ! The scaling factors 13. and 0.8 for acc and coarse mode aerosols are + ! chosen to obtain a realistic distribution + ! SALT_V (D) = dV/dln(D) [um3] + SALT_V(ID) = PI / 6d0* (DMID(ID)**3) * ( + & 13d0*exp(-0.5*( LOG(DMID(ID))-LOG(RG_A*2d0) )**2d0/ + & LOG(SIG_A)**2d0 ) + & /( sqrt(2d0 * PI) * LOG(SIG_A) ) + + & 0.8d0*exp(-0.5*( LOG(DMID(ID))-LOG(RG_C*2d0) )**2d0/ + & LOG(SIG_C)**2d0) + & /( sqrt(2d0 * PI) * LOG(SIG_C) ) ) + ! update the next edge + DEDGE = DEDGE + DR*2d0 + ENDDO + END SUBROUTINE INIT_WEIGHTSS +!------------------------------------------------------------------------------ + + FUNCTION DUST_SFCRSI( K, II, PRESS, TEMP, USTAR ) RESULT( RS ) +! +!****************************************************************************** +! Function DUST_SFCRSI computes the aerodynamic resistance of dust aerosol +! tracers according to Seinfeld et al 96. We do not consider hygroscopic +! growth of the dust aerosol particles. (rjp, tdf, bmy, bec, 4/1/04, 4/15/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) K (INTEGER) : Dry deposition tracer index (range: 1-NUMDEP) +! (2 ) II (INTEGER) : GEOS-CHEM surface type index +! (3 ) PRESS (REAL*8 ) : Pressure [kPa] (where 1 Kpa = 0.1 mb) +! (4 ) TEMP (REAL*8 ) : Temperature [K] +! (5 ) USTAR (REAL*8 ) : Friction Velocity [m/s] +! +! Function Value +! ============================================================================ +! (6 ) Rs (REAL*8 ) : Surface resistance for dust particles [s/m] +! +! NOTES +! (1 ) Updated comments. Also now force double precision w/ "D" exponents. +! (bmy, 4/1/04) +! (2 ) Renamed to DUST_SFCRSII, since this will only be used to compute +! aerodynamic resistance of dust aerosols. (bec, bmy, 4/15/05) +!****************************************************************************** +! + INTEGER, INTENT(IN) :: K ! INDEX OF NUMDEP + INTEGER, INTENT(IN) :: II ! Surface type index of GEOS-CHEM + REAL*8, INTENT(IN) :: PRESS ! Pressure in Kpa 1 mb = 100 pa = 0.1 kPa + REAL*8, INTENT(IN) :: TEMP ! Temperature (K) + REAL*8, INTENT(IN) :: USTAR ! Friction velocity (m/s) + + ! Function value + REAL*8 :: RS ! Surface resistance for particles [s/m] + + ! Local variables + INTEGER :: N + REAL*8, PARAMETER :: C1 = 0.7674d0, C2 = 3.079d0, + & C3 = 2.573d-11, C4 = -1.424d0 + + REAL*8, PARAMETER :: G0 = 9.8d0 + REAL*8, PARAMETER :: BETA = 2.d0 + REAL*8, PARAMETER :: BOLTZ = 1.381D-23 ! Baltzmann constant (J/K) + rEAL*8, PARAMETER :: E0 = 1.d0 + REAL*8 :: AIRVS ! kinematic viscosity of Air (m^2/s) + REAL*8 :: DP ! Diameter of aerosol [um] + REAL*8 :: PDP ! Press * Dp + REAL*8 :: CONST ! Constant for settling velocity calculations + REAL*8 :: SLIP ! Slip correction factor + REAL*8 :: VISC ! Viscosity of air (Pa s) + REAL*8 :: DIFF ! Brownian Diffusion constant for particles (m2/s) + REAL*8 :: SC, ST ! Schmidt and Stokes number (nondim) + + REAL*8 :: DIAM, DEN + REAL*8 :: EB, EIM, EIN, R1, AA, VTS + + !================================================================= + ! Ref. Zhang et al., AE 35(2001) 549-560 and Seinfeld(1986) + ! + ! Model theory + ! Vd = Vs + 1./(Ra+Rs) + ! where Vs is the gravitational settling velocity, + ! Ra is the aerodynamic resistance above the canopy + ! Rs is the surface resistance + ! Here we calculate Rs only.. + ! Rs = 1 / (Eo*Ustar*(Eb+Eim+Ein)*R1) + ! where Eo is an empirical constant ( = 3.) + ! Ustar is the friction velocity + ! Collection efficiency from + ! Eb, [Brownian diffusion] + ! Eim, [Impaction] + ! Ein, [Interception] + ! R1 is the correction factor representing the fraction + ! of particles that stick to the surface. + !================================================================= + ! Eb is a funciont of Schmidt number, Eb = Sc^(-gamma) + ! Sc = v/D, v (the kinematic viscosity of air) + ! D (particle brownian diffusivity) + ! r usually lies between 1/2 and 2/3 + ! Eim is a function of Stokes number, St + ! St = Vs * Ustar / (g0 * A) for vegetated surfaces + ! St = Vs * Ustar * Ustar / v for smooth surface + ! A is the characteristic radius of collectors. + ! + ! 1) Slinn (1982) + ! Eim = 10^(-3/St) for smooth surface + ! Eim = St^2 / ( 1 + St^2 ) for vegetative canopies + ! 2) Peters and Eiden (1992) + ! Eim = ( St / ( alpha + St ) )^(beta) + ! alpha(=0.8) and beta(=2) are constants + ! 3) Giorgi (1986) + ! Eim = St^2 / ( 400 + St^2 ) for smooth surface + ! Eim = ( St / (0.6 + St) )^(3.2) for vegetative surface + ! 4) Davidson et al.(1982) + ! Eim = St^3 / (St^3+0.753*St^2+2.796St-0.202) for grassland + ! 5) Zhang et al.(2001) used 2) method with alpha varying with + ! vegetation type and beta equal to 2 + ! + ! Ein = 0.5 * ( Dp / A )^2 + ! + ! R1 (Particle rebound) = exp(-St^0.5) + !================================================================= + + ! Particle diameter [m] + DIAM = A_RADI(K) * 2.d0 + + ! Particle density [kg/m3] + DEN = A_DEN(K) + + ! Dp [um] = particle diameter + DP = DIAM * 1.d6 + + ! Constant for settling velocity calculation + CONST = DEN * DIAM**2 * G0 / 18.d0 + + !================================================================= + ! # air molecule number density + ! num = P * 1d3 * 6.023d23 / (8.314 * Temp) + ! # gas mean free path + ! lamda = 1.d6/( 1.41421 * num * 3.141592 * (3.7d-10)**2 ) + ! # Slip correction + ! Slip = 1. + 2. * lamda * (1.257 + 0.4 * exp( -1.1 * Dp + ! & / (2. * lamda))) / Dp + !================================================================ + ! Note, Slip correction factor calculations following Seinfeld, + ! pp464 which is thought to be more accurate but more computation + ! required. + !================================================================= + + ! Slip correction factor as function of (P*dp) + PDP = PRESS * DP + SLIP = 1d0 + ( 15.60d0 + 7.0d0 * EXP( -0.059d0 * PDP ) ) / PDP + + !================================================================= + ! Note, Eq) 3.22 pp 50 in Hinds (Aerosol Technology) + ! which produce slip correction factore with small error + ! compared to the above with less computation. + !================================================================= + + ! Viscosity [Pa s] of air as a function of temp (K) + VISC = 1.458d-6 * (TEMP)**(1.5d0) / (TEMP + 110.4d0) + + ! Kinematic viscosity (Dynamic viscosity/Density) + AIRVS= VISC / 1.2928d0 + + ! Settling velocity [m/s] + VTS = CONST * SLIP / VISC + + ! Brownian diffusion constant for particle (m2/s) + DIFF = BOLTZ * TEMP * SLIP + & / (3.d0 * 3.141592d0 * VISC * DIAM) + + ! Schmidt number and Diffusion term + SC = AIRVS / DIFF + EB = SC**(-0.666667d0) + + ! Stokes number and impaction term + ST = VTS * USTAR * USTAR / ( AIRVS * G0 ) + EIM = 10.d0**(-3.d0 / ST) + + ! surface resistance for particle + RS = 1.D0 / ( E0 * USTAR * (EB + EIM) ) + + ! Return to calling program + END FUNCTION DUST_SFCRSI + +!------------------------------------------------------------------------------ + + FUNCTION DUST_SFCRSII( K, II, PRESS, TEMP, USTAR ) RESULT( RS ) +! +!****************************************************************************** +! Function DUST_SFCRSII computes the aerodynamic resistance of dust aerosol +! tracers according to Zhang et al 2001. We do not consider the hygroscopic +! growth of the aerosol particles. (rjp, tdf, bec, bmy, 4/1/04, 4/15/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) K (INTEGER) : Dry deposition tracer index (range: 1-NUMDEP) +! (2 ) II (INTEGER) : GEOS-CHEM surface type index +! (3 ) PRESS (REAL*8 ) : Pressure [kPa] (where 1 Kpa = 0.1 mb) +! (4 ) TEMP (REAL*8 ) : Temperature [K] +! (5 ) USTAR (REAL*8 ) : Friction Velocity [m/s] +! +! Function Value +! ============================================================================ +! (6 ) Rs (REAL*8 ) : Surface resistance for dust particles [s/m] +! +! NOTES +! (1 ) Updated comments. Also now force double precision w/ "D" exponents. +! (bmy, 4/1/04) +! (2 ) Renamed to DUST_SFCRSII, since this will only be used to compute +! aerodynamic resistance of dust aerosols. (bec, bmy, 4/15/05) +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: K ! INDEX OF NUMDEP + INTEGER, INTENT(IN) :: II ! Surface type index of GEOS-CHEM + REAL*8, INTENT(IN) :: PRESS ! Pressure in Kpa 1 mb = 100 pa = 0.1 kPa + REAL*8, INTENT(IN) :: TEMP ! Temperature (K) + REAL*8, INTENT(IN) :: USTAR ! Friction velocity (m/s) + + ! Function value + REAL*8 :: RS ! Surface resistance for particles [s/m] + + ! Local variables + INTEGER :: N + REAL*8, PARAMETER :: C1 = 0.7674d0, C2 = 3.079d0, + & C3 = 2.573d-11, C4 = -1.424d0 + + REAL*8, PARAMETER :: G0 = 9.8D0 + REAL*8, PARAMETER :: BETA = 2.d0 + REAL*8, PARAMETER :: BOLTZ = 1.381d-23 ! Boltzmann constant (J/K) + REAL*8, PARAMETER :: E0 = 3.d0 + REAL*8 :: AIRVS ! kinematic viscosity of Air (m^2/s) + REAL*8 :: DP ! Diameter of aerosol [um] + REAL*8 :: PDP ! Press * Dp + REAL*8 :: CONST ! Constant for settling velocity calculations + REAL*8 :: SLIP ! Slip correction factor + REAL*8 :: VISC ! Viscosity of air (Pa s) + REAL*8 :: DIFF ! Brownian Diffusion constant for particles (m2/s) + REAL*8 :: SC, ST ! Schmidt and Stokes number (nondim) + + REAL*8 :: DIAM, DEN + REAL*8 :: EB, EIM, EIN, R1, AA, VTS + +!======================================================================= +! # LUC [Zhang et al., 2001] GEOS-CHEM LUC (Corr. #) +!----------------------------------------------------------------------- +! 1 - Evergreen needleleaf trees Snow/Ice (12) +! 2 - Evergreen broadleaf trees Deciduous forest ( 4) +! 3 - Deciduous needleleaf trees Coniferous forest ( 1) +! 4 - Deciduous broadleaf trees Agricultural land ( 7) +! 5 - Mixed broadleaf and needleleaf trees Shrub/grassland (10) +! 6 - Grass Amazon forest ( 2) +! 7 - Crops and mixed farming Tundra ( 9) +! 8 - Desert Desert ( 8) +! 9 - Tundra Wetland (11) +! 10 - Shrubs and interrupted woodlands Urban (15) +! 11 - Wet land with plants Water (14) +! 12 - Ice cap and glacier +! 13 - Inland water +! 14 - Ocean +! 15 - Urban +!======================================================================= +! GEOS-CHEM LUC 1, 2, 3, 4, 5, 6, 7 8, 9,10,11 + INTEGER :: LUCINDEX(11) = (/12, 4, 1, 7,10, 2, 9, 8,11,15,14/) + INTEGER :: LUC + +!======================================================================= +! LUC 1, 2, 3, 4, 5, 6, 7, 8, +! alpha 1.0, 0.6, 1.1, 0.8, 0.8, 1.2, 1.2, 50.0, +! gamma 0.56, 0.58, 0.56, 0.56, 0.56, 0.54, 0.54, 0.54 + +! LUC 9, 10, 11, 12, 13, 14, 15 +! alpha 50.0, 1,3, 2.0, 50.0,100.0,100.0, 1.5 +! gamma 0.54, 0.54, 0.54, 0.54, 0.50, 0.50, 0.56 +!======================================================================= + + ! Now force to double precision (bmy, 4/1/04) + REAL*8 :: + & ALPHA(15) = (/ 1.0d0, 0.6d0, 1.1d0, 0.8d0, 0.8d0, + & 1.2d0, 1.2d0, 50.0d0, 50.0d0, 1.3d0, + & 2.0d0, 50.0d0, 100.0d0, 100.0d0, 1.5d0 /) + + ! Now force to double precision (bmy, 4/1/04) + REAL*8 :: + & GAMMA(15) = (/ 0.56d0, 0.58d0, 0.56d0, 0.56d0, 0.56d0, + & 0.54d0, 0.54d0, 0.54d0, 0.54d0, 0.54d0, + & 0.54d0, 0.54d0, 0.50d0, 0.50d0, 0.56d0 /) + +!...A unit is (mm) so multiply by 1.D-3 to (m) +! LUC 1, 2, 3, 4, 5, 6, 7, 8, +! SC1 2.0, 5.0, 2.0, 5.0, 5.0, 2.0, 2.0,-999., +! SC2 2.0, 5.0, 2.0, 5.0, 5.0, 2.0, 2.0,-999., +! A SC3 2.0, 5.0, 5.0, 10.0, 5.0, 5.0, 5.0,-999., +! SC4 2.0, 5.0, 5.0, 10.0, 5.0, 5.0, 5.0,-999., +! SC5 2.0, 5.0, 2.0, 5.0, 5.0, 2.0, 2.0,-999., + +! LUC 9, 10, 11, 12, 13, 14, 15 +! SC1 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! SC2 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! A SC3 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! SC4 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 +! SC5 -999., 10.0, 10.0,-999.,-999.,-999., 10.0 + + REAL*8 :: A(15,5) + + REAL*8 :: Aavg(15) + + ! Now force to double precision (bmy, 4/1/04) + DATA A / 2.0d0, 5.0d0, 2.0d0, 5.0d0, 5.0d0, + & 2.0d0, 2.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 2.0d0, 5.0d0, 5.0d0, + & 2.0d0, 2.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 5.0d0, 10.0d0, 5.0d0, + & 5.0d0, 5.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 5.0d0, 10.0d0, 5.0d0, + & 5.0d0, 5.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0, + & + & 2.0d0, 5.0d0, 2.0d0, 5.0d0, 5.0d0, + & 2.0d0, 2.0d0, -999.d0, -999.d0, 10.0d0, + & 10.0d0, -999.d0, -999.d0, -999.d0, 10.0d0 / + + ! Annual average of A + Aavg(:) = (A(:,1)+A(:,2)+A(:,3)+A(:,4)+A(:,5))/5. + LUC = LUCINDEX(II) + AA = Aavg(LUC) * 1.D-3 + + !================================================================= + !...Ref. Zhang et al., AE 35(2001) 549-560 + !. + !...Model theroy + ! Vd = Vs + 1./(Ra+Rs) + ! where Vs is the gravitational settling velocity, + ! Ra is the aerodynamic resistance above the canopy + ! Rs is the surface resistance + ! Here we calculate Rs only.. + ! Rs = 1 / (Eo*Ustar*(Eb+Eim+Ein)*R1) + ! where Eo is an empirical constant ( = 3.) + ! Ustar is the friction velocity + ! Collection efficiency from + ! Eb, [Brownian diffusion] + ! Eim, [Impaction] + ! Ein, [Interception] + ! R1 is the correction factor representing the fraction + ! of particles that stick to the surface. + !======================================================================= + ! Eb is a funciont of Schmidt number, Eb = Sc^(-gamma) + ! Sc = v/D, v (the kinematic viscosity of air) + ! D (particle brownian diffusivity) + ! r usually lies between 1/2 and 2/3 + ! Eim is a function of Stokes number, St + ! St = Vs * Ustar / (g0 * A) for vegetated surfaces + ! St = Vs * Ustar * Ustar / v for smooth surface + ! A is the characteristic radius of collectors. + ! + ! 1) Slinn (1982) + ! Eim = 10^(-3/St) for smooth surface + ! Eim = St^2 / ( 1 + St^2 ) for vegetative canopies + ! 2) Peters and Eiden (1992) + ! Eim = ( St / ( alpha + St ) )^(beta) + ! alpha(=0.8) and beta(=2) are constants + ! 3) Giorgi (1986) + ! Eim = St^2 / ( 400 + St^2 ) for smooth surface + ! Eim = ( St / (0.6 + St) )^(3.2) for vegetative surface + ! 4) Davidson et al.(1982) + ! Eim = St^3 / (St^3+0.753*St^2+2.796St-0.202) for grassland + ! 5) Zhang et al.(2001) used 2) method with alpha varying with + ! vegetation type and beta equal to 2 + ! + ! Ein = 0.5 * ( Dp / A )^2 + ! + ! R1 (Particle rebound) = exp(-St^0.5) + !================================================================= + + ! Particle diameter [m] + DIAM = A_RADI(K) * 2.d0 + + ! Particle density [kg/m3] + DEN = A_DEN(K) + + ! Dp [um] = particle diameter + DP = DIAM * 1.d6 + + ! Constant for settling velocity calculation + CONST = DEN * DIAM**2 * G0 / 18.d0 + + !================================================================= + ! # air molecule number density + ! num = P * 1d3 * 6.023d23 / (8.314 * Temp) + ! # gas mean free path + ! lamda = 1.d6/( 1.41421 * num * 3.141592 * (3.7d-10)**2 ) + ! # Slip correction + ! Slip = 1. + 2. * lamda * (1.257 + 0.4 * exp( -1.1 * Dp + ! & / (2. * lamda))) / Dp + !================================================================= + ! Note, Slip correction factor calculations following Seinfeld, + ! pp464 which is thought to be more accurate but more computation + ! required. + !================================================================= + + ! Slip correction factor as function of (P*dp) + PDP = PRESS * DP + SLIP = 1d0 + ( 15.60d0 + 7.0d0 * EXP( -0.059d0 * PDP) ) / PDP + + !================================================================= + ! Note, Eq) 3.22 pp 50 in Hinds (Aerosol Technology) + ! which produce slip correction factore with small error + ! compared to the above with less computation. + !================================================================= + + ! Viscosity [Pa s] of air as a function of temp (K) + VISC = 1.458d-6 * (TEMP)**(1.5d0) / (TEMP + 110.4d0) + + ! Kinematic viscosity (Dynamic viscosity/Density) + AIRVS= VISC / 1.2928d0 + + ! Settling velocity [m/s] + VTS = CONST * SLIP / VISC + + ! Brownian diffusion constant for particle (m2/s) + DIFF = BOLTZ * TEMP * SLIP + & / (3.d0 * 3.141592d0 * VISC * DIAM) + + ! Schmidt number + SC = AIRVS / DIFF + EB = 1.D0/SC**(gamma(LUC)) + + ! Stokes number + IF ( AA < 0d0 ) then + ST = VTS * USTAR * USTAR / ( AIRVS * G0 ) ! for smooth surface + EIN = 0D0 + ELSE + ST = VTS * USTAR / ( G0 * AA ) ! for vegetated surfaces + EIN = 0.5d0 * ( DIAM / AA )**2 + ENDIF + + EIM = ( ST / ( ALPHA(LUC) + ST ) )**(BETA) + + EIM = MIN( EIM, 0.6D0 ) + + IF (LUC == 11 .OR. LUC == 13 .OR. LUC == 14) THEN + R1 = 1.D0 + ELSE + R1 = EXP( -1D0 * SQRT( ST ) ) + ENDIF + + ! surface resistance for particle + RS = 1.D0 / (E0 * USTAR * (EB + EIM + EIN) * R1 ) + + ! Return to calling program + END FUNCTION DUST_SFCRSII + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DRYDEP +! +!****************************************************************************** +! Subroutine INIT_DRYDEP initializes certain variables for the GEOS-CHEM +! dry deposition subroutines. (bmy, 11/19/02, 6/23/06) +! +! NOTES: +! (1 ) Added N2O5 as a drydep tracer, w/ the same drydep velocity as +! HNO3. Now initialize PBLFRAC array. (rjp, bmy, 7/21/03) +! (2 ) Added extra carbon & dust aerosol tracers (rjp, tdf, bmy, 4/1/04) +! (3 ) Added seasalt aerosol tracers. Now use A_RADI and A_DEN to store +! radius & density of size-resolved tracers. Also added fancy +! output. (bec, rjp, bmy, 4/26/04) +! (3 ) Now handles extra SOA tracers (rjp, bmy, 7/13/04) +! (4 ) Now references LDRYD from "logical_mod.f" and N_TRACERS, +! SALA_REDGE_um, and SALC_REDGE_um from "tracer_mod.f" (bmy, 7/20/04) +! (5 ) Included Hg2, HgP tracers (eck, bmy, 12/14/04) +! (6 ) Included AS, AHS, LET, NH4aq, SO4aq tracers (cas, bmy, 1/6/05) +! (7 ) Remove reference to PBLFRAC array -- it's obsolete (bmy, 2/22/05) +! (8 ) Included SO4s, NITs tracers (bec, bmy, 4/13/05) +! (9 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (10) Now set Henry's law constant to 1.0d+14 for Hg2. Now use ID_Hg2, +! ID_HgP, and ID_Hg_tot from "tracerid_mod.f". Bug fix: split up +! compound IF statements into separate 2 IF statements for ID_Hg2, +! ID_HgP to avoid seg faults. (eck, cdh, bmy, 4/17/06) +! (11) Now also initialize SOG4, SOA4 drydep species. Bug fix: Remove 2nd +! "IF ( IS_Hg ) THEN" statement. (dkh, bmy, 5/24/06) +! (12) Bug fix: fix TYPO in IF block for IDTSOA4 (dkh, bmy, 6/23/06) +! (13) Included H2/HD tracers for offline H2-HD sim (phs, 9/18/07) +! (14) Add dicarbonyl chemistry species (tmf, ccc, 3/6/09) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LDRYD + USE TRACER_MOD, ONLY : ITS_A_MERCURY_SIM + USE TRACER_MOD, ONLY : N_TRACERS, SALA_REDGE_um, SALC_REDGE_um + USE TRACERID_MOD, ONLY : IDTPB, IDTBE7, IDTNOX + USE TRACERID_MOD, ONLY : IDTOX, IDTPAN, IDTHNO3 + USE TRACERID_MOD, ONLY : IDTH2O2, IDTPMN, IDTPPN + USE TRACERID_MOD, ONLY : IDTISN2, IDTR4N2, IDTCH2O + USE TRACERID_MOD, ONLY : IDTN2O5, IDTSO2, IDTSO4 + USE TRACERID_MOD, ONLY : IDTSO4S, IDTMSA, IDTNH3 + USE TRACERID_MOD, ONLY : IDTNH4, IDTNIT, IDTNITS + USE TRACERID_MOD, ONLY : IDTAS, IDTAHS, IDTLET + USE TRACERID_MOD, ONLY : IDTSO4aq, IDTNH4aq, IDTBCPI + USE TRACERID_MOD, ONLY : IDTOCPI, IDTBCPO, IDTOCPO + USE TRACERID_MOD, ONLY : IDTALPH, IDTLIMO, IDTALCO + USE TRACERID_MOD, ONLY : IDTSOG1, IDTSOG2, IDTSOG3 + USE TRACERID_MOD, ONLY : IDTSOG4, IDTSOA1, IDTSOA2 + USE TRACERID_MOD, ONLY : IDTSOA3, IDTSOA4, IDTDST1 + USE TRACERID_MOD, ONLY : IDTDST2, IDTDST3, IDTDST4 + USE TRACERID_MOD, ONLY : IDTSALA, IDTSALC, Id_Hg2 + USE TRACERID_MOD, ONLY : ID_HgP, ID_Hg_tot + USE TRACERID_MOD, ONLY : IDTH2, IDTHD + USE TRACERID_MOD, ONLY : IDTGLYX, IDTMGLY + USE TRACERID_MOD, ONLY : IDTSOAG, IDTSOAM + USE TRACERID_MOD, ONLY : IDTGLYC + USE TRACERID_MOD, ONLY : IDTAPAN, IDTENPAN, IDTGLPAN + USE TRACERID_MOD, ONLY : IDTGPAN, IDTMPAN, IDTNIPAN + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + LOGICAL :: IS_Hg + INTEGER :: AS, N + + !================================================================= + ! INIT_DRYDEP begins here! + !================================================================= + + ! Is this a mercury simulation? + IS_Hg = ITS_A_MERCURY_SIM() + + ! Zero variables + DRYDNO2 = 0 + DRYDPAN = 0 + DRYDHNO3 = 0 + NUMDEP = 0 + NTRAIND(:) = 0 + NDVZIND(:) = 0 + HSTAR(:) = 0d0 + F0(:) = 0d0 + XMW(:) = 0d0 + A_RADI(:) = 0d0 + A_DEN(:) = 0d0 + AIROSOL(:) = .FALSE. + + !================================================================= + ! First identify tracers that dry deposit and then initialize + ! DEPNAME, NDVZIND, HSTAR, F0, XMW and AIROSOL accordingly + !================================================================= + DO N = 1, N_TRACERS + + !---------------------------------- + ! Regular full-chemistry tracers + !---------------------------------- + + ! 210Pb (aerosol) + IF ( N == IDTPB ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTPB + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = '210Pb' + HSTAR(NUMDEP) = 0.0d+3 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 210d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! 7Be (aerosol) + ELSE IF ( N == IDTBE7 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTBE7 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = '7Be' + HSTAR(NUMDEP) = 0.0d+3 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 7d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! NO2 (as part of NOx) + ELSE IF ( N == IDTNOX ) THEN + NUMDEP = NUMDEP + 1 + DRYDNO2 = NUMDEP + NTRAIND(NUMDEP) = IDTNOX + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'NO2' + HSTAR(NUMDEP) = 0.01d0 + F0(NUMDEP) = 0.1d0 + XMW(NUMDEP) = 46d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! O3 (as part of Ox) + ELSE IF ( N == IDTOX ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTOX + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'O3' + HSTAR(NUMDEP) = 0.01d0 + F0(NUMDEP) = 1.0d0 + XMW(NUMDEP) = 48d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! PAN + ELSE IF ( N == IDTPAN ) THEN + NUMDEP = NUMDEP + 1 + DRYDPAN = NUMDEP + NTRAIND(NUMDEP) = IDTPAN + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'PAN' + HSTAR(NUMDEP) = 3.6d0 + F0(NUMDEP) = 1.0d0 + XMW(NUMDEP) = 121d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! HNO3 + ELSE IF ( N == IDTHNO3 ) THEN + NUMDEP = NUMDEP + 1 + DRYDHNO3 = NUMDEP + NTRAIND(NUMDEP) = IDTHNO3 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'HNO3' + HST AR(NUMDEP) = 1.0d+14 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 63d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! H2O2 + ELSE IF ( N == IDTH2O2 ) THEN + NUMDEP = NUMDEP + 1 + NDVZIND(NUMDEP) = NUMDEP + NTRAIND(NUMDEP) = IDTH2O2 + DEPNAME(NUMDEP) = 'H2O2' + HSTAR(NUMDEP) = 1.0d+5 + F0(NUMDEP) = 1.0d0 + XMW(NUMDEP) = 34d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! PMN (uses same dep vel as PAN) + ELSE IF ( N == IDTPMN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTPMN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'PMN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! PPN (uses same dep vel as PAN) + ELSE IF ( N == IDTPPN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTPPN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'PPN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! ISN2 (uses same dep vel as HNO3) + ELSE IF ( N == IDTISN2 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTISN2 + NDVZIND(NUMDEP) = DRYDHNO3 + DEPNAME(NUMDEP) = 'ISN2' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! R4N2 (uses same dep vel as PAN) + ELSE IF ( N == IDTR4N2 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTR4N2 + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'R4N2' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! CH2O + ELSE IF ( N == IDTCH2O ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTCH2O + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'CH2O' + HSTAR(NUMDEP) = 6.0d+3 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 30d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! Add GLYX and MGLY dry deposition, + ! using same algorithm as CH2O. (tmf, 5/25/06) + ! GLYX + ELSE IF ( N == IDTGLYX ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTGLYX + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'GLYX' + HSTAR(NUMDEP) = 3.6d+5 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 58d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! MGLY + ELSE IF ( N == IDTMGLY ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTMGLY + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'MGLY' + HSTAR(NUMDEP) = 3.7d+3 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 72d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! GLYC + ELSE IF ( N == IDTGLYC ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTGLYC + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'GLYC' + HSTAR(NUMDEP) = 4.1d+4 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 60d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! APAN (uses same dep vel as PAN) + ELSE IF ( N == IDTAPAN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTAPAN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'APAN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! ENPAN (uses same dep vel as PAN) + ELSE IF ( N == IDTENPAN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTENPAN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'ENPAN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! GLPAN (uses same dep vel as PAN) + ELSE IF ( N == IDTGLPAN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTGLPAN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'GLPAN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! GPAN (uses same dep vel as PAN) + ELSE IF ( N == IDTGPAN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTGPAN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'GPAN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! MPAN (uses same dep vel as PAN) + ELSE IF ( N == IDTMPAN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTMPAN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'MPAN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! NIPAN (uses same dep vel as PAN) + ELSE IF ( N == IDTNIPAN ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTNIPAN + NDVZIND(NUMDEP) = DRYDPAN + DEPNAME(NUMDEP) = 'NIPAN' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + ! N2O5 (uses same dep vel as HNO3) + ELSE IF ( N == IDTN2O5 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTN2O5 + NDVZIND(NUMDEP) = DRYDHNO3 + DEPNAME(NUMDEP) = 'N2O5' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 0d0 + AIROSOL(NUMDEP) = .FALSE. + + !---------------------------------- + ! Sulfur & Nitrate aerosol tracers + !---------------------------------- + + ! SO2 + ELSE IF ( N == IDTSO2 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSO2 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SO2' + HSTAR(NUMDEP) = 1.0d+5 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 64d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! SO4 (aerosol) + ELSE IF ( N == IDTSO4 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSO4 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SO4' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 96d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! SO4 in seasalt aerosol (bec, bmy, 4/13/05) + ELSE IF ( N == IDTSO4s ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSO4s + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SO4S' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 36d-3 ! MW of seasalt + A_RADI(NUMDEP) = ( SALC_REDGE_um(1) + + & SALC_REDGE_um(2) ) * 0.5d-6 + A_DEN(NUMDEP) = 2200.d0 + AIROSOL(NUMDEP) = .TRUE. + + ! MSA (aerosol) + ELSE IF ( N == IDTMSA ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTMSA + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'MSA' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 96d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! NH3 + ELSE IF ( N == IDTNH3 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTNH3 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'NH3' + HSTAR(NUMDEP) = 2.0d+4 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 17d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! NH4 (aerosol) + ELSE IF ( N == IDTNH4 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTNH4 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'NH4' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 18d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! NIT (aerosol) + ELSE IF ( N == IDTNIT ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTNIT + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'NIT' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 62d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! NIT in seasalt aerosol (bec, bmy, 4/13/05) + ELSE IF ( N == IDTNITs ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTNITs + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'NITS' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 36d-3 ! MW of seasalt + A_RADI(NUMDEP) = ( SALC_REDGE_um(1) + + & SALC_REDGE_um(2) ) * 0.5d-6 + A_DEN(NUMDEP) = 2200.d0 + AIROSOL(NUMDEP) = .TRUE. + + !---------------------------------- + ! Crystalline & aqueous aerosols + !---------------------------------- + + ! AS (crystalline ammonium sulfate) + ELSE IF ( N == IDTAS ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTAS + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'AS' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 132d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! AHS (crystaline ammonium bisulfite) + ELSE IF ( N == IDTAHS ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTAHS + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'AHS' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 115d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! LET (crystaline LETOVOCITE) + ELSE IF ( N == IDTLET ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTLET + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'LET' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 248.0d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! SO4aq (aqueous sulfate aerosol) + ELSE IF ( N == IDTSO4aq ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSO4aq + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SO4aq' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 96.0d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! NH4aq (aqueous NH4 aerosol) + ELSE IF ( N == IDTNH4aq ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTNH4aq + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'NH4aq' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 18d-3 + AIROSOL(NUMDEP) = .TRUE. + + !---------------------------------- + ! Carbon & SOA aerosol tracers + !---------------------------------- + + ! Hydrophilic BC (aerosol) + ELSE IF ( N == IDTBCPI ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTBCPI + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'BCPI' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 12d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! Hydrophilic OC (aerosol) + ELSE IF ( N == IDTOCPI ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTOCPI + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'OCPI' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 12d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! Hydrophobic BC (aerosol) + ELSE IF ( N == IDTBCPO ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTBCPO + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'BCPO' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 12d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! Hydrophobic OC (aerosol) + ELSE IF ( N == IDTOCPO ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTOCPO + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'OCPO' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 12d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! ALPH (Alpha-pinene) + ELSE IF ( N == IDTALPH ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTALPH + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'ALPH' + HSTAR(NUMDEP) = 0.023d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 136d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! LIMO (Limonene) + ELSE IF ( N == IDTLIMO ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTLIMO + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'LIMO' + HSTAR(NUMDEP) = 0.07d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 136d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! ALCO (Alcohols) + ELSE IF ( N == IDTALCO ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTALCO + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'ALCO' + HSTAR(NUMDEP) = 54.d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 142d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! SOG1 + ELSE IF ( N == IDTSOG1 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOG1 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOG1' + HSTAR(NUMDEP) = 1d5 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 150d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! SOG2 + ELSE IF ( N == IDTSOG2 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOG2 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOG2' + HSTAR(NUMDEP) = 1d5 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 160d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! SOG3 + ELSE IF ( N == IDTSOG3 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOG3 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOG3' + HSTAR(NUMDEP) = 1d5 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 220d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! SOG4 + ELSE IF ( N == IDTSOG4 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOG4 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOG4' + HSTAR(NUMDEP) = 1d5 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 130d-3 + AIROSOL(NUMDEP) = .FALSE. + + ! SOA1 + ELSE IF ( N == IDTSOA1 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOA1 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOA1' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 150d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! SOA2 + ELSE IF ( N == IDTSOA2 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOA2 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOA2' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 160d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! SOA3 + ELSE IF ( N == IDTSOA3 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOA3 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOA3' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 220d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! SOA4 + ELSE IF ( N == IDTSOA4 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOA4 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOA4' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 130d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! SOAG + ELSE IF ( N == IDTSOAG ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOAG + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOAG' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 58d-3 + AIROSOL(NUMDEP) = .TRUE. + + ! SOAM + ELSE IF ( N == IDTSOAM ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSOAM + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SOAM' + HSTAR(NUMDEP) = 0d0 + F0(NUMDEP) = 0d0 + XMW(NUMDEP) = 72d-3 + AIROSOL(NUMDEP) = .TRUE. + + !---------------------------------- + ! Dust aerosol tracers + !---------------------------------- + + ! DUST1 (aerosol) + ELSE IF ( N == IDTDST1 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTDST1 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'DST1' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 29d-3 + A_RADI(NUMDEP) = 0.73d-6 + A_DEN(NUMDEP) = 2500.d0 + AIROSOL(NUMDEP) = .TRUE. + + ! DUST2 (aerosol) + ELSE IF ( N == IDTDST2 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTDST2 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'DST2' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 29d-3 + A_RADI(NUMDEP) = 1.4d-6 + A_DEN(NUMDEP) = 2650.d0 + AIROSOL(NUMDEP) = .TRUE. + + ! DUST3 (aerosol) + ELSE IF ( N == IDTDST3 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTDST3 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'DST3' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 29d-3 + A_RADI(NUMDEP) = 2.4d-6 + A_DEN(NUMDEP) = 2650.d0 + AIROSOL(NUMDEP) = .TRUE. + + ! DUST4 (aerosol) + ELSE IF ( N == IDTDST4 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTDST4 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'DST4' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 29d-3 + A_RADI(NUMDEP) = 4.5d-6 + A_DEN(NUMDEP) = 2650.d0 + AIROSOL(NUMDEP) = .TRUE. + + !---------------------------------- + ! Sea salt aerosol tracers + !---------------------------------- + + ! Accum mode seasalt (aerosol) + ELSE IF ( N == IDTSALA ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSALA + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SALA' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 36d-3 + A_RADI(NUMDEP) = ( SALA_REDGE_um(1) + + & SALA_REDGE_um(2) ) * 0.5d-6 + A_DEN(NUMDEP) = 2200.d0 + AIROSOL(NUMDEP) = .TRUE. + + ! Coarse mode seasalt (aerosol) + ELSE IF ( N == IDTSALC ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTSALC + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'SALC' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 36d-3 + A_RADI(NUMDEP) = ( SALC_REDGE_um(1) + + & SALC_REDGE_um(2) ) * 0.5d-6 + A_DEN(NUMDEP) = 2200.d0 + AIROSOL(NUMDEP) = .TRUE. + !---------------------------------- + ! H2/HD tracers + ! (hup, jaegle, phs, 9/17/08) + !---------------------------------- + ELSE IF ( N == IDTH2 ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTH2 + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'H2' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 0d-3 + AIROSOL(NUMDEP) = .FALSE. + + ELSE IF ( N == IDTHD ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = IDTHD + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'HD' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 0d-3 + AIROSOL(NUMDEP) = .FALSE. + + !---------------------------------- + ! Mercury tracers + !---------------------------------- + + ! Hg2 -- Divalent Mercury + ELSE IF ( IS_Hg ) THEN + IF ( N == ID_Hg2(ID_Hg_tot) ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = ID_Hg2(ID_Hg_tot) + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'Hg2' + HSTAR(NUMDEP) = 1.0d+14 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 201d-3 + AIROSOL(NUMDEP) = .FALSE. + ENDIF + + IF ( N == ID_HgP(ID_Hg_tot) ) THEN + NUMDEP = NUMDEP + 1 + NTRAIND(NUMDEP) = ID_HgP(ID_Hg_tot) + NDVZIND(NUMDEP) = NUMDEP + DEPNAME(NUMDEP) = 'HgP' + HSTAR(NUMDEP) = 0.0d0 + F0(NUMDEP) = 0.0d0 + XMW(NUMDEP) = 201d-3 + AIROSOL(NUMDEP) = .TRUE. + ENDIF + ENDIF + ENDDO + + !================================================================= + ! Allocate arrays + !================================================================= + ALLOCATE( DEPSAV( IIPAR, JJPAR, NUMDEP ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'DEPSAV' ) + DEPSAV = 0d0 + + ALLOCATE( SALT_V( NR_MAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SALT_V' ) + SALT_V = 0d0 + + ALLOCATE( DMID( NR_MAX ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'DMID' ) + DMID = 0d0 + + ALLOCATE( SHIPO3DEP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SHIPO3DEP' ) + SHIPO3DEP = 0d0 + + !================================================================= + ! Echo information to stdout + !================================================================= + WRITE( 6, '(/,a)' ) 'INIT_DRYDEP: List of dry deposition species:' + WRITE( 6, '(/,a)' ) + & ' # Name Tracer DEPVEL Henry''s React. Molec. Aerosol?' + WRITE( 6, '(a)' ) + & ' Number Index Law Const Factor Weight (T or F)' + WRITE( 6, '(a)' ) REPEAT( '-', 65 ) + + DO N = 1, NUMDEP + WRITE( 6, 100 ) N, TRIM( DEPNAME(N) ), NTRAIND(N), NDVZIND(N), + & HSTAR(N), F0(N), XMW(N), AIROSOL(N) + ENDDO + 100 FORMAT( i3, 3x, a4, 2(3x,i3), 4x, es8.1, 2(3x,f6.3), 3x, L3 ) + + ! Return to calling program + END SUBROUTINE INIT_DRYDEP + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DRYDEP +! +!****************************************************************************** +! Subroutine CLEANUP_DRYDEP deallocates all module arrays. +! (bmy, 2/27/03, 2/22/05) +! +! NOTES: +! (1 ) Remove reference to PBLFRAC array; it's obsolete (bmy, 2/22/05) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DRYDEP begins here! + !================================================================= + IF ( ALLOCATED( DEPSAV ) ) DEALLOCATE( DEPSAV ) + IF ( ALLOCATED( SALT_V ) ) DEALLOCATE( SALT_V ) + IF ( ALLOCATED( DMID ) ) DEALLOCATE( DMID ) + IF ( ALLOCATED( SHIPO3DEP) ) DEALLOCATE( SHIPO3DEP) + + ! Return to calling program + END SUBROUTINE CLEANUP_DRYDEP + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE DRYDEP_MOD + + diff --git a/code/dust_dead_mod.f b/code/dust_dead_mod.f new file mode 100644 index 0000000..97311a4 --- /dev/null +++ b/code/dust_dead_mod.f @@ -0,0 +1,5154 @@ +! $Id: dust_dead_mod.f,v 1.2 2012/03/01 22:00:26 daven Exp $ + MODULE DUST_DEAD_MOD +! +!****************************************************************************** +! Module DUST_DEAD_MOD contains routines and variables from Charlie Zender's +! DEAD dust mobilization model. Most routines are from Charlie Zender, but +! have been modified and/or cleaned up for inclusion into GEOS-Chem. +! (tdf, rjp, bmy, 4/6/04, 8/13/10) +! +! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +! %%% NOTE: The current [dust] code was validated at 2 x 2.5 resolution. %%% +! %%% We have found that running at 4x5 we get much lower (~50%) dust %%% +! %%% emissions than at 2x2.5. Recommend we either find a way to scale %%% +! %%% the U* computed in the dust module, or run a 1x1 and store the the %%% +! %%% dust emissions, with which to drive lower resolution runs. %%% +! %%% -- Duncan Fairlie, 1/25/07 %%% +! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +! %%% NOTE: [We'll] implement the [dust] code in the standard [GEOS-Chem] %%% +! %%% model and put a warning about expected low bias when the simulation %%% +! %%% is run at 4x5. Whoever is interested in running dust at 4x5 in the %%% +! %%% future can deal with making the fix. %%% +! %%% -- Daniel Jacob, 1/25/07 %%% +! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +! +! Module Variables: +! ============================================================================ +! (1 ) GAS_CNST_UNV (REAL*8 ) : Universal gas constant [J/mol/K ] +! (2 ) MMW_H2O (REAL*8 ) : Mean mol wt (MMW) of water [kg/mol ] +! (3 ) MMW_DRY_AIR (REAL*8 ) : Mean mol wt (MMW) of dry air [kg/mol ] +! (4 ) CST_VON_KRM (REAL*8 ) : Von Karman constant [fraction] +! (5 ) GRV_SFC (REAL*8 ) : Acceleration due to gravity [m/s2 ] +! (6 ) GAS_CST_DRY_AIR (REAL*8 ) : Gas constant of dry air [J/kg/K ] +! (7 ) RDS_EARTH (REAL*8 ) : Equivalent earth radius [m ] +! (8 ) GAS_CST_H2O (REAL*8 ) : Gas constant of H2O [J/kg/K ] +! (9 ) SPC_HEAT_DRY_AIR (REAL*8 ) : Specific heat of dry air, Cp [J/kg/K ] +! (10) TPT_FRZ_PNT (REAL*8) : Freezing point of water [K ] +! (11) GRV_SFC_RCP (REAL*8) : 1/GRV_SFC [s2/m ] +! (12) CST_VON_KRM_RCP (REAL*8) : 1/CST_VON_KRM [fraction] +! (13) EPS_H2O (REAL*8) : MMW(H2O) / MMW(dry air) [fraction] +! (14) EPS_H2O_RCP_M1 (REAL*8) : Constant for virtual temp. [fraction] +! (15) KAPPA_DRY_AIR (REAL*8) : R/Cp (const. for pot. temp) [fraction] +! (16) DST_SRC_NBR (INTEGER) : # of size distributions in source soil +! (17) MVT (INTEGER) : +! (18) ERD_FCT_GEO (REAL*8 ) : Geomorphic erodibility +! (19) ERD_FCT_HYDRO (REAL*8 ) : Hydrologic erodibility +! (20) ERD_FCT_TOPO (REAL*8 ) : Topographic erodibility (Ginoux) +! (21) ERD_FCT_UNITY (REAL*8 ) : Uniform erodibility +! (22) MBL_BSN_FCT (REAL*8 ) : Overall erodibility factor +! (23) LND_FRC_DRY (REAL*8 ) : Dry Land Fraction [fraction] +! (24) MSS_FRC_CACO3 (REAL*8 ) : Mass Fraction of soil CaCO3 [fraction] +! (25) MSS_FRC_CLY (REAL*8 ) : Mass fraction of clay [fraction] +! (26) MSS_FRC_SND (REAL*8 ) : Mass fraction of sand [fraction] +! (27) SFC_TYP (INTEGER) : Surface type index (0..28) [unitless] +! (28) FLX_LW_DWN_SFC (REAL*8 ) : Downward Longwave flux at sfc [W/m2 ] +! (29) FLX_SW_ABS_SFC (REAL*8 ) : Solar flux absorbed by ground [W/m2 ] +! (30) TPT_GND (REAL*8 ) : Ground temperature [K ] +! (31) TPT_SOI (REAL*8 ) : Soil temperature [K ] +! (32) VWC_SFC (REAL*8 ) : Volumetric water content [m3/m3 ] +! (33) VAI_DST (REAL*8 ) : Vegetation area index [m2/m2 ] +! (34) VAI_DST_BND (REAL*8 ) : Vegetation area index-boundary [m2/m2 ] +! (35) SRC_STR (REAL*8 ) : Source strength [fraction] +! (36) SRC_STR_BND (REAL*8 ) : Source strength-boundary data [fraction] +! (37) PLN_TYP (INTEGER) : LSM plant type index (1-14) [number ] +! (38) PLN_FRC (REAL*8 ) : Plant type weights (sums to 1) [unitless] +! (39) TAI (REAL*8 ) : monthly LAI + Stem Area Index [fraction] +! (40) DMT_VWR (REAL*8 ) : Mass weighted diameter resolved[m ] +! (41) DNS_AER (REAL*8 ) : Particle density [kg/m3 ] +! (42) OVR_SRC_SNK_FRC (REAL*8 ) : Mass Overlap fraction (Mij p5) [fraction] +! (43) OVR_SRC_SNK_MSS (REAL*8 ) : Mass fraction [fraction] +! (44) OROGRAPHY (INTEGER) : 0=ocean; 1=land; 2=ice [unitless] +! (45) DMT_MIN (REAL*8 ) : Bin diameter -- minimums [m ] +! (46) DMT_MAX (REAL*8 ) : Bin diameter -- maximums [m ] +! (47) DMT_VMA_SRC (REAL*8 ) : D'Almeida's (1987) bkgr modes [m ] +! (48) GSD_ANL_SRC (REAL*8 ) : Geometric std deviation [fraction] +! (49) MSS_FRC_SRC (REAL*8 ) : Mass fraction BSM96 p.73 [fraction] +! (50) SRCE_FUNC (REAL*8 ) : GOCART source function [fraction] +! +! Module Routines: +! ============================================================================ +! (1 ) DST_MBL : Driver routine for dust mobilization +! (2 ) SOI_TXT_GET : Gets latitude slice of soil texture +! (3 ) SFC_TYP_GET : Gets latitude slice of surface type +! (4 ) TPT_GND_SOI_GET : Gets latitude slice of soil & gnd tmp +! (5 ) VWC_SFC_GET : Gets latitude slice of VWC +! (6 ) DSVPDT_H2O_LQD_PRK78_FST_SCL : Gets deriv of vapor pressure over water +! (7 ) DSVPDT_H2O_ICE_PRK78_FST_SCL : Gets deriv of vapor pressure over ice +! (8 ) SVP_H2O_LQD_PRK78_FST_SCL : Gets saturation vapor press. over water +! (9 ) SVP_H2O_ICE_PRK78_FST_SCL : Gets saturation vapor press. over ice +! (10) TPT_BND_CLS_GET : Gets temperature in C (-50 < T < 50 C) +! (11) GET_ORO : Gets 2-D orography array +! (12) HYD_PRP_GET : Gets hydrologic properties of soil +! (13) CND_TRM_SOI_GET : Gets thermal properties of soil +! (14) TRN_FSH_VPR_SOI_ATM_GET : Gets factor of transfer from soil->atm +! (15) BLM_MBL : Gets boundary-layer exchange properties +! (16) ORO_IS_OCN : Returns TRUE for ocean grid boxes +! (17) ORO_IS_LND : Returns TRUE for land grid boxes +! (18) ORO_IS_ICE : Returns TRUE for ice grid boxes +! (19) MNO_STB_CRC_HEAT_UNS_GET : Returns M-O stab corr factor for heat +! (20) MNO_STB_CRC_MMN_UNS_GET : Returns M-0 stab corr factor for mom. +! (21) XCH_CFF_MMN_OCN_NTR_GET : Returns neutral 10m drag coefficient +! (22) RGH_MMN_GET : Sets the roughness length +! (23) SNW_FRC_GET : Converts LW snow depth to snow cover +! (24) WND_RFR_GET : Interpolates wind speed to ref. hght +! (25) WND_FRC_THR_SLT_GET : Gets dry friction vel. for saltation +! (26) WND_RFR_THR_SLT_GET : Gets threshold U-wind for saltation +! (27) VWC2GWC : Converts VWC to GWC +! (28) FRC_THR_NCR_WTR_GET : Gets factor: soil moist. incr. USTAR +! (29) FRC_THR_NCR_DRG_GET : Gets factor: roughness incr. USTAR +! (30) WND_FRC_SLT_GET : Gets saltating fricton velocity +! (31) FLX_MSS_CACO3_MSK : Mask dust mass by CaCO3 mass fraction +! (32) FLX_MSS_HRZ_SLT_TTL_WHI79_GET : Gets vert int. streamwise mass flux +! (33) FLX_MSS_VRT_DST_TTL_MAB95_GET : Gets total vertical mass flux of dust +! (34) DST_PSD_MSS : Gets OVR_SRC_SNK_MSS mass overlap +! (35) FLX_MSS_VRT_DST_PRT : Partitions vert mass flux into bins +! (36) TM_2_IDX_WGT : Now deleted +! (37) LND_FRC_MBL_GET : Gets fraction of grid box for mobiliz. +! (38) DST_ADD_LON : Sums property w/in a dust bin +! (39) DST_TVBDS_GET : Gets a latitude slice of VAI data +! (40) OVR_SRC_SNK_FRC_GET : Gets overlap factors betwn src & sink +! (41) ERF : Driver for CALERF +! (42) CALERF : Platform independent erf(x) +! (43) PLN_TYP_GET : Returns info from land sfc model +! (44) GET_TIME_INVARIANT_DATA : Reads time-invariant fields from disk +! (45) GET_MONTHLY_DATA : Reads monthly fields from disk +! (46) INIT_DUST_DEAD : Allocates & zeroes module arrays +! (47) CLEANUP_DUST_DEAD : Deallocates +! +! GEOS-CHEM modules referenced by dust_dead_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module containing routines for binary punch file I/O +! (2 ) dao_mod.f : Module containing arrays for GMAO met fields +! (3 ) directory_mod.f : Module containing GEOS-CHEM data & met field dirs +! (4 ) error_mod.f : Module containing I/O error and NaN check routines +! (5 ) grid_mod.f : Module containing horizontal grid information +! (6 ) time_mod.f : Module containing routines for computing time & date +! (7 ) transfer_mod.f : Module containing routines to cast & resize arrays +! +! NOTES: +! (1 ) Added parallel DO loop in GET_ORO (bmy, 4/14/04) +! (2 ) Now references "directory_mod.f" (bmy, 7/20/04) +! (3 ) Fixed typo in ORO_IS_LND for PGI compiler (bmy, 3/1/05) +! (4 ) Modified for GEOS-5 and GCAP met fields (swu, bmy, 8/16/05) +! (5 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (6 ) Now uses GOCART source function (tdf, bmy, 1/25/07) +! (7 ) Modifications for 0.5 x 0.667 grid (yxw, dan, bmy, 11/6/08) +! (8 ) Updates for nested grids (amv, bmy, 12/18/09) +!****************************************************************************** +! + IMPLICIT NONE +# include "define.h" + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "dust_dead_mod.f" + !================================================================= + + ! Make everything PRIVATE.... + PRIVATE + + ! Except these routines + PUBLIC :: DST_MBL + PUBLIC :: CLEANUP_DUST_DEAD + PUBLIC :: GET_ORO + PUBLIC :: GET_TIME_INVARIANT_DATA + PUBLIC :: GET_MONTHLY_DATA + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Fundamental physical constants + REAL*8, PARAMETER :: GAS_CST_UNV = 8.31441d0 + REAL*8, PARAMETER :: MMW_H2O = 1.8015259d-02 + REAL*8, PARAMETER :: MMW_DRY_AIR = 28.9644d-3 + REAL*8, PARAMETER :: CST_VON_KRM = 0.4d0 + REAL*8, PARAMETER :: GRV_SFC = 9.80616d0 + REAL*8, PARAMETER :: GAS_CST_DRY_AIR = 287.05d0 + REAL*8, PARAMETER :: RDS_EARTH = 6.37122d+6 + REAL*8, PARAMETER :: GAS_CST_H2O = 461.65D0 + REAL*8, PARAMETER :: SPC_HEAT_DRY_AIR = 1005.0d0 + REAL*8, PARAMETER :: TPT_FRZ_PNT = 273.15d0 + + ! Derived quantities + REAL*8, PARAMETER :: GRV_SFC_RCP = 1.0d0 / GRV_SFC + REAL*8, PARAMETER :: CST_VON_KRM_RCP = 1.0d0 / CST_VON_KRM + REAL*8, PARAMETER :: EPS_H2O = MMW_H2O / MMW_DRY_AIR + REAL*8, PARAMETER :: EPS_H2O_RCP_M1 = -1.0d0 + MMW_DRY_AIR + & / MMW_H2O + REAL*8, PARAMETER :: KAPPA_DRY_AIR = GAS_CST_DRY_AIR + & / SPC_HEAT_DRY_AIR + + ! Fixed-size grid information + INTEGER, PARAMETER :: DST_SRC_NBR = 3 + INTEGER, PARAMETER :: MVT = 14 + + ! Time-invariant fields + REAL*8, ALLOCATABLE :: ERD_FCT_GEO(:,:) + REAL*8, ALLOCATABLE :: ERD_FCT_HYDRO(:,:) + REAL*8, ALLOCATABLE :: ERD_FCT_TOPO(:,:) + REAL*8, ALLOCATABLE :: ERD_FCT_UNITY(:,:) + REAL*8, ALLOCATABLE :: MBL_BSN_FCT(:,:) + + ! GOCART source function (tdf, bmy, 1/25/07) + REAL*8, ALLOCATABLE :: SRCE_FUNC(:,:) + + ! Land surface that is not lake or wetland (by area) + REAL*8, ALLOCATABLE :: LND_FRC_DRY(:,:) + REAL*8, ALLOCATABLE :: MSS_FRC_CACO3(:,:) + REAL*8, ALLOCATABLE :: MSS_FRC_CLY(:,:) + REAL*8, ALLOCATABLE :: MSS_FRC_SND(:,:) + INTEGER, ALLOCATABLE :: SFC_TYP(:,:) + + ! Time-varying surface info from CTM + REAL*8, ALLOCATABLE :: FLX_LW_DWN_SFC(:,:) + REAL*8, ALLOCATABLE :: FLX_SW_ABS_SFC(:,:) + REAL*8, ALLOCATABLE :: TPT_GND(:,:) + REAL*8, ALLOCATABLE :: TPT_SOI(:,:) + REAL*8, ALLOCATABLE :: VWC_SFC(:,:) + + ! Variables initialized in dst_tvbds_ntp() and dst_tvbds_ini() + REAL*8, ALLOCATABLE :: VAI_DST(:,:) + REAL*8, ALLOCATABLE :: SRC_STR(:,:) + + ! LSM plant type, 28 land surface types plus 0 for ocean + ! Also account for 3 different land types in each grid box + INTEGER, ALLOCATABLE :: PLN_TYP(:,:) + REAL*8, ALLOCATABLE :: PLN_FRC(:,:) + REAL*8, ALLOCATABLE :: TAI(:,:) + + ! Other fields + REAL*8, ALLOCATABLE :: DMT_VWR(:) + REAL*8, ALLOCATABLE :: DNS_AER(:) + REAL*8, ALLOCATABLE :: OVR_SRC_SNK_FRC(:,:) + REAL*8, ALLOCATABLE :: OVR_SRC_SNK_MSS(:,:) + INTEGER, ALLOCATABLE :: OROGRAPHY(:,:) + REAL*8, ALLOCATABLE :: DMT_MIN(:) + REAL*8, ALLOCATABLE :: DMT_MAX(:) + REAL*8, ALLOCATABLE :: DMT_VMA_SRC(:) + REAL*8, ALLOCATABLE :: GSD_ANL_SRC(:) + REAL*8, ALLOCATABLE :: MSS_FRC_SRC(:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DST_MBL( DOY, HGT_MDP, LAT_IDX, + & LAT_RDN, ORO, PRS_DLT, + & PRS_MDP, Q_H2O_VPR, DSRC, + & SNW_HGT_LQD, TM_ADJ, TPT_MDP, + & TPT_PTN_MDP, WND_MRD_MDP, WND_ZNL_MDP, + & FIRST, NSTEP ) +! +!****************************************************************************** +! Subroutine DST_MBL is the driver for aerosol mobilization (DEAD model). +! It is designed to require only single layer surface fields, allowing for +! easier implementation. DST_MBL is called once per latitude. Modified +! for GEOS-CHEM by Duncan Fairlie and Bob Yantosca. +! (tdf, bmy, 1/25/07, 12/18/09) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DOY (REAL*8 ) : Day of year [1.0..366.0) [unitless] +! (2 ) HGT_MDP (REAL*8 ) : Midpoint height above surface [m ] +! (3 ) LAT_IDX (INTEGER) : Model latitude index [unitless] +! (4 ) LAT_RDN (REAL*8 ) : Model latitude [radians ] +! (5 ) ORO (REAL*8 ) : Orography [fraction] +! (6 ) PRS_DLT (REAL*8 ) : Pressure thickness of grid box [Pa ] +! (7 ) PRS_MDP (REAL*8 ) : Pressure @ midpoint of grid box [Pa ] +! (8 ) Q_H2O_VPR, (REAL*8 ) : Water vapor mixing ratio [kg/kg ] +! (9 ) SNW_HGT_LQD (REAL*8 ) : Equivalent liquid water snow depth [m ] +! (10) TM_ADJ, (REAL*8 ) : Adjustment timestep [s ] +! (11) TPT_MDP, (REAL*8 ) : Temperature [K ] +! (12) TPT_PTN_MDP (REAL*8 ) : Midlayer local potential temp. [K ] +! (13) WND_MRD_MDP (REAL*8 ) : Meridional wind component (V-wind) [m/s ] +! (14) WND_ZNL_MDP (REAL*8 ) : Zonal wind component (U-wind) [m/s ] +! (15) FIRST, (LOGICAL) : Logical used ot open output dataset [unitless] +! (16) NSTEP (INTEGER) : Iteration counter [unitless] +! +! Arguments as Output: +! ============================================================================ +! (10) DSRC ! O [kg kg-1] Dust mixing ratio increment +! +! NOTES: +! (1 ) Cleaned up and added comments. Also force double precision with +! "D" exponents. (bmy, 3/30/04) +! (2 ) Now get GOCART source function. (tdf, bmy, 1/25/07) +! (3 ) Tune nested-domain emissions dust to the same as 2x2.5 simulation +! Also tune GEOS-3 1x1 N. America nested-grid dust emissions to +! the 4x5 totals from the GEOS-5 4x5 v8-01-01-Run0 benchmark. +! (yxw, bmy, dan, 11/6/08) +! (4 ) New scale parameter for 2x2.5 GEOS-5 (tdf, jaf, phs, 10/30/09) +! (5 ) Defined FLX_MSS_FDG_FCT for GEOS_4 2x2.5, GEOS_5 2x2.5, NESTED_NA and +! NESTED_EU. Redefined FLX_MSS_FDG_FCT for NESTED_CH, based upon above +! changes. (amv, bmy, 12/18/09) +! (6 ) For now treat MERRA like GEOS-5 (bmy, 8/13/10) +! 29 Oct 2010 - T. D. Fairlie, R. Yantosca - Retune dust for MERRA 4x5 +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : USTAR, Z0 + USE GRID_MOD, ONLY : GET_AREA_M2 + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: LAT_IDX + REAL*8, INTENT(IN) :: DOY + REAL*8, INTENT(IN) :: HGT_MDP(IIPAR) + REAL*8, INTENT(IN) :: LAT_RDN + REAL*8, INTENT(IN) :: ORO(IIPAR) + REAL*8, INTENT(IN) :: PRS_DLT(IIPAR) + REAL*8, INTENT(IN) :: PRS_MDP(IIPAR) + REAL*8, INTENT(IN) :: Q_H2O_VPR(IIPAR) + REAL*8, INTENT(IN) :: SNW_HGT_LQD(IIPAR) + REAL*8, INTENT(IN) :: TM_ADJ + REAL*8, INTENT(IN) :: TPT_MDP(IIPAR) + REAL*8, INTENT(IN) :: TPT_PTN_MDP(IIPAR) + REAL*8, INTENT(IN) :: WND_MRD_MDP(IIPAR) + REAL*8, INTENT(IN) :: WND_ZNL_MDP(IIPAR) + INTEGER, INTENT(IN) :: NSTEP + LOGICAL, INTENT(IN) :: FIRST + REAL*8, INTENT(INOUT) :: DSRC(IIPAR,NDSTBIN) + + !-------------- + ! Parameters + !-------------- + + ! Global mass flux tuning factor (a posteriori) [frc] +#if defined( GEOS_5 ) && defined( GRID05x0666 ) + +#if defined(NESTED_CH) + ! retuned based upon updated GEOS-4 tuning (amv, Nov 9, 2009) + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 3.23d-4 +#elif defined(NESTED_EU) + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 4.54d-4 +#elif defined(NESTED_NA) + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 2.16d-4 +#endif + + +#elif defined( GEOS_4 ) && defined( GRID2x25 ) + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 3.5d-4 + + +#elif defined( GEOS_5 ) && defined( GRID2x25 ) + + ! retuned based upon updated GEOS-4 tuning (amv, Nov 9, 2009) + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 4.9d-4 + +#elif defined( MERRA ) && defined( GRID2x25 ) + + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + !%%% NOTE: RETUNING FOR MERRA 1x25 IS NEEDED ONCE MET IS AVAILABLE %%% + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 4.9d-4 + +#elif defined( MERRA ) && defined( GRID4x5 ) + + !---------------------------------------------------------------- + ! Based on results from MERRA 4x5 for years 2004-2005: + ! + ! (GEOS-5 - MERRA)/GEOS-5 * 100 is 26.9% in each size bin. + ! + ! We need to scale to the parameter FLX_MSS_FDG_FCT to make the + ! dust emissions consistent. Consequently, to bring MERRA 4x5 + ! dust emissions up to GEOS-5 levels, we need to DIVIDE the + ! FLX_MSS_FDG_FCT used for GEOS-5 by (1. - 0.269) = 0.731. + ! + ! -- Duncan Fairlie (t.d.fairlie@nasa.gov), 29 Oct 2010 + !---------------------------------------------------------------- + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 7.0d-4 / 0.731d0 + +!! (lzh, 11/01/2014) add geos_fp +#elif defined( GEOS_FP ) && defined( GRID2x25 ) + + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + !%%% NOTE: RETUNING FOR MERRA 1x25 IS NEEDED ONCE MET IS AVAILABLE %%% + !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 4.9d-4 + +#elif defined( GEOS_FP ) && defined( GRID4x5 ) + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 7.0d-4 / 0.731d0 + +#elif defined( GEOS_3 ) && defined( GRID1x1 ) && defined( NESTED_NA ) + + ! For the GEOS-3 1x1 N. America Nested grid (as used by the MIT/FAA-ULS + ! project), we'll tune the global dust emissions to the same totals as + ! the GEOS-5 4x5 1-year benchmark v8-01-01-Run0. (bmy, 11/10/08) + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 7.0d-4 / 9.57d0 + +#else + + ! Default value + REAL*8, PARAMETER :: FLX_MSS_FDG_FCT = 7.0d-4 + +#endif + + ! Reference height for mobilization processes [m] + REAL*8, PARAMETER :: HGT_RFR = 10.0d0 + + ! Zero plane displacement for erodible surfaces [m] + REAL*8, PARAMETER :: HGT_ZPD_MBL = 0.0d0 + + ! Set roughness length momentum for erodible surfaces, S&P, p. 858. [m] + REAL*8, PARAMETER :: RGH_MMN_MBL = 1.0d-3 + + ! rgh_mmn_smt set to 33.3e-6 um, MaB95 p. 16426 recommend 10.0e-6 + ! Smooth roughness length MaB95 p. 16426, MaB97 p. 4392, GMB98 p. 6207 + ! [m] Z0,m,s + REAL*8, PARAMETER :: RGH_MMN_SMT = 33.3d-6 + + ! Minimum windspeed used for mobilization [m/s] + REAL*8, PARAMETER :: WND_MIN_MBL = 1.0d0 + + !-------------- + ! Local Output + !-------------- + REAL*8 DST_SLT_FLX_RAT_TTL(IIPAR) ! [m-1] Ratio of vertical dust flux to + ! streamwise mass flux + REAL*8 FLX_MSS_HRZ_SLT_TTL(IIPAR) ! [kg/m/s] Vertically integrated + ! streamwise mass flux + REAL*8 FLX_MSS_VRT_DST_TTL(IIPAR) ! [kg/m2/s] Total vertical mass + ! flux of dust + REAL*8 FRC_THR_NCR_DRG(IIPAR) ! [frc] Threshold friction velocity + ! increase from roughness + REAL*8 FRC_THR_NCR_WTR(IIPAR) ! [frc] Threshold friction velocity + ! increase from moisture + REAL*8 FLX_MSS_VRT_DST(IIPAR,NDSTBIN) ! [kg/m2/s] Vertical mass flux + ! of dust + REAL*8 HGT_ZPD(IIPAR) ! [m] Zero plane displacement + REAL*8 LND_FRC_MBL_SLICE(IIPAR) ! [frc] Bare ground fraction + REAL*8 MNO_LNG(IIPAR) ! [m] Monin-Obukhov length + REAL*8 WND_FRC(IIPAR) ! [m/s] Friction velocity + REAL*8 WND_FRC_GEOS(IIPAR) ! [m/s] Friction velocity + REAL*8 Z0_GEOS(IIPAR) ! [m] roughness height + REAL*8 SNW_FRC(IIPAR) ! [frc] Fraction of surface covered + ! by snow + REAL*8 TRN_FSH_VPR_SOI_ATM(IIPAR) ! [frc] Transfer efficiency of vapor + ! from soil to atmosphere + REAL*8 wnd_frc_slt(IIPAR) ! [m/s] Saltating friction velocity + REAL*8 WND_FRC_THR_SLT(IIPAR) ! [m/s] Threshold friction velocity + ! for saltation + REAL*8 WND_MDP(IIPAR) ! [m/s] Surface layer mean wind speed + REAL*8 WND_RFR(IIPAR) ! [m/s] Wind speed at reference height + REAL*8 WND_RFR_THR_SLT(IIPAR) ! [m/s] Threshold 10 m wind speed for + ! saltation + + LOGICAL FLG_CACO3 ! [FLG] Activate CaCO3 tracer + LOGICAL FLG_MBL_SLICE(IIPAR) ! [flg] Mobilization candidates + CHARACTER(80) FL_OUT ! [sng] Name of netCDF output file + INTEGER I ! [idx] Counting index + INTEGER IJLOOP ! [idx] counting index + INTEGER M ! [idx] Counting index + INTEGER MBL_NBR ! [nbr] Number of mobilization candidates + INTEGER SFC_TYP_SLICE(IIPAR) ! [idx] LSM surface type lat slice (0..28) + REAL*8 CND_TRM_SOI(IIPAR) ! [W/m/K] Soil thermal conductivity + REAL*8 DNS_MDP(IIPAR) ! [kg/m3] Midlayer density + REAL*8 FLX_LW_DWN_SFC_SLICE(IIPAR) ! [W/m2] Longwave downwelling flux + ! at surface + REAL*8 FLX_SW_ABS_SFC_SLICE(IIPAR) ! [W/m2] Solar flux absorbed by ground + + REAL*8 LND_FRC_DRY_SLICE(IIPAR) ! [frc] Dry land fraction + REAL*8 MBL_BSN_FCT_SLICE(IIPAR) ! [frc] Erodibility factor + REAL*8 MSS_FRC_CACO3_SLICE(IIPAR) ! [frc] Mass fraction of CaCO3 + REAL*8 MSS_FRC_CLY_SLICE(IIPAR) ! [frc] Mass fraction of clay + REAL*8 MSS_FRC_SND_SLICE(IIPAR) ! [frc] Mass fraction of sand + + ! GOCART source function (tdf, bmy, 1/25/07) + REAL*8 SRCE_FUNC_SLICE(IIPAR) ! GOCART source function + + REAL*8 LVL_DLT(IIPAR) ! [m] Soil layer thickness + REAL*8 MPL_AIR(IIPAR) ! [kg/m2] Air mass path in layer + + REAL*8 TM_DLT ! [s] Mobilization timestep + REAL*8 TPT_GND_SLICE(IIPAR) ! [K] Ground temperature + REAL*8 TPT_SOI_SLICE(IIPAR) ! [K] Soil temperature + REAL*8 TPT_SOI_FRZ ! [K] Temperature of frozen soil + REAL*8 TPT_VRT_MDP ! [K] Midlayer virtual temperature + REAL*8 VAI_DST_SLICE(IIPAR) ! [m2/m2] Vegetation area index, + ! one-sided + REAL*8 VWC_DRY(IIPAR) ! [m3/s] Dry volumetric water content + ! (no E-T) + REAL*8 VWC_OPT(IIPAR) ! [m3/m3] E-T optimal volumetric water + ! content + REAL*8 VWC_SAT(IIPAR) ! [m3/m3] Saturated volumetric water + ! content (sand-dependent) + REAL*8 VWC_SFC_SLICE(IIPAR) ! [m3/m3] Volumetric water content + REAL*8 GWC_SFC(IIPAR) ! [kg/kg] Gravimetric water content + REAL*8 RGH_MMN(IIPAR) ! [m] Roughness length momentum + REAL*8 W10M + + ! GCM diagnostics + ! Dust tendency due to gravitational settling [kg/kg/s] + REAL*8 Q_DST_TND_MBL(IIPAR,NDSTBIN) + + ! Total dust tendency due to gravitational settling [kg/kg/s] + REAL*8 Q_DST_TND_MBL_TTL(IIPAR) + + ! External functions + REAL*8, EXTERNAL :: SFCWINDSQR + + !================================================================= + ! DST_MBL begins here! + !================================================================= + + ! Time step [s] + TM_DLT = TM_ADJ + + ! Freezing pt of soil [K] -- assume it's 0C + TPT_SOI_FRZ = TPT_FRZ_PNT + + ! Initialize output fluxes and tendencies + Q_DST_TND_MBL(:,:) = 0.0D0 ! [kg kg-1 s-1] + Q_DST_TND_MBL_TTL(:) = 0.0D0 ! [kg kg-1 s-1] + FLX_MSS_VRT_DST(:,:) = 0.0D0 ! [kg m-2 s-1] + FLX_MSS_VRT_DST_TTL(:) = 0.0D0 ! [kg m-2 s-1] + FRC_THR_NCR_WTR(:) = 0.0D0 ! [frc] + WND_RFR(:) = 0.0D0 ! [m s-1] + WND_FRC(:) = 0.0D0 ! [m s-1] + WND_FRC_SLT(:) = 0.0D0 ! [m s-1] + WND_FRC_THR_SLT(:) = 0.0D0 ! [m s-1] + WND_RFR_THR_SLT(:) = 0.0D0 ! [m s-1] + HGT_ZPD(:) = HGT_ZPD_MBL ! [m] + + DSRC(:,:) = 0.0D0 + + !================================================================= + ! Compute necessary derived fields + !================================================================= + DO I = 1, IIPAR + + ! Stop occasional haywire model runs + IF ( TPT_MDP(I) > 350.0d0 ) THEN + CALL ERROR_STOP( 'TPT_MDP(i) > 350.0', + & 'DST_MBL ("dust_dead_mod.f")' ) + ENDIF + + ! Midlayer virtual temperature [K] + TPT_VRT_MDP = TPT_MDP(I) + & * (1.0d0 + EPS_H2O_RCP_M1 * Q_H2O_VPR(I)) + + ! Density at center of gridbox [kg/m3] + DNS_MDP(I) = PRS_MDP(I) + & / (TPT_VRT_MDP * GAS_CST_DRY_AIR) + + ! Commented out + !cApproximate surface virtual temperature (uses midlayer moisture) + !c tpt_vrt_sfc=tpt_sfc(i)*(1.0+eps_H2O_rcp_m1*q_H2O_vpr(i)) ! [K] + !c + !c Surface density + !c dns_sfc(i)=prs_sfc(i)/(tpt_vrt_sfc*gas_cst_dry_air) ! [kg m-3] + + ! Mass of air currently in gridbox [kg/m2] + MPL_AIR(I) = PRS_DLT(I) * GRV_SFC_RCP + + ! Mean surface layer horizontal wind speed + WND_MDP(I) = SQRT( WND_ZNL_MDP(I)*WND_ZNL_MDP(I) + & + WND_MRD_MDP(I)*WND_MRD_MDP(I) ) + + ENDDO + + !================================================================= + ! Gather input variables from GEOS-CHEM modules etc. + !================================================================= + + ! Get LSM Surface type (0..28) + CALL SFC_TYP_GET( LAT_IDX, SFC_TYP_SLICE ) + + ! Get erodability and mass fractions + CALL SOI_TXT_GET( + & LAT_IDX, ! I [idx] Latitude index + & LND_FRC_DRY_SLICE, ! O [frc] Dry land fraction + & MBL_BSN_FCT_SLICE, ! O [frc] Erodibility factor + & MSS_FRC_CACO3_SLICE, ! O [frc] Mass fraction of CaCO3 + & MSS_FRC_CLY_SLICE, ! O [frc] Mass fraction of clay + & MSS_FRC_SND_SLICE ) ! O [frc] Mass fraction of sand + + ! Get GOCART source function (tdf, bmy, 1/25/07) + CALL SRCE_FUNC_GET( ! GOCART source function + & LAT_IDX, ! I [idx] Latitude index + & SRCE_FUNC_SLICE ) ! O [frc] GOCART source function + + ! Get volumetric water content from GWET + CALL VWC_SFC_GET( + & LAT_IDX, ! I [idx] Latitude index + & VWC_SFC_SLICE ) ! O [m3 m-3] Volumetric water content + + ! Get surface and soil temperature + CALL TPT_GND_SOI_GET( + & LAT_IDX, ! I [idx] Latitude index! + & TPT_GND_SLICE, ! O [K] Ground temperature + & TPT_SOI_SLICE ) ! O [K] Soil temperature + + ! Get time-varying vegetation area index + CALL DST_TVBDS_GET( + & LAT_IDX, ! I [idx] Latitude index + & VAI_DST_SLICE) ! O [m2 m-2] Vegetation area index, one-sided + + ! Get fraction of surface covered by snow + CALL SNW_FRC_GET( + & SNW_HGT_LQD, ! I [m] Equivalent liquid water snow depth + & SNW_FRC ) ! O [frc] Fraction of surface covered by snow + + !================================================================= + ! Use the variables retrieved above to compute the fraction + ! of each gridcell suitable for dust mobilization + !================================================================= + CALL LND_FRC_MBL_GET( + & DOY, ! I [day] Day of year [1.0..366.0) + & FLG_MBL_SLICE, ! O [flg] Mobilization candidate flag + & LAT_RDN, ! I [rdn] Latitude + & LND_FRC_DRY_SLICE, ! I [frc] Dry land fraction + & LND_FRC_MBL_SLICE, ! O [frc] Bare ground fraction + & MBL_NBR, ! O [flg] Number of mobilization candidates + & ORO, ! I [frc] Orography + & SFC_TYP_SLICE, ! I [idx] LSM surface type (0..28) + & SNW_FRC, ! I [frc] Fraction of surface covered by snow + & TPT_SOI_SLICE, ! I [K] Soil temperature + & TPT_SOI_FRZ, ! I [K] Temperature of frozen soil + & VAI_DST_SLICE) ! I [m2 m-2] Vegetation area index, one-sided + + ! Much ado about nothing + if (mbl_nbr == 0) then +ctdf print *,' no mobilisation candidates' + goto 737 + endif + + !================================================================= + ! Compute time-invariant hydrologic properties + ! NB flg_mbl IS time-dependent, so keep this in time loop. + !================================================================= + CALL HYD_PRP_GET( ! NB: These properties are time-invariant + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & MSS_FRC_CLY_SLICE, ! I [frc] Mass fraction clay + & MSS_FRC_SND_SLICE, ! I [frc] Mass fraction sand + & VWC_DRY, ! O [m3/m3] Dry vol'mtric water content (no E-T) + & VWC_OPT, ! O [m3/m3] E-T optimal volumetric water content + & VWC_SAT) ! O [m3/m3] Saturated volumetric water content + + CND_TRM_SOI(:) = 0.0D0 + LVL_DLT(:) = 0.0D0 + + !================================================================= + ! Get reference wind at 10m + !================================================================= + DO I = 1, IIPAR + W10M = SQRT( SFCWINDSQR( I, LAT_IDX ) ) + + ! add mobilisation criterion flag + IF ( FLG_MBL_SLICE(I) ) THEN + WND_RFR(I) = W10M + ENDIF + ENDDO + + !================================================================= + ! Compute standard roughness length. This call is probably + ! unnecessary, because we are only concerned with mobilisation + ! candidates, for which roughness length is imposed in blm_mbl + !================================================================= + CALL RGH_MMN_GET( ! Set roughness length w/o zero plane displacement + & ORO, ! I [frc] Orography + & RGH_MMN, ! O [m] Roughness length momentum + & SFC_TYP_SLICE, ! I [idx] LSM surface type (0..28) + & SNW_FRC, ! I [frc] Fraction of surface covered by snow + & WND_RFR ) ! I [m s-1] 10 m wind speed + + !================================================================= + ! Introduce Ustar and Z0 from GEOS data + !================================================================= + DO I = 1, IIPAR + IJLOOP = (LAT_IDX-1)*IIPAR+I + + ! Just assign for flag mobilisation candidates + IF ( FLG_MBL_SLICE(I) ) THEN + WND_FRC_GEOS(I) = USTAR(I,LAT_IDX) + Z0_GEOS(I) = Z0(I,LAT_IDX) + ELSE + WND_FRC_GEOS(I) = 0.0D0 + Z0_GEOS(I) = 0.0D0 + ENDIF + ENDDO + + !================================================================= + ! Surface exchange properties over erodible surfaces + ! DO NEED THIS: Compute Monin-Obukhov and Friction velocities + ! appropriate for dust producing regions. + ! + ! Now calling Stripped down (adiabatic) version tdf 10/27/2K3 + ! rgh_mmn_mbl parameter included directly in blm_mbl + !================================================================= + CALL BLM_MBL( + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & RGH_MMN, ! I [m] Roughness length momentum, Z0,m + & WND_RFR, ! I [m s-1] 10 m wind speed + & MNO_LNG, ! O [m] Monin-Obukhov length + & WND_FRC) ! O [m s-1] Surface friction velocity, U* + + !================================================================= + ! Factor by which surface roughness increases threshold friction + ! velocity. The sink of atrmospheric momentum into non-erodible + ! roughness elements Zender et al., expression (3) + !================================================================= +!----------------------------------------------------------------------------- +! Prior to 1/25/07: +! For now, instead of calling this routine to get FRC_THR_NCR_DRG, we will +! just set it to 1 (tdf, bmy, 1/25/07) +! +! %%%%% DO NOT DELETE -- LEAVE THIS CODE COMMENTED OUT %%%%% +! +! CALL FRC_THR_NCR_DRG_GET( +! & FRC_THR_NCR_DRG, ! O [frc] Factor increases thresh. fric. veloc. +! & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag +! & RGH_MMN_MBL, ! I [m] Rgh length momentum for erodible sfcs +! & RGH_MMN_SMT ) ! I [m] Smooth roughness length, Z0,m,s +!----------------------------------------------------------------------------- + + ! Now set roughness factor to 1.0 (tdf, bmy, 1/25/07) + FRC_THR_NCR_DRG(:) = 1.0d0 + + !================================================================= + ! Convert volumetric water content to gravimetric water content + ! NB: Owen effect included in wnd_frc_slt_get + !================================================================= + CALL VWC2GWC( + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & GWC_SFC, ! O [kg kg-1] Gravimetric water content + & VWC_SAT, ! I [m3 m-3] Saturated VWC (sand-dependent) + & VWC_SFC_SLICE ) ! I [m3 m-3] Volumetric water content + + !================================================================= + ! Factor by which soil moisture increases threshold friction + ! velocity -- i.e. the inhibition of saltation by soil mositure, + ! Zender et al., exp(5). + !================================================================= + CALL FRC_THR_NCR_WTR_GET( + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & FRC_THR_NCR_WTR, ! O [frc] Factor by which moisture increases + ! threshold friction velocity + & MSS_FRC_CLY_SLICE, ! I [frc] Mass fraction of clay + & GWC_SFC) ! I [kg kg-1] Gravimetric water content + + !================================================================= + ! Now, compute basic threshold friction velocity for saltation + ! over dry, bare, smooth ground. fxm: Use surface density not + ! midlayer density + !================================================================= + CALL WND_FRC_THR_SLT_GET( + & FLG_MBL_SLICE, ! I mobilisation flag + & DNS_MDP, ! I [kg m-3] Midlayer density + & WND_FRC_THR_SLT ) ! O [m s-1] Threshold friction velocity + + ! Adjust threshold friction velocity to account + ! for moisture and roughness + DO I = 1, IIPAR + WND_FRC_THR_SLT(I) = ! [m s-1] Threshold friction velocity + ! for saltation + & WND_FRC_THR_SLT(i) ! [m s-1] Threshold for dry, flat ground + & * FRC_THR_NCR_WTR(i) ! [frc] Adjustment for moisture + & * FRC_THR_NCR_DRG(i) ! [frc] Adjustment for roughness + ENDDO + + ! Threshold saltation wind speed at reference height, 10m + DO I = 1, IIPAR + IF ( FLG_MBL_SLICE(I) ) THEN + WND_RFR_THR_SLT(I) = ! [m s-1] Threshold 10 m wind speed + ! for saltation + & WND_RFR(I) * WND_FRC_THR_SLT(I) / WND_FRC(i) + ENDIF + ENDDO + + !================================================================= + ! Saltation increases friction speed by roughening surface + ! i.e. Owen effect, Zender et al., expression (4) + ! + ! Compute the wind friction velocity due to saltation, U*,s + ! accounting for the Owen effect. + !================================================================= + CALL WND_FRC_SLT_GET( + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & WND_FRC, ! I [m s-1] Surface friction velocity + & WND_FRC_SLT, ! O [m s-1] Saltating friction velocity + & WND_RFR, ! I [m s-1] Wind speed at reference height + & WND_RFR_THR_SLT ) ! I [m s-1] Thresh. 10 m wind speed for saltation + + !================================================================= + ! Compute horizontal streamwise mass flux, Zender et al., expr. (10) + !================================================================= + CALL FLX_MSS_HRZ_SLT_TTL_WHI79_GET( + & DNS_MDP, ! I [kg m-3] Midlayer density + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & FLX_MSS_HRZ_SLT_TTL, ! O [kg m-1 s-1] Vertically integrated + ! streamwise mass flux + & WND_FRC_SLT, ! I [m s-1] Saltating friction velocity + & WND_FRC_THR_SLT ) ! I [m s-1] Threshold friction vel for saltation + +!----------------------------------------------------------------------------- +! Prior to 1/25/07: +! We now multiply by the GOCART source function, and we will ignore +! the MBL_BSN_FCT_SLICE. (tdf, bmy, 1/25/07) +! +! %%%%% DO NOT DELETE -- LEAVE THIS CODE COMMENTED OUT %%%%% +! +!ctdf...prior to Apr/05/06 +! ! Apply land surface and vegetation limitations +! ! and global tuning factor +! DO I = 1, IIPAR +! FLX_MSS_HRZ_SLT_TTL(I) = FLX_MSS_HRZ_SLT_TTL(I) ! [kg m-2 s-1] +! & * LND_FRC_MBL_SLICE(i) ! [frc] Bare ground fraction +! & * MBL_BSN_FCT_SLICE(i) ! [frc] Erodibility factor +! & * FLX_MSS_FDG_FCT ! [frc] Global mass flux tuning +! ! factor (empirical) +! ENDDO +!----------------------------------------------------------------------------- + + ! Now simply multiply by the GOCART source function. + ! The vegetation effect has been eliminated in LND_FRC_MBL_GET + ! and we also ignore MBL_BSN_FCT. (tdf, bmy, 1/25/07) + DO I = 1, IIPAR + FLX_MSS_HRZ_SLT_TTL(I) = FLX_MSS_HRZ_SLT_TTL(I) ! [kg m-2 s-1] + & * LND_FRC_MBL_SLICE(i) ! [frc] Bare ground fraction + & * FLX_MSS_FDG_FCT ! [frc] Global mass flux tuning + & * SRCE_FUNC_SLICE(I) ! GOCART source function + ENDDO + + !================================================================= + ! Compute vertical dust mass flux, see Zender et al., expr. (11). + !================================================================= + CALL FLX_MSS_VRT_DST_TTL_MAB95_GET( + & DST_SLT_FLX_RAT_TTL, ! O [m-1] Ratio of vertical dust flux to + ! streamwise mass flux + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & FLX_MSS_HRZ_SLT_TTL, ! I [kg/m/s] Vertically integrated + ! streamwise mass flux + & FLX_MSS_VRT_DST_TTL, ! O [kg/m2/s] Total vertical mass flux of dust + & MSS_FRC_CLY_SLICE ) ! I [frc] Mass fraction clay + + + !================================================================= + ! Now, partition vertical dust mass flux into transport bins + ! + ! OVR_SRC_SNK_MSS needed in FLX_MSS_VRT_DST_PRT + ! computed in DST_PSD_MSS, called from "dust_mod.f" (tdf, 3/30/04) + !================================================================= + CALL FLX_MSS_VRT_DST_PRT( + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & FLX_MSS_VRT_DST, ! O [kg m-2 s-1] Vertical mass flux of dust + & FLX_MSS_VRT_DST_TTL) ! I [kg m-2 s-1] Total vertical mass flux of dus + + !================================================================= + ! Mask dust mass flux by tracer mass fraction at source + !================================================================= + FLG_CACO3 = .FALSE. ! [flg] Activate CaCO3 tracer + IF ( FLG_CACO3 ) THEN + CALL FLX_MSS_CACO3_MSK( + & DMT_VWR, ! I [m] Mass weighted diameter resolved + & FLG_MBL_SLICE, ! I [flg] Mobilization candidate flag + & FLX_MSS_VRT_DST, ! I/O [kg m-2 s-1] Vert. mass flux of dust + & MSS_FRC_CACO3_SLICE, ! I [frc] Mass fraction of CaCO3 + & MSS_FRC_CLY_SLICE, ! I [frc] Mass fraction of clay + & MSS_FRC_SND_SLICE ) ! I [frc] Mass fraction of sand + endif + + ! Now, flx_mss_vrt_dst has units of kg/m2/sec + + ! Fluxes are known, so adjust mixing ratios + DO I=1, IIPAR ! NB: Inefficient loop order + IF (FLG_MBL_SLICE(I)) THEN + + ! Loop over dust bins + DO M = 1, NDSTBIN + + !======================================================== + ! Compute dust mobilisation tendency. Recognise that + ! what GEOS-CHEM wants is an increment in kg...So, + ! multiply by DXYP [m2] and tm_adj [sec] + !======================================================== + + ! use get_area_m2 (Grid box surface area) [m2] instead of DXYP + Q_DST_TND_MBL(I,M) = + & FLX_MSS_VRT_DST(I,M) * GET_AREA_M2(LAT_IDX) ! [kg/sec] + + ! Introduce DSRC: dust mixing ratio increment 12/9/2K3 + DSRC(I,M) = ! [kg] + & TM_ADJ * Q_DST_TND_MBL(I,M) + + ENDDO + ENDIF + ENDDO + + ! Jump to here when no points are mobilization candidates + 737 CONTINUE + + ! Return to calling program + END SUBROUTINE DST_MBL + +!------------------------------------------------------------------------------ + + SUBROUTINE SRCE_FUNC_GET( LAT_IDX, SRCE_FUNC_OUT ) +! +!****************************************************************************** +! Subroutine SRCE_FUNC_GET returns a latitude slice of the GOCART source +! function. This routine is called by DST_MBL. (tdf, bmy, 1/25/07) +! +! Arguments as Input: +! ============================================================================ +! (1 ) LAT_IDX (INTEGER) : GEOS-Chem latitude index +! +! Arguments as Output: +! ============================================================================ +! (1 ) SRCE_FUNC_OUT (REAL*8 ) : GOCART source function [fraction] +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: LAT_IDX + REAL*8, INTENT(OUT) :: SRCE_FUNC_OUT(IIPAR) + + ! Local variables + INTEGER :: LON_IDX + + !================================================================= + ! SRCE_FUNC_GET begins here! + !================================================================= + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! Save latitude slice in SRCE_FUNC_OUT + SRCE_FUNC_OUT(LON_IDX) = SRCE_FUNC(LON_IDX,LAT_IDX) + + ENDDO + + ! Return to calling program + END SUBROUTINE SRCE_FUNC_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE SOI_TXT_GET( J, LND_FRC_DRY_OUT, + & MBL_BSN_FCT_OUT, MSS_FRC_CACO3_OUT, + & MSS_FRC_CLY_OUT, MSS_FRC_SND_OUT ) +! +!****************************************************************************** +! Subroutine SOI_GET_TXT returns a latitude slice of soil texture to the +! calling program DST_MBL. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : Grid box latitude index +! +! Arguments as Output: +! ============================================================================ +! (2 ) lnd_frc_dry_out (REAL*8 ) : Dry land fraction [fraction] +! (3 ) mbl_bsn_fct_out (REAL*8 ) : Erodibility factor [fraction] +! (4 ) mss_frc_CaCO3_out (REAL*8 ) : Mass fraction of CaCO3 [fraction] +! (5 ) mss_frc_cly_out (REAL*8 ) : Mass fraction of clay [fraction] +! (6 ) mss_frc_snd_out (REAL*8 ) : Mass fraction of sand [fraction] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes (bmy, 3/30/04) +!****************************************************************************** +! + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: J + REAL*8, INTENT(OUT) :: LND_FRC_DRY_OUT(IIPAR) + REAL*8, INTENT(OUT) :: MBL_BSN_FCT_OUT(IIPAR) + REAL*8, INTENT(OUT) :: MSS_FRC_CACO3_OUT(IIPAR) + REAL*8, INTENT(OUT) :: MSS_FRC_CLY_OUT(IIPAR) + REAL*8, INTENT(OUT) :: MSS_FRC_SND_OUT(IIPAR) + + ! Local variables + INTEGER :: I + + ! Ad hoc globally uniform clay mass fraction [kg/kg] + REAL*8, PARAMETER :: MSS_FRC_CLY_GLB = 0.20d0 + + !================================================================= + ! SOI_GET_TXT begins here! + !================================================================= + DO I = 1, IIPAR + + ! Save dry land fraction slice + LND_FRC_DRY_OUT(I) = LND_FRC_DRY(I,J) + + ! Change surface source distribution to "geomorphic" tdf 12/12/2K3 + MBL_BSN_FCT_OUT(I) = ERD_FCT_GEO(I,J) + + !fxm: CaCO3 currently has missing value of + ! 1.0e36 which causes problems + IF ( MSS_FRC_CACO3(I,J) <= 1.0D0 ) THEN + MSS_FRC_CACO3_OUT(I) = MSS_FRC_CACO3(I,J) + ELSE + MSS_FRC_CACO3_OUT(I) = 0.0D0 + ENDIF + + ! fxm Temporarily set mss_frc_cly used in mobilization to globally + ! uniform SGS value of 0.20, and put excess mass fraction + ! into sand + MSS_FRC_CLY_OUT(I) = MSS_FRC_CLY_GLB + MSS_FRC_SND_OUT(I) = MSS_FRC_SND(I,J) + + & MSS_FRC_CLY(I,J) - MSS_FRC_CLY_GLB + + ENDDO + + ! Return to calling program + END SUBROUTINE SOI_TXT_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE SFC_TYP_GET( J, SFC_TYP_OUT ) +! +!****************************************************************************** +! Subroutine SFC_TYP_GET returns a latitude slice of LSM surface type +! to the calling programs DST_MBL & DST_DPS_DRY. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : Grid box latitude index +! +! Arguments as Output: +! ============================================================================ +! (1 ) sfc_typ_out (REAL*8 ) : LSM surface type (0..28) [unitless] +! +! NOTES +! (1 ) Updated comments & cosmetic changes (bmy, 3/30/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! IIPAR + + ! Arguments + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(OUT) :: SFC_TYP_OUT(IIPAR) + + ! Local variables + INTEGER :: I + + !================================================================= + ! SFC_TYP_GET begins here! + !================================================================= + DO I = 1, IIPAR + SFC_TYP_OUT(I) = SFC_TYP(I,J) + ENDDO + + ! Return to calling program + END SUBROUTINE SFC_TYP_GET ! end sfc_typ_get() + +!------------------------------------------------------------------------------ + + SUBROUTINE TPT_GND_SOI_GET( J, TPT_GND_OUT, TPT_SOI_OUT ) +! +!****************************************************************************** +! Subroutine TPT_GND_SOI_GET returns a latitude slice of soil temperature and +! ground temperature to the calling program DST_MBL. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : Grid box latitude index +! +! Arguments as Output: +! ============================================================================ +! (2 ) TPT_GND_OUT (REAL*8 ) : Ground temperature array slice [K] +! (3 ) tpt_soi_out (REAL*8 ) : Soil temperature array slice [K] +! +! NOTES +! (1 ) Updated comments & cosmetic changes (bmy, 3/30/04) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : TS + +# include "CMN_SIZE" ! Size parameters ! IIPAR + + ! Arguments + INTEGER, INTENT(IN) :: J + REAL*8, INTENT(OUT) :: TPT_GND_OUT(IIPAR) + REAL*8, INTENT(OUT) :: TPT_SOI_OUT(IIPAR) + + ! Local variables + INTEGER :: I + + !================================================================= + ! TPT_GND_SOI_GET begins here! + !================================================================= + + ! Use TS from GEOS-CHEM (tdf, 3/30/04) + DO I = 1, IIPAR + TPT_GND_OUT(I) = TS(I,J) + TPT_SOI_OUT(I) = TS(I,J) + ENDDO + + ! Return to calling program + END SUBROUTINE TPT_GND_SOI_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE VWC_SFC_GET( J, VWC_SFC_OUT ) +! +!****************************************************************************** +! Subroutine TPT_GND_SOI_GET returns a latitude slice of volumetric water +! content to the calling program DST_MBL. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : Grid box latitude index +! +! Arguments as Output: +! ============================================================================ +! VWC_SFC_OUT (REAL*8 ) : Volumetric water content [m3/m3] +! +! NOTES +! (1 ) Updated comments & cosmetic changes (bmy, 3/30/04) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : GWETTOP + +# include "CMN_SIZE" ! Size parameters ! IIPAR + + ! Arguments + INTEGER, INTENT(IN) :: J + REAL*8, INTENT(OUT) :: VWC_SFC_OUT(IIPAR) + + ! Local variables + INTEGER :: I + + !================================================================= + ! VWC_SFC_GET begins here! + !================================================================= + DO I = 1, IIPAR + VWC_SFC_OUT(I) = GWETTOP(I,J) + ENDDO + + ! Return to calling program + END SUBROUTINE VWC_SFC_GET + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION DSVPDT_H2O_LQD_PRK78_FST_SCL( TPT_CLS ) +! +!****************************************************************************** +! Function DSVPDT_H2O_LQD_PRK78_FST_SCL returns the derivative of saturation +! vapor pressure [Pa] over planar liquid water (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TPT_CLS (REAL*8) : Temperature in Celsius [C] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents. (bmy, 3/30/04) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: TPT_CLS + + ! Local variables + REAL*8, PARAMETER :: C0 = 4.438099984d-01 + REAL*8, PARAMETER :: C1 = 2.857002636d-02 + REAL*8, PARAMETER :: C2 = 7.938054040d-04 + REAL*8, PARAMETER :: C3 = 1.215215065d-05 + REAL*8, PARAMETER :: C4 = 1.036561403d-07 + REAL*8, PARAMETER :: C5 = 3.532421810d-10 + REAL*8, PARAMETER :: C6 =-7.090244804d-13 + + !================================================================= + ! DSVPDT_H2O_LQD_PRK78_FST_SCL begins here! + !================================================================= + + ! Return deriv. of saturation vapor pressure [Pa] + DSVPDT_H2O_LQD_PRK78_FST_SCL = 100.0d0 * ( C0+TPT_CLS * + & ( C1+TPT_CLS * + & ( C2+TPT_CLS * + & ( C3+TPT_CLS * + & ( C4+TPT_CLS * + & ( C5+TPT_CLS * C6 )))))) + + ! Return to calling program + END FUNCTION DSVPDT_H2O_LQD_PRK78_FST_SCL + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION DSVPDT_H2O_ICE_PRK78_FST_SCL( TPT_CLS ) +! +!****************************************************************************** +! Function DSVPDT_H2O_ICE_PRK78_FST_SCL returns the derivative of saturation +! vapor pressure [Pa] over planar ice water (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TPT_CLS (REAL*8) : Temperature in Celsius [C] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents. (bmy, 3/30/04) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: TPT_CLS + + ! Local variables + REAL*8, PARAMETER :: D0 = 5.030305237d-01 + REAL*8, PARAMETER :: D1 = 3.773255020d-02 + REAL*8, PARAMETER :: D2 = 1.267995369d-03 + REAL*8, PARAMETER :: D3 = 2.477563108d-05 + REAL*8, PARAMETER :: D4 = 3.005693132d-07 + REAL*8, PARAMETER :: D5 = 2.158542548d-09 + REAL*8, PARAMETER :: D6 = 7.131097725d-12 + + !================================================================= + ! DSVPDT_H2O_ICE_PRK78_FST_SCL begins here! + !================================================================= + + ! Return deriv. of sat vapor pressure [Pa] + DSVPDT_H2O_ICE_PRK78_FST_SCL = 100.0D0 * ( D0+TPT_CLS * + & ( D1+TPT_CLS * + & ( D2+TPT_CLS * + & ( D3+TPT_CLS * + & ( D4+TPT_CLS * + & ( D5+TPT_CLS * D6 )))))) + + ! Return to calling program + END FUNCTION DSVPDT_H2O_ICE_PRK78_FST_SCL + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION SVP_H2O_LQD_PRK78_FST_SCL( TPT_CLS ) +! +!****************************************************************************** +! Function SVP_H2O_LQD_PRK78_FST_SCL returns the saturation vapor pressure +! over planer liquid water [Pa] See Lowe and Ficke (1974) as reported in +! PrK78 p. 625. Range of validity is -50 C < T < 50 C. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TPT_CLS (REAL*8) : Temperature in Celsius [C] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents. (bmy, 3/30/04) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: TPT_CLS + + ! Local variables + REAL*8, PARAMETER :: A0 = 6.107799961d0 + REAL*8, PARAMETER :: A1 = 4.436518521d-01 + REAL*8, PARAMETER :: A2 = 1.428945805d-02 + REAL*8, PARAMETER :: A3 = 2.650648471d-04 + REAL*8, PARAMETER :: A4 = 3.031240396d-06 + REAL*8, PARAMETER :: A5 = 2.034080948d-08 + REAL*8, PARAMETER :: A6 = 6.136820929d-11 + + !================================================================= + ! SVP_H2O_LQD_PRK78_FST_SCL begins here! + !================================================================= + + ! Return saturation vapor pressure over liquid water [Pa] + SVP_H2O_LQD_PRK78_FST_SCL = 100.0D0 * ( A0+TPT_CLS * + & ( A1+TPT_CLS * + & ( A2+TPT_CLS * + & ( A3+TPT_CLS * + & ( A4+TPT_CLS * + & ( A5+TPT_CLS * A6 )))))) + + ! Return to calling program + END FUNCTION SVP_H2O_LQD_PRK78_FST_SCL + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION SVP_H2O_ICE_PRK78_FST_SCL( TPT_CLS ) +! +!****************************************************************************** +! Function SVP_H2O_ICE_PRK78_FST_SCL returns the saturation vapor pressure +! [Pa] over planar ice water (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TPT_CLS (REAL*8) : Temperature in Celsius [C] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents. (bmy, 3/30/04) +!****************************************************************************** +! + + ! Arguments + REAL*8, INTENT(IN) :: TPT_CLS + + ! Local variables + REAL*8, PARAMETER :: B0 = 6.109177956d0 + REAL*8, PARAMETER :: B1 = 5.034698970d-01 + REAL*8, PARAMETER :: B2 = 1.886013408d-02 + REAL*8, PARAMETER :: B3 = 4.176223716d-04 + REAL*8, PARAMETER :: B4 = 5.824720280d-06 + REAL*8, PARAMETER :: B5 = 4.838803174d-08 + REAL*8, PARAMETER :: B6 = 1.838826904d-10 + + !================================================================= + ! SVP_H2O_ICE_PRK78_FST_SCL begins here! + !================================================================= + + ! Return saturation vapor pressure over ice [Pa] + SVP_H2O_ICE_PRK78_FST_SCL = 100.0D0 * ( B0+TPT_CLS * + & ( B1+TPT_CLS * + & ( B2+TPT_CLS * + & ( B3+TPT_CLS * + & ( B4+TPT_CLS * + & ( B5+TPT_CLS * B6 )))))) + + ! Return to calling program + END FUNCTION SVP_H2O_ICE_PRK78_FST_SCL + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION TPT_BND_CLS_GET( TPT ) +! +!****************************************************************************** +! Function TPT_BND_CLS_GET returns the bounded temperature in [C], +! (i.e., -50 < T [C] < 50 C), given the temperature in [K]. +! (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TPT (REAL*8) : Temperature in Kelvin [K] +! +! NOTES: +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: TPT + + ! Local variables + REAL*8, PARAMETER :: TPT_FRZ_PNT=273.15 + + !================================================================= + ! TPT_BND_CLS_GET begins here! + !================================================================= + TPT_BND_CLS_GET = MIN( 50.0D0, MAX( -50.0D0, ( TPT-TPT_FRZ_PNT)) ) + + ! Return to calling program + END FUNCTION TPT_BND_CLS_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_ORO( OROGRAPHY ) +! +!****************************************************************************** +! Subroutine GET_ORO creates a 2D orography array, OROGRAPHY, from the +! GMAO LWI fields. Ocean= 0; Land=1; ice=2. (tdf, bmy, 3/30/04, 8/17/05) +! +! Arguments as Output: +! ============================================================================ +! (1 ) OROGRAPHY (INTEGER) : Array for orography flags +! +! NOTES: +! (1 ) Added parallel DO-loop (bmy, 4/14/04) +! (2 ) Now modified for GCAP and GEOS-5 met fields (swu, bmy, 6/9/05) +! (3 ) Now use IS_LAND, IS_WATER, IS_ICE functions from "dao_mod.f" +! (bmy, 8/17/05) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : IS_LAND, IS_WATER, IS_ICE + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(OUT) :: OROGRAPHY(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J, TEMP + + !================================================================= + ! GET_ORO begins here! + !================================================================= +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Ocean + IF ( IS_WATER( I, J ) ) OROGRAPHY(I,J) = 0 + + ! Land + IF ( IS_LAND( I, J ) ) OROGRAPHY(I,J) = 1 + + ! Ice + IF ( IS_ICE ( I, J ) ) OROGRAPHY(I,J) = 2 + + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE GET_ORO + +!------------------------------------------------------------------------------ + + SUBROUTINE HYD_PRP_GET( FLG_MBL, MSS_FRC_CLY, MSS_FRC_SND, + & VWC_DRY, VWC_OPT, VWC_SAT ) +! +!****************************************************************************** +! Subroutine HYD_PRP_GET determines hydrologic properties from soil texture. +! (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [unitless] +! (2 ) MSS_FRC_CLY (REAL*8 ) : Mass fraction clay [fraction] +! (3 ) MSS_FRC_SND (REAL*8 ) : Mass fraction sand [fraction] +! +! Arguments as Output: +! ============================================================================ +! (4 ) VWC_DRY (REAL*8 ) : Dry volumetric water content (no E-T) [m3/m3] +! (5 ) VWC_OPT (REAL*8 ) : E-T optimal volumetric water content [m3/m3] +! (6 ) VWC_SAT (REAL*8 ) : Saturated volumetric water content [m3/m3] +! +! NOTES: +! (1 ) All I/O for this routine is time-invariant, thus, the hydrologic +! properties could be computed once at initialization. However, +! FLG_MBL is time-dependent, so we should keep this as-is. +! (tdf, 10/27/03) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! IIPAR + + ! Arguments + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_CLY(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_SND(IIPAR) + REAL*8, INTENT(OUT) :: VWC_DRY(IIPAR) + REAL*8, INTENT(OUT) :: VWC_OPT(IIPAR) + REAL*8, INTENT(OUT) :: VWC_SAT(IIPAR) + + ! Local variables + INTEGER :: LON_IDX + + ! [frc] Exponent "b" for smp (clay-dependent) + REAL*8 :: SMP_XPN_B(IIPAR) + + ! [mm H2O] Saturated soil matric potential (sand-dependent) + REAL*8 :: SMP_SAT(IIPAR) + + !================================================================= + ! HYD_PRP_GET begins here + !================================================================= + + ! Initialize output values + VWC_DRY(:) = 0.0D0 + VWC_OPT(:) = 0.0D0 + VWC_SAT(:) = 0.0D0 + + ! Time-invariant soil hydraulic properties + ! See Bon96 p. 98, implemented in CCM:lsm/lsmtci() + DO LON_IDX = 1, IIPAR + + IF ( FLG_MBL(LON_IDX) ) THEN + + ! Exponent "b" for smp (clay-dependent) [fraction] + SMP_XPN_B(LON_IDX) = + & 2.91D0 +0.159D0 * MSS_FRC_CLY(LON_IDX) * 100.0D0 + + ! NB: Adopt convention that matric potential is positive definite + ! Saturated soil matric potential (sand-dependent) [mm H2O] + SMP_SAT(LON_IDX) = + & 10.0D0 * (10.0D0**(1.88D0-0.0131D0 + & * MSS_FRC_SND(LON_IDX)*100.0D0)) + + ! Saturated volumetric water content (sand-dependent) ! [m3 m-3] + VWC_SAT(LON_IDX)= + & 0.489D0 - 0.00126D0 * MSS_FRC_SND(LON_IDX)*100.0D0 + + ! [m3 m-3] + VWC_DRY(LON_IDX) = + + ! Dry volumetric water content (no E-T) + & VWC_SAT(LON_IDX)*(316230.0D0/SMP_SAT(LON_IDX)) + & **(-1.0D0/SMP_XPN_B(LON_IDX)) + + ! E-T optimal volumetric water content! [m3 m-3] + VWC_OPT(LON_IDX) = + & VWC_SAT(LON_IDX)*(158490.0D0/SMP_SAT(LON_IDX)) + & **(-1.0D0/SMP_XPN_B(LON_IDX)) + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE HYD_PRP_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE CND_TRM_SOI_GET( CND_TRM_SOI, FLG_MBL, LVL_DLT, + & MSS_FRC_CLY, MSS_FRC_SND, TPT_SOI, + & VWC_DRY, VWC_OPT, VWC_SAT, + & VWC_SFC ) + +! +!****************************************************************************** +! Subroutine CND_TRM_SOI_GET gets thermal properties of soil. Currently this +! routine is optimized for ground without snow-cover. Although snow +! thickness is read in, it is not currently used. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (3 ) lvl_dlt (REAL*8 ) : Soil layer thickness [m ] +! (4 ) mss_frc_cly (REAL*8 ) : Mass fraction clay [frac.] +! (5 ) mss_frc_snd (REAL*8 ) : Mass fraction sand [frac.] +! (6 ) tpt_soi (REAL*8 ) : Soil temperature [K ] +! (7 ) vwc_dry (REAL*8 ) : Dry volumetric water content (no E-T) [m3/m3] +! (8 ) vwc_opt (REAL*8 ) : E-T optimal volumetric water content [m3/m3] +! (9 ) vwc_sat (REAL*8 ) : Saturated volumetric water content [m3/m3] +! (10) vwc_sfc (REAL*8 ) : Volumetric water content [m3/m3] +! +! Arguments as Output: +! ============================================================================ +! (1 ) CND_TRM_SOI (REAL*8 ) : Soil thermal conductivity [W/m/K] +! (2 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [flag ] +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! IIPAR + + ! Arguments + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_CLY(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_SND(IIPAR) + REAL*8, INTENT(IN) :: TPT_SOI(IIPAR) + REAL*8, INTENT(IN) :: VWC_DRY(IIPAR) + REAL*8, INTENT(IN) :: VWC_OPT(IIPAR) + REAL*8, INTENT(IN) :: VWC_SAT(IIPAR) + REAL*8, INTENT(IN) :: VWC_SFC(IIPAR) + REAL*8, INTENT(OUT) :: CND_TRM_SOI(IIPAR) + REAL*8, INTENT(OUT) :: LVL_DLT(IIPAR) + + !------------ + ! Parameters + !------------ + + ! Thermal conductivity of ice water [W m-1 K-1] + REAL*8, PARAMETER :: CND_TRM_H2O_ICE = 2.2d0 + + ! Thermal conductivity of liquid water [W m-1 K-1] + REAL*8, PARAMETER :: CND_TRM_H2O_LQD = 0.6d0 + + ! Thermal conductivity of snow Bon96 p. 77 [W m-1 K-1] + REAL*8, PARAMETER :: CND_TRM_SNW = 0.34d0 + + ! Soil layer thickness, top layer! [m] + REAL*8, PARAMETER :: LVL_DLT_SFC = 0.1d0 + + ! Temperature range of mixed phase soil [K] + REAL*8, PARAMETER :: TPT_DLT = 0.5d0 + + ! Latent heat of fusion of H2O at 0 C, standard [J kg-1] + REAL*8, PARAMETER :: LTN_HEAT_FSN_H2O_STD = 0.3336d06 + + ! Liquid water density [kg/m3] + REAL*8, PARAMETER :: DNS_H2O_LQD_STD = 1000.0d0 + + ! Kelvin--Celsius scale offset Bol80 [K] + REAL*8, PARAMETER :: TPT_FRZ_PNT = 273.15d0 + + !----------------- + ! Local variables + !----------------- + + ! Longitude index + INTEGER :: LON_IDX + + ! Thermal conductivity of dry soil [W m-1 K-1] + REAL*8 :: CND_TRM_SOI_DRY(IIPAR) + + ! Soil thermal conductivity, frozen [W m-1 K-1] + REAL*8 :: CND_TRM_SOI_FRZ(IIPAR) + + ! Thermal conductivity of soil solids [W m-1 K-1] + REAL*8 :: CND_TRM_SOI_SLD(IIPAR) + + ! Soil thermal conductivity, unfrozen [W m-1 K-1] + REAL*8 :: CND_TRM_SOI_WRM(IIPAR) + + ! Volumetric latent heat of fusion [J m-3] + REAL*8 :: LTN_HEAT_FSN_VLM(IIPAR) + + ! Bounded geometric bulk thickness of snow [m] + REAL*8 :: SNW_HGT_BND + + !================================================================= + ! CND_TRM_SOI_GET begins here! + !================================================================= + + ! [m] Soil layer thickness + LVL_DLT(:) = LVL_DLT_SFC + + ! [W m-1 K-1] Soil thermal conductivity + CND_TRM_SOI(:) = 0.0D0 + + ! Loop over longitude + DO LON_IDX = 1, IIPAR + IF ( FLG_MBL(LON_IDX) ) THEN + + ! Volumetric latent heat of fusion [J m-3] + LTN_HEAT_FSN_VLM(LON_IDX) = VWC_SFC(LON_IDX) + & * LTN_HEAT_FSN_H2O_STD * DNS_H2O_LQD_STD + + !Thermal conductivity of soil solids Bon96 p. 77 [W/m/K] + CND_TRM_SOI_SLD(LON_IDX) = + & ( 8.80D0 *MSS_FRC_SND(LON_IDX) + & + 2.92D0 *MSS_FRC_CLY(LON_IDX) ) + & / (MSS_FRC_SND(LON_IDX) + & + MSS_FRC_CLY(LON_IDX)) + + ! Thermal conductivity of dry soil Bon96 p. 77 [W/m/K] + cnd_trm_soi_dry(lon_idx) = 0.15D0 + + ! Soil thermal conductivity, unfrozen [W/m/K] + CND_TRM_SOI_WRM(LON_IDX) = + & CND_TRM_SOI_DRY(LON_IDX) + & + ( CND_TRM_SOI_SLD(LON_IDX) + & ** (1.0D0-VWC_SAT(LON_IDX)) + & * (CND_TRM_H2O_LQD ** VWC_SFC(LON_IDX) ) + & - CND_TRM_SOI_DRY(LON_IDX) ) + & * VWC_SFC(LON_IDX) / VWC_SAT(lon_idx) + + ! Soil thermal conductivity, frozen [W/m/K] + CND_TRM_SOI_FRZ(LON_IDX) = + & CND_TRM_SOI_DRY(LON_IDX) + & + ( CND_TRM_SOI_SLD(LON_IDX) + & ** (1.0D0-VWC_SAT(LON_IDX)) + & * (CND_TRM_H2O_ICE ** VWC_SFC(LON_IDX) ) + & - CND_TRM_SOI_DRY(LON_IDX) ) + & * VWC_SFC(LON_IDX) / VWC_SAT(LON_IDX) + + IF (TPT_SOI(LON_IDX) < TPT_FRZ_PNT-TPT_DLT) THEN + ! Soil thermal conductivity [W/m/K] + CND_TRM_SOI(LON_IDX) = CND_TRM_SOI_FRZ(LON_IDX) + ENDIF + + IF ( (TPT_SOI(LON_IDX) >= TPT_FRZ_PNT-TPT_DLT) + & .AND. (TPT_SOI(LON_IDX) <= TPT_FRZ_PNT+TPT_DLT) ) + & THEN + + ! Soil thermal conductivity [W/m/K] + CND_TRM_SOI(LON_IDX) = + & CND_TRM_SOI_FRZ(LON_IDX) + & + (CND_TRM_SOI_FRZ(LON_IDX) + & - CND_TRM_SOI_WRM(LON_IDX) ) + & * (TPT_SOI(LON_IDX) + & -TPT_FRZ_PNT+TPT_DLT) + & / (2.0D0*TPT_DLT) + ENDIF + + IF (TPT_SOI(LON_IDX) > TPT_FRZ_PNT+TPT_DLT) THEN + ! Soil thermal conductivity[W/m/K] + CND_TRM_SOI(LON_IDX)=CND_TRM_SOI_WRM(LON_IDX) + ENDIF + +! Implement this later(??) +!cZ Blend snow into first soil layer +!cZ Snow is not allowed to cover dust mobilization regions +!cZ snw_hgt_bnd=min(snw_hgt(lon_idx),1.0D0) ! [m] Bounded geometric bulk thickness of snow +!cZ lvl_dlt_snw(lon_idx)=lvl_dlt(lon_idx)+snw_hgt_bnd ! O [m] Soil layer thickness +!cZ including snow Bon96 p. 77 +! +!cZ cnd_trm_soi(lon_idx)= & ! [W m-1 K-1] Soil thermal conductivity Bon96 p. 77 +!cZ cnd_trm_snw*cnd_trm_soi(lon_idx)*lvl_dlt_snw(lon_idx) & +!cZ /(cnd_trm_snw*lvl_dlt(lon_idx)+cnd_trm_soi(lon_idx)*snw_hgt_bnd) + + ENDIF + ENDDO + + END SUBROUTINE CND_TRM_SOI_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE TRN_FSH_VPR_SOI_ATM_GET( FLG_MBL, + & TPT_SOI, + & TPT_SOI_FRZ, + & TRN_FSH_VPR_SOI_ATM, + & VWC_DRY, + & VWC_OPT, + & VWC_SFC ) +! +!****************************************************************************** +! Subroutine TRN_FSH_VPR_SOI_ATM_GET computes the factor describing effects +! of soil texture and moisture on vapor transfer between soil and atmosphere. +! Taken from Bon96 p. 59, CCM:lsm/surphys. (tdf, bmy, 3/30/04) +! +! The TRN_FSH_VPR_SOI_ATM efficiency factor attempts to tie soil texture and +! moisture properties to the vapor conductance of the soil-atmosphere system. +! When the soil temperature is sub-freezing, the conductance describes the +! resistance to vapor sublimation (or deposition) and transport through the +! open soil pores to the atmosphere. +! +! For warm soils, vapor transfer is most efficient at the optimal VWC for E-T +! Thus when vwc_sfc = vwc_opt, soil vapor transfer is perfectly efficient +! (trn_fsh_vpr_soi_atm = 1.0) so the soil does not contribute any resistance +! to the surface vapor transfer. +! +! When vwc_sfc > vwc_opt, the soil has an excess of moisture and, again, +! vapor transfer is not limited by soil characteristics. +! In fact, according to Bon96 p. 98, vwc_dry is only slightly smaller than +! vwc_opt, so trn_fsh_vpr_soi_atm is usually either 0 or 1 and intermediate +! efficiencies occur over only a relatively small range of VWC. +! +! When vwc_sfc < vwc_dry, the soil matrix is subsaturated and acts as a +! one-way sink for vapor through osmotic and capillary potentials. +! In this case trn_fsh_vpr_soi_atm = 0, which would cause the surface +! resistance rss_vpr_sfc to blow up, but this is guarded against and +! rss_sfc_vpr is set to ~1.0e6*rss_aer_vpr instead. +! +! Note that this formulation does not seem to allow vapor transfer from +! the atmosphere to the soil when vwc_sfc < vwc_dry, even when +! e_atm > esat(Tg). +! +! Air at the apparent sink for moisture is has vapor pressure e_sfc +! e_atm = Vapor pressure of ambient air at z = hgt_mdp +! e_sfc = Vapor pressure at apparent sink for moisture at z = zpd + rgh_vpr +! e_gnd = Vapor pressure at air/ground interface temperature +! Air at the soil interface is assumed saturated, i.e., e_gnd = esat(Tg) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [unitless] +! (2 ) TPT_SOI (REAL*8 ) : Soil temperature [K ] +! (3 ) TPT_SOI_FRZ (REAL*8 ) : Temperature of frozen soil [K ] +! (5 ) VWC_DRY (REAL*8 ) : Dry volumetric WC (no E-T) [m3/m3 ] +! (6 ) VWC_OPT (REAL*8 ) : E-T optimal volumetric WC [m3/m3 ] +! (7 ) VWC_SFC (REAL*8 ) : Volumetric water content [m3/m3 ] +! +! Arguments as Output: +! ============================================================================ +! (4 ) TRN_FSH_VPR_SOI_ATM (REAL*8 ) : Transfer efficiency of vapor from +! soil to atmosphere [fraction] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also force double-precision +! with "D" exponents. (tdf, bmy, 3/30/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! IIPAR + + !---------------- + ! Arguments + !---------------- + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: TPT_SOI(IIPAR) + REAL*8, INTENT(IN) :: TPT_SOI_FRZ + REAL*8, INTENT(IN) :: VWC_DRY(IIPAR) + REAL*8, INTENT(IN) :: VWC_OPT(IIPAR) + REAL*8, INTENT(IN) :: VWC_SFC(IIPAR) + REAL*8, INTENT(OUT) :: TRN_FSH_VPR_SOI_ATM(IIPAR) + + !---------------- + ! Parameters + !---------------- + + ! Transfer efficiency of vapor from frozen soil to + ! atmosphere CCM:lsm/surphy() [fraction] + REAL*8, PARAMETER :: TRN_FSH_VPR_SOI_ATM_FRZ = 0.01D0 + + !----------------- + ! Local variables + !----------------- + INTEGER :: LON_IDX + + !================================================================= + ! TRN_FSH_VPR_SOI_ATM_GET + !================================================================= + TRN_FSH_VPR_SOI_ATM(:) = 0.0D0 + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! If this is a mobilization candidate ... + IF ( FLG_MBL(LON_IDX) ) THEN + + ! ... and if the soil is above freezing ... + IF ( TPT_SOI(LON_IDX) > TPT_SOI_FRZ ) THEN + + ! Transfer efficiency of cvapor from soil to atmosphere [frac] + ! CCM:lsm/surphys Bon96 p. 59 + TRN_FSH_VPR_SOI_ATM(LON_IDX) = + & MIN ( MAX(VWC_SFC(LON_IDX)-VWC_DRY(LON_IDX), 0.0D0) + & /(VWC_OPT(LON_IDX)-VWC_DRY(LON_IDX)), 1.0D0) + + ELSE + + ! [frc] Bon96 p. 59 + TRN_FSH_VPR_SOI_ATM(LON_IDX) = TRN_FSH_VPR_SOI_ATM_FRZ + + ENDIF + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE TRN_FSH_VPR_SOI_ATM_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE BLM_MBL( FLG_MBL, RGH_MMN, WND_10M, MNO_LNG, WND_FRC ) +! +!****************************************************************************** +! Subroutine BLM_MBL computes the boundary-layer exchange properties, given +! the meteorology at the GEOS-CHEM layer midpoint. This routine is optimized +! for dust source regions: dry, bare, uncovered land. Theory and algorithms: +! Bonan (1996) CCM:lsm/surtem(). Stripped down version, based on adiabatic +! approximation to U*. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [unitless] +! (2 ) RGH_MMN (REAL*8 ) : Roughness length momentum [m ] +! (3 ) WND_10M (REAL*8 ) : 10 m wind speed [m/s ] +! +! Arguments as Output: +! ============================================================================ +! (4 ) MNO_LNG (REAL*8 ) : Monin-Obukhov length [m ] +! (5 ) WND_FRC (REAL*8 ) : Surface friction velocity [m/s ] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also force double-precision with +! "D" exponents. (tdf, bmy, 3/30/04) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : USTAR + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters ! Size parameters + + !----------------- + ! Arguments + !----------------- + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: RGH_MMN(IIPAR) + REAL*8, INTENT(IN) :: WND_10M(IIPAR) + REAL*8, INTENT(OUT) :: MNO_LNG(IIPAR) + REAL*8, INTENT(OUT) :: WND_FRC(IIPAR) + + !----------------- + ! Parameters + !----------------- + + ! Prevents division by zero [unitless] + REAL*8, PARAMETER :: EPS_DBZ = 1.0d-6 + + ! Minimum windspeed used for mobilization [m/s] + REAL*8, PARAMETER :: WND_MIN_MBL = 1.0d0 + + ! Roughness length momentum for erodible surfaces [m] + ! MaB95 p. 16420, GMB98 p. 6205 + REAL*8, PARAMETER :: RGH_MMN_MBL = 100.0d-6 + + ! Reference height for mobilization processes [m] + REAL*8, PARAMETER :: HGT_RFR = 10.0d0 + + !----------------- + ! Local variables + !----------------- + + ! Counting index for lon + INTEGER :: LON_IDX + + ! Denominator of Monin-Obukhov length Bon96 p. 49 + REAL*8 :: MNO_DNM + + ! Surface layer mean wind speed [m/s] + REAL*8 :: WND_MDP_BND(IIPAR) + + ! denominator for wind friction velocity + REAL*8 :: WND_FRC_DENOM + + !================================================================= + ! BLM_MBL begins here! + !================================================================= + + ! Initialize + MNO_LNG(:) = 0.0D0 + WND_FRC(:) = 0.0D0 + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! Surface layer mean wind speed bounded [m/s] + WND_MDP_BND(LON_IDX) = + & MAX(WND_10M(LON_IDX), WND_MIN_MBL) + + ! Friction velocity (adiabatic approximation S&P equ. 16.57, + ! tdf 10/27/2K3 -- Sanity check + IF ( RGH_MMN(LON_IDX) <= 0.0 ) THEN + CALL ERROR_STOP( 'RGH_MMN <= 0.0', + & 'BLM_MBL ("dust_dead_mod.f")' ) + ENDIF + + ! Distinguish between mobilisation candidates and noncandidates + IF ( FLG_MBL(LON_IDX) ) THEN + WND_FRC_DENOM = HGT_RFR / RGH_MMN_MBL ! z = 10 m + ELSE + WND_FRC_DENOM = HGT_RFR / RGH_MMN(LON_IDX) ! z = 10 m + ENDIF + + ! Sanity check + IF ( WND_FRC_DENOM <= 0.0 ) THEN + CALL ERROR_STOP( 'wnd_frc_denom <= 0.0', + & 'BLM_MBL ("dust_dead_mod.f")' ) + ENDIF + + ! Take natural LOG of WND_FRC_DENOM + WND_FRC_DENOM = LOG(WND_FRC_DENOM) + + ! Convert to [m/s] + WND_FRC(LON_IDX) = WND_MDP_BND(LON_IDX) * CST_VON_KRM + & / WND_FRC_DENOM + + ! Denominator of Monin-Obukhov length Bon96 p. 49 + ! Set denominator of Monin-Obukhov length to minimum value + MNO_DNM = EPS_DBZ + + ! Monin-Obukhov length Bon96 p. 49 [m] + MNO_LNG(LON_IDX) = -1.0D0 * (WND_FRC(LON_IDX)**3.0D0) + & /MNO_DNM + + ! Override for non mobilisation candidates + IF ( .NOT. FLG_MBL(LON_IDX) ) THEN + WND_FRC(LON_IDX) = 0.0D0 + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE BLM_MBL + +!------------------------------------------------------------------------------ + + LOGICAL FUNCTION ORO_IS_OCN( ORO_VAL ) +! +!****************************************************************************** +! Function ORO_IS_OCN returns TRUE if a grid box contains more than 50% +! ocean. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) ORO_VAL (REAL*8) : Orography at a grid box (0=ocean; 1=land; 2=ice) +! +! NOTES: +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: ORO_VAL + + !================================================================= + ! ORO_IS_OCN begins here! + !================================================================= + ORO_IS_OCN = ( NINT( ORO_VAL ) == 0 ) + + ! Return to calling program + END FUNCTION ORO_IS_OCN + +!------------------------------------------------------------------------------ + + LOGICAL FUNCTION ORO_IS_LND( ORO_VAL ) +! +!****************************************************************************** +! Function ORO_IS_LND returns TRUE if a grid box contains more than 50% +! land. (tdf, bmy, 3/30/04, 3/1/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) ORO_VAL (REAL*8) : Orography at a grid box (0=ocean; 1=land; 2=ice) +! +! NOTES: +! (1 ) Bug fix: Replaced ": :" with "::" in order to prevent compile error +! on Linux w/ PGI compiler. (bmy, 3/1/05) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: ORO_VAL + + !================================================================= + ! ORO_IS_OCN begins here! + !================================================================= + ORO_IS_LND = ( NINT( ORO_VAL ) == 1 ) + + ! Return to calling program + END FUNCTION ORO_IS_LND + +!------------------------------------------------------------------------------ + + LOGICAL FUNCTION ORO_IS_ICE( ORO_VAL ) +! +!****************************************************************************** +! Function ORO_IS_LND returns TRUE if a grid box contains more than 50% +! ice. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) ORO_VAL (REAL*8) : Orography at a grid box (0=ocean; 1=land; 2=ice) +! +! NOTES: +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: ORO_VAL + + !================================================================= + ! ORO_IS_ICE begins here! + !================================================================= + ORO_IS_ICE = ( NINT( ORO_VAL ) == 2 ) + + ! Return to calling program + END FUNCTION ORO_IS_ICE + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION MNO_STB_CRC_HEAT_UNS_GET( SML_FNC_MMN_UNS_RCP ) +! +!****************************************************************************** +! Function MNO_STB_CRC_HEAT_UNS_GET returns the stability correction factor +! for heat (usually called PSI), given the reciprocal of the Monin-Obukhov +! similarity function (usually called PHI) for momentum in an unstable +! atmosphere. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) sml_fnc_mmn_uns_rcp (REAL*8) : 1/(M-O similarity function) [fraction] +! +! References: +! ============================================================================ +! References are Ary88 p. 167, Bru82 p. 71, SeP97 p. 869, +! Bon96 p. 52, BKL97 p. F1, LaP81 p. 325, LaP82 p. 466 +! Currently this function is BFB with CCM:dom/flxoce() +! +! NOTES: +! (1 ) Updated comments, cosmetic changes (bmy, 3/30/04) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: SML_FNC_MMN_UNS_RCP + + !================================================================= + ! MNO_STB_CRC_HEAT_UNS_GET + !================================================================= + MNO_STB_CRC_HEAT_UNS_GET = 2.0D0 * + & LOG( ( 1.0D0+SML_FNC_MMN_UNS_RCP * SML_FNC_MMN_UNS_RCP) / 2.0D0 ) + + ! Return to calling program + END FUNCTION MNO_STB_CRC_HEAT_UNS_GET + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION MNO_STB_CRC_MMN_UNS_GET( SML_FNC_MMN_UNS_RCP ) +! +!****************************************************************************** +! Function MNO_STB_CRC_MMN_UNS_GET returns the stability correction factor +! for momentum (usually called PSI), given the reciprocal of the +! Monin-Obukhov similarity function (usually called PHI), for momentum in +! an unstable atmosphere. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) SML_FNC_MMN_UNS_RCP (REAL*8) : 1/(M-O similarity function) [fraction] +! +! References: +! ============================================================================ +! References are Ary88 p. 167, Bru82 p. 71, SeP97 p. 869, +! Bon96 p. 52, BKL97 p. F1, LaP81 p. 325, LaP82 p. 466 +! Currently this function is BFB with CCM:dom/flxoce() +! +! NOTES: +! (1 ) Updated comments, cosmetic changes (bmy, 3/30/04) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: SML_FNC_MMN_UNS_RCP + + !================================================================= + ! MNO_STB_CRC_MMN_UNS_GET begins here! + !================================================================= + MNO_STB_CRC_MMN_UNS_GET = + & LOG((1.0D0+SML_FNC_MMN_UNS_RCP*(2.0D0+SML_FNC_MMN_UNS_RCP)) + & *(1.0D0+SML_FNC_MMN_UNS_RCP*SML_FNC_MMN_UNS_RCP)/8.0D0) + & -2.0D0*ATAN(SML_FNC_MMN_UNS_RCP)+1.571D0 + + ! Return to calling program + END FUNCTION MNO_STB_CRC_MMN_UNS_GET + +!------------------------------------------------------------------------------ + + REAL*8 FUNCTION XCH_CFF_MMN_OCN_NTR_GET( WND_10M_NTR ) +! +!****************************************************************************** +! Function XCH_CFF_MMN_OCN_NTR_GET returns the Neutral 10m drag coefficient +! over oceans. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) WIND_10M_NTR (REAL*8) : Wind speed @ 10 m[m/s] +! +! References: +! ============================================================================ +! LaP82 CCM:dom/flxoce(), NOS97 p. I2 +! +! NOTES: +! (1 ) Updated comments, cosmetic changes (bmy, 3/30/04) +!****************************************************************************** +! + ! Arguments + REAL*8, INTENT(IN) :: WND_10M_NTR + + !================================================================= + ! XCH_CFF_MMN_OCN_NTR_GET begins here! + !================================================================= + XCH_CFF_MMN_OCN_NTR_GET = 0.0027D0 / WND_10M_NTR + 0.000142D0 + & + 0.0000764D0 * WND_10M_NTR + + ! REturn to calling program + END FUNCTION XCH_CFF_MMN_OCN_NTR_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE RGH_MMN_GET( ORO, RGH_MMN, SFC_TYP, SNW_FRC, WND_10M ) +! +!****************************************************************************** +! Subroutine RGH_MMN_GET sets the roughness length. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) ORO (INTEGER) : Orography (0=ocean; 1=land; 2=ice) [unitless] +! (3 ) SFC_TYP (REAL*8 ) : LSM surface type (0..28) [unitless] +! (4 ) SNW_FRC (REAL*8 ) : Fraction of surface covered by snow [fraction] +! (5 ) WND_10M (REAL*8 ) : 10 m wind speed [m/s ] +! +! Arguments as Output: +! ============================================================================ +! (2 ) RGH_MMN (REAL*8 ) : Roughness length momentu [m ] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents (bmy, 3/30/04) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters ! Size parameters + + !----------------- + ! Arguments + !----------------- + INTEGER, INTENT(IN) :: SFC_TYP(IIPAR) + REAL*8, INTENT(IN) :: ORO(IIPAR) + REAL*8, INTENT(IN) :: SNW_FRC(IIPAR) + REAL*8, INTENT(IN) :: WND_10M(IIPAR) + REAL*8, INTENT(OUT) :: RGH_MMN(IIPAR) + + !----------------- + ! Parameters + !----------------- + + ! Roughness length over frozen lakes Bon96 p. 59 [m] + REAL*8, PARAMETER :: RGH_MMN_ICE_LAK = 0.04d0 + + ! Roughness length over ice, bare ground, wetlands Bon96 p. 59 [m] + REAL*8, PARAMETER :: RGH_MMN_ICE_LND = 0.05d0 + + ! Roughness length over sea ice BKL97 p. F-3 [m] + REAL*8, PARAMETER :: RGH_MMN_ICE_OCN = 0.0005d0 + + ! Roughness length over unfrozen lakes Bon96 p. 59 [m] + REAL*8, PARAMETER :: RGH_MMN_LAK_WRM = 0.001d0 + + ! Roughness length over snow Bon96 p. 59 CCM:lsm/snoconi.F ! [m] + REAL*8, PARAMETER :: RGH_MMN_SNW = 0.04d0 + + ! Minimum windspeed for momentum exchange + REAL*8, PARAMETER :: WND_MIN_DPS = 1.0d0 + + !----------------- + ! Local variables + !----------------- + + ! [idx] Longitude index array (sea ice) + INTEGER :: ICE_IDX(IIPAR) + + ! [nbr] Number of sea ice points + INTEGER :: ICE_NBR + + ! [Idx] Counting index + INTEGER :: IDX_IDX + + ! [idx] Longitude index array (land) + INTEGER :: LND_IDX(IIPAR) + + ! [nbr] Number of land points + INTEGER :: LND_NBR + + ! [idx] Counting index + INTEGER :: LON_IDX + + ! [idx] Longitude index array (ocean) + INTEGER :: OCN_IDX(IIPAR) + + ! [nbr] Number of ocean points + INTEGER :: OCN_NBR + + ! [idx] Plant type index + INTEGER :: PLN_TYP_IDX + + ! [idx] Surface type index + INTEGER :: SFC_TYP_IDX + + ! [idx] Surface sub-gridscale index + INTEGER :: SGS_IDX + + ! [m] Roughness length of current sub-gridscale + REAL*8 :: RLM_CRR + + ! [m s-1] Bounded wind speed at 10 m + REAL*8 :: WND_10M_BND + + ! [frc] Neutral 10 m drag coefficient over ocean + REAL*8 :: XCH_CFF_MMN_OCN_NTR + + ! Momentum roughness length [m] + REAL*8 :: Z0MVT(MVT) = (/ 0.94d0, 0.77d0, 2.62d0, 1.10d0, 0.99d0, + & 0.06d0, 0.06d0, 0.06d0, 0.06d0, 0.06d0, + & 0.06d0, 0.06d0, 0.06d0, 0.00d0 /) + + ! Displacement height (fn of plant type) + REAL*8 :: ZPDVT(MVT) = (/ 11.39d0, 9.38d0, 23.45d0, 13.40d0, + & 12.06d0, 0.34d0, 0.34d0, 0.34d0, + & 0.34d0, 0.34d0, 0.34d0, 0.34d0, + & 0.34d0, 0.00d0 /) + + !================================================================= + ! RGH_MMN_SET begins here + !================================================================= + RGH_MMN(:) = 0.0D0 + + ! Count ocean grid boxes + OCN_NBR = 0 + DO LON_IDX = 1, IIPAR + IF ( ORO_IS_OCN( ORO(LON_IDX) ) ) THEN + OCN_NBR = OCN_NBR + 1 + OCN_IDX(OCN_NBR) = LON_IDX + ENDIF + ENDDO + + ! Count ice grid boxes + ICE_NBR = 0 + DO LON_IDX = 1, IIPAR + IF ( ORO_IS_ICE( ORO(LON_IDX) ) ) THEN + ICE_NBR = ICE_NBR+1 + ICE_IDX(ICE_NBR) = LON_IDX + ENDIF + ENDDO + + ! Count land grid boxes + LND_NBR = 0 + DO LON_IDX = 1, IIPAR + IF ( ORO_IS_LND( ORO(LON_IDX) ) ) THEN + LND_NBR = LND_NBR + 1 + LND_IDX(LND_NBR) = LON_IDX + ENDIF + ENDDO + + !================================================================= + ! Ocean points + !================================================================= + DO IDX_IDX = 1, OCN_NBR + + ! Longitude index of the ocean point + LON_IDX = OCN_IDX(IDX_IDX) + + ! Convert wind speed to roughness length over ocean [m/s] + WND_10M_BND = MAX( WND_MIN_DPS, WND_10M(LON_IDX) ) + + !Approximation: neutral 10 m wind speed unavailable, + ! use 10 m wind speed [fraction] + XCH_CFF_MMN_OCN_NTR = XCH_CFF_MMN_OCN_NTR_GET(WND_10M_BND) + + ! BKL97 p. F-4, LaP81 p. 327 (14) Ocean Points [m] + RGH_MMN(LON_IDX)=10.0D0 + & * EXP(-CST_VON_KRM / SQRT(XCH_CFF_MMN_OCN_NTR)) + ENDDO + + !================================================================= + ! Sea ice points + !================================================================= + DO IDX_IDX = 1, ICE_NBR + LON_IDX = ICE_IDX(IDX_IDX) + RGH_MMN(LON_IDX) = SNW_FRC(LON_IDX) * RGH_MMN_SNW + & +(1.0D0-SNW_FRC(LON_IDX)) * RGH_MMN_ICE_OCN ! [m] Bon96 p. 59 + ENDDO + + !================================================================= + ! Land points + !================================================================= + DO IDX_IDX = 1, LND_NBR + + ! Longitude + LON_IDX = LND_IDX(IDX_IDX) + + ! Store surface blend for current gridpoint, sfc_typ(lon_idx) + SFC_TYP_IDX = SFC_TYP(LON_IDX) + + ! Inland lakes + IF ( SFC_TYP_IDX == 0 ) THEN + + !fxm: Add temperature input and so ability to discriminate warm + ! from frozen lakes here [m] Bon96 p. 59 + RGH_MMN(LON_IDX) = RGH_MMN_LAK_WRM + + ! Land ice + ELSE IF ( SFC_TYP_IDX == 1 ) THEN + + ! [m] Bon96 p. 59 + RGH_MMN(LON_IDX) = SNW_FRC(LON_IDX)*RGH_MMN_SNW + & + (1.0D0-SNW_FRC(LON_IDX))*RGH_MMN_ICE_LND + + + ! Normal land + ELSE + DO SGS_IDX = 1, 3 + + ! Bare ground is pln_typ=14, ocean is pln_typ=0 + PLN_TYP_IDX = PLN_TYP(SFC_TYP_IDX,SGS_IDX) + + ! Bare ground + IF ( PLN_TYP_IDX == 14 ) THEN + + ! Bon96 p. 59 (glacial ice is same as bare ground) + RLM_CRR = SNW_FRC(LON_IDX) * RGH_MMN_SNW + & + (1.0D0-SNW_FRC(LON_IDX)) * RGH_MMN_ICE_LND ! [m] + + ! Regular plant type + ELSE IF ( PLN_TYP_IDX > 0 ) THEN + RLM_CRR = SNW_FRC(LON_IDX) * RGH_MMN_SNW + & + (1.0D0-SNW_FRC(LON_IDX)) * Z0MVT(PLN_TYP_IDX) + ! [m] Bon96 p. 59 + + ! Presumably ocean snuck through + ELSE + CALL ERROR_STOP( 'pln_typ_idx == 0', + & 'RGH_MMN_GET ("dead_dust_mod.f")' ) + ENDIF ! endif + + ! Roughness length for normal land + RGH_MMN(LON_IDX) = RGH_MMN(LON_IDX) ! [m] + & + PLN_FRC(SFC_TYP_IDX,SGS_IDX) ! [frc] + & * RLM_CRR ! [m] + + ENDDO + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE RGH_MMN_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE SNW_FRC_GET( SNW_HGT_LQD, SNW_FRC ) +! +!****************************************************************************** +! Subroutine SNW_FRC_GET converts equivalent liquid water snow depth to +! fractional snow cover. Uses the snow thickness -> fraction algorithm of +! Bon96. (tdf bmy, 3/30/04) +! +! Arguments as Input: +! =========================================================================== +! (1 ) snw_hgt_lqd (REAL*8) : Equivalent liquid water snow depth [m] +! +! Arguments as Output: +! =========================================================================== +! (2 ) snw_frc (REAL*8 ) : Fraction of surface covered by snow +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents. (bmy, 3/30/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + !---------------- + ! Arguments + !---------------- + REAL*8, INTENT(IN) :: SNW_HGT_LQD(IIPAR) + REAL*8, INTENT(OUT) :: SNW_FRC(IIPAR) + + !---------------- + ! Parameters + !---------------- + + ! Note disparity in bulk snow density between CCM and LSM + ! WiW80 p. 2724, 2725 has some discussion of bulk snow density + ! + ! Bulk density of snow [kg m-3] + REAL*8, PARAMETER :: DNS_H2O_SNW_GND_LSM = 250.0D0 + + ! Standard bulk density of snow on ground [kg m-3] + REAL*8, PARAMETER :: DNS_H2O_SNW_GND_STD = 100.0D0 + + ! Geometric snow thickness for 100% coverage ! [m] + REAL*8, PARAMETER :: SNW_HGT_THR = 0.05D0 + + ! Liquid water density! [kg/m3] + REAL*8, PARAMETER :: DNS_H2O_LQD_STD = 1000.0D0 + + !----------------- + ! Local variables + !----------------- + + ! [idx] Counting index for lon + INTEGER :: LON_IDX + + ! [m] Geometric bulk thickness of snow + REAL*8 :: SNW_HGT(IIPAR) + + ! Conversion factor from liquid water depth + ! to geometric snow thickness [fraction] + REAL*8 :: HGT_LQD_SNW_CNV + + !================================================================= + ! SNW_FRC_GET begins here! + !================================================================= + + ! Conversion factor from liquid water depth to + ! geometric snow thickness [fraction] + HGT_LQD_SNW_CNV = DNS_H2O_LQD_STD + & / DNS_H2O_SNW_GND_STD + + ! Fractional snow cover + DO LON_IDX = 1, IIPAR + + ! Snow height [m] + SNW_HGT(LON_IDX) = SNW_HGT_LQD(LON_IDX) + & * HGT_LQD_SNW_CNV + + ! Snow fraction + ! NB: CCM and LSM seem to disagree on this + SNW_FRC(LON_IDX) = MIN(SNW_HGT(LON_IDX)/SNW_HGT_THR, 1.0D0) + ENDDO + + ! Return to calling program + END SUBROUTINE SNW_FRC_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE WND_RFR_GET( FLG_ORO, HGT_MDP, HGT_RFR, HGT_ZPD, + & MNO_LNG, WND_FRC, WND_MDP, WND_MIN, + & WND_RFR ) +! +!****************************************************************************** +! Subroutine WND_RFR_GET interpolates wind speed at given height to wind +! speed at reference height. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! =========================================================================== +! (1 ) FLG_ORO (LOGICAL) : Orography flag (mobilization flag) [flag] +! (2 ) HGT_MDP (REAL*8 ) : Midpoint height above surface [m ] +! (3 ) HGT_RFR (REAL*8 ) : Reference height [m ] +! (4 ) HGT_ZPD (REAL*8 ) : Zero plane displacement [m ] +! (5 ) MNO_LNG (REAL*8 ) : Monin-Obukhov length [m ] +! (6 ) WND_FRC (REAL*8 ) : Surface friction velocity [m/s ] +! (7 ) WND_MDP (REAL*8 ) : Surface layer mean wind speed [m/s ] +! (8 ) WND_MIN (REAL*8 ) : Minimum windspeed [m/s ] +! +! Arguments as Output: +! =========================================================================== +! (9 ) WND_RFR (REAL*8 ) : Wind speed at reference height [m/s ] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents. (bmy, 3/30/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! IIPAR + + !------------------ + ! Arguments + !------------------ + LOGICAL, INTENT(IN) :: FLG_ORO(IIPAR) + REAL*8, INTENT(IN) :: HGT_MDP(IIPAR) + REAL*8, INTENT(IN) :: HGT_RFR + REAL*8, INTENT(IN) :: HGT_ZPD(IIPAR) + REAL*8, INTENT(IN) :: MNO_LNG(IIPAR) + REAL*8, INTENT(IN) :: WND_FRC(IIPAR) + REAL*8, INTENT(IN) :: WND_MDP(IIPAR) + REAL*8, INTENT(IN) :: WND_MIN + REAL*8, INTENT(OUT) :: WND_RFR(IIPAR) + + !------------------ + ! Parameters + !------------------ + + ! Named index for lower (target) hght + INTEGER, PARAMETER :: RFR_HGT_IDX=1 + + ! Named index for upper (known) hght + INTEGER, PARAMETER :: GCM_HGT_IDX=2 + + !------------------ + ! Local variables + !------------------ + + ! [idx] Counting index + INTEGER :: IDX_IDX + + ! [idx] Counting index for lon + INTEGER :: LON_IDX + + ! Stability computation loop index + INTEGER :: LVL_IDX + + ! Valid indices + INTEGER :: VLD_IDX(IIPAR) + + ! [nbr] Number of valid indices + INTEGER :: VLD_NBR + + ! [frc] Monin-Obukhov stability correction momentum + REAL*8 :: MNO_STB_CRC_MMN(IIPAR,2) + + ! [frc] Monin-Obukhov stability parameter + REAL*8 :: MNO_STB_PRM(IIPAR,2) + + ! [frc] Reciprocal of similarity function + ! for momentum, unstable atmosphere + REAL*8 :: SML_FNC_MMN_UNS_RCP + + ! Term in stability correction computation + REAL*8 :: TMP2 + + ! Term in stability correction computation + REAL*8 :: TMP3 + + ! Term in stability correction computation + REAL*8 :: TMP4 + + ! [frc] Wind correction factor + REAL*8 :: WND_CRC_FCT(IIPAR) + + ! [m-1] Reciprocal of reference height + REAL*8 :: HGT_RFR_RCP + + !================================================================= + ! WND_RFR_GET begins here! + !================================================================= + + HGT_RFR_RCP = 1.0D0 / HGT_RFR ! [m-1] + WND_RFR = WND_MIN ! [m s-1] + + ! Compute horizontal wind speed at reference height + DO LON_IDX = 1, IIPAR + IF (FLG_ORO(LON_IDX) .AND. HGT_ZPD(LON_IDX) < HGT_RFR) THEN + + ! Code uses notation of Bon96 p. 50, where lvl_idx=1 + ! is 10 m ref. hgt, lvl_idx=2 is atm. hgt + MNO_STB_PRM(LON_IDX,RFR_HGT_IDX) = + & MIN((HGT_RFR-HGT_ZPD(LON_IDX)) + & /MNO_LNG(LON_IDX),1.0D0) ! [frc] + + MNO_STB_PRM(LON_IDX,GCM_HGT_IDX) = + & MIN((HGT_MDP(LON_IDX)-HGT_ZPD(LON_IDX)) + & /MNO_LNG(LON_IDX),1.0D0) ! [frc] + + DO LVL_IDX = 1, 2 + IF (MNO_STB_PRM(LON_IDX,LVL_IDX) < 0.0D0) THEN + SML_FNC_MMN_UNS_RCP = (1.0D0 - 16.0D0 + & * MNO_STB_PRM(LON_IDX,LVL_IDX))**0.25D0 + TMP2 = LOG((1.0D0 + SML_FNC_MMN_UNS_RCP + & * SML_FNC_MMN_UNS_RCP)/2.0D0) + TMP3 = LOG((1.0D0 + SML_FNC_MMN_UNS_RCP)/2.0D0) + MNO_STB_CRC_MMN(LON_IDX,LVL_IDX) = + & 2.0D0 * TMP3 + TMP2 - 2.0D0 + & * ATAN(SML_FNC_MMN_UNS_RCP) + 1.5707963 + ELSE ! not stable + MNO_STB_CRC_MMN(LON_IDX,LVL_IDX) = -5.0D0 + & * MNO_STB_PRM(LON_IDX,LVL_IDX) + ENDIF ! stable + ENDDO ! end loop over lvl_idx + + TMP4 = LOG( (HGT_MDP(LON_IDX)-HGT_ZPD(LON_IDX)) + & / (HGT_RFR-HGT_ZPD(LON_IDX)) ) + + ! Correct neutral stability assumption + WND_CRC_FCT(LON_IDX) = TMP4 + & - MNO_STB_CRC_MMN(LON_IDX,GCM_HGT_IDX) + & + MNO_STB_CRC_MMN(LON_IDX,RFR_HGT_IDX) ! [frc] + WND_RFR(LON_IDX) = WND_MDP(LON_IDX)-WND_FRC(LON_IDX) + & * CST_VON_KRM_RCP * WND_CRC_FCT(LON_IDX) ! [m s-1] + WND_RFR(LON_IDX) = MAX(WND_RFR(LON_IDX),WND_MIN) ! [m s-1] + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE WND_RFR_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE WND_FRC_THR_SLT_GET( FLG_MBL, DNS_MDP, WND_FRC_THR_SLT) +! +!****************************************************************************** +! Subroutine WND_FRC_THR_SLT_GET ccmputes the dry threshold friction velocity +! for saltation -- See Zender et al. expression (1) (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! =========================================================================== +! (1 ) FLG_MBL (LOGICAL) : mobilisation flag +! (2 ) DNS_MDP (REAL*8 ) : Midlayer density [kg/m3] +! +! Arguments as Output: +! =========================================================================== +! (3 ) WND_FRC_THR_SLT (REAL*8 ) : Threshold friction velocity +! for saltation [m/s] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now force double-precision +! with "D" exponents. (bmy, 3/30/04) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters ! IIPAR + + !---------------- + ! Arguments + !---------------- + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: DNS_MDP(IIPAR) + REAL*8, INTENT(OUT) :: WND_FRC_THR_SLT(IIPAR) + + !----------------- + ! Parameters + !----------------- + + ! [m] Optimal diameter for saltation, + ! IvW82 p. 117 Fgr. 8, Pye87 p. 31, MBA97 p. 4388, SRL96 (2) + REAL*8, PARAMETER :: DMT_SLT_OPT = 75.0d-6 + + ! [kg m-3] Density of optimal saltation particles, + ! MBA97 p. 4388 friction velocity for saltation + REAL*8, PARAMETER :: DNS_SLT = 2650.0d0 + + !----------------- + ! Local variables + !----------------- + + ! [idx] Longitude Counting Index + INTEGER :: LON_IDX + + ! Threshold friction Reynolds number + ! approximation for optimal size [frc] + REAL*8 :: RYN_NBR + + ! Density ratio factor for saltation calculation + REAL*8 :: DNS_FCT + + ! Interparticle cohesive forces factor for saltation calculation + REAL*8 :: ALPHA, BETA, GAMMA, TMP1 + + !================================================================= + ! WND_FRC_THR_SLT_GET begins here! + !================================================================= + + ! Initialize some variables + ! MaB95 pzn. for Re*t(D_opt) circumvents iterative solution + ! [frc] "B" MaB95 p. 16417 (5) + + ! [m/s] Threshold velocity + WND_FRC_THR_SLT(:) = 0.0D0 + + ! Threshold friction Reynolds number approximation for optimal size + RYN_NBR = 0.38D0 + 1331.0D0 + & * (100.0D0*DMT_SLT_OPT)**1.56D0 + + ! tdf NB conversion of Dp to [cm] + ! Given Re*t(D_opt), compute time independent factors contributing + ! to u*t. IvW82 p. 115 (6) MaB95 p. 16417 (4) Interparticle cohesive + ! forces. see Zender et al., Equ. (1). + + ! tdf introduced beta [fraction] + BETA = 1.0D0+6.0D-07 / (DNS_SLT*GRV_SFC*(DMT_SLT_OPT**2.5D0)) + + ! IvW82 p. 115 (6) MaB95 p. 16417 (4) + DNS_FCT = DNS_SLT * GRV_SFC * DMT_SLT_OPT + + ! Error check + IF ( RYN_NBR < 0.03D0 ) THEN + CALL ERROR_STOP( 'RYN_NBR < 0.03', + & 'WND_FRC_THR_SLT_GET ("dust_dead_mod.f")' ) + + ELSE IF ( RYN_NBR < 10.0D0 ) THEN + + ! IvW82 p. 114 (3), MaB95 p. 16417 (6) + ! tdf introduced gamma [fraction] + GAMMA = -1.0D0 + 1.928D0 * (RYN_NBR**0.0922D0) + TMP1 = 0.129D0*0.129D0 * BETA / GAMMA + + ELSE + + ! ryn_nbr > 10.0D0 + ! IvW82 p. 114 (3), MaB95 p. 16417 (7) + ! tdf introduced gamma [fraction] + GAMMA = 1.0D0-0.0858D0 * EXP(-0.0617D0*(RYN_NBR-10.0D0)) + TMP1 = 0.12D0*0.12D0 * BETA * GAMMA * GAMMA + + ENDIF + + DO LON_IDX = 1, IIPAR + + ! Threshold friction velocity for saltation dry ground + ! tdf introduced alpha + ALPHA = DNS_FCT / DNS_MDP(LON_IDX) + + ! Added mobilisation constraint + IF ( FLG_MBL(LON_IDX) ) THEN + WND_FRC_THR_SLT(LON_IDX) = SQRT(TMP1) * SQRT(ALPHA) ! [m s-1] + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE WND_FRC_THR_SLT_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE WND_RFR_THR_SLT_GET( WND_FRC, WND_FRC_THR_SLT, + & WND_MDP, WND_RFR, + & WND_RFR_THR_SLT ) +! +!****************************************************************************** +! Subroutine WND_RFR_THR_SLT_GET computes the threshold horizontal wind +! speed at reference height for saltation. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) wnd_frc (REAL*8) : Surface friction velocity [m/s] +! (2 ) wnd_frc_thr_slt (REAL*8) : Threshold friction vel. for saltation [m/s] +! (3 ) wnd_mdp (REAL*8) : Surface layer mean wind speed [m/s] +! (4 ) wnd_rfr (REAL*8) : Wind speed at reference height [m/s] +! +! Arguments as Output: +! ============================================================================ +! (5 ) wnd_rfr_thr_slt (REAL*8) : Threshold 10m wind speed for saltation [m/s] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Arguments + REAL*8, INTENT(IN) :: WND_FRC(IIPAR) + REAL*8, INTENT(IN) :: WND_FRC_THR_SLT(IIPAR) + REAL*8, INTENT(IN) :: WND_MDP(IIPAR) + REAL*8, INTENT(IN) :: WND_RFR(IIPAR) + REAL*8, INTENT(OUT) :: WND_RFR_THR_SLT(IIPAR) + + ! Local variables + INTEGER :: I + + !================================================================= + ! WND_RFR_THR_SLT_GET begins here + !================================================================= + DO I = 1, IIPAR + + ! A more complicated procedure would recompute mno_lng for + ! wnd_frc_thr, and then integrate vertically from rgh_mmn+hgt_zpd + ! to hgt_rfr. + ! + ! wnd_crc_fct is (1/k)*[ln(z-D)/z0 - psi(zeta2) + psi(zeta1)] + WND_RFR_THR_SLT(I) = WND_FRC_THR_SLT(I) + & * WND_RFR(I) / WND_FRC(I) + + ENDDO + + ! Return to calling program + END SUBROUTINE WND_RFR_THR_SLT_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE VWC2GWC( FLG_MBL, GWC_SFC, VWC_SAT, VWC_SFC ) +! +!****************************************************************************** +! Subroutine VWC2GWC converts volumetric water content to gravimetric water +! content -- assigned only for mobilisation candidates. (tdf, bmy, 3/30/04) +! +! Arguments as Input: +! =========================================================================== +! (1 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [flag] +! (3 ) VWC_SAT (REAL*8 ) : Saturated VWC (sand-dependent) [m3/m3] +! (4 ) VWC_SFC (REAL*8 ) : Volumetric water content! [m3/m3 +! +! Arguments as Output: +! =========================================================================== +! (2 ) gwc_sfc (REAL*8 ) : Gravimetric water content [kg/kg] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 3/30/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + !---------------- + ! Arguments + !---------------- + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: VWC_SAT(IIPAR) + REAL*8, INTENT(IN) :: VWC_SFC(IIPAR) + REAL*8, INTENT(OUT) :: GWC_SFC(IIPAR) + + !---------------- + ! Parameters + !---------------- + + ! Dry density of soil ! particles (excluding pores) [kg/m3] + REAL*8, PARAMETER :: DNS_PRT_SFC = 2650.0d0 + + ! liq. H2O density [kg/m3] + REAL*8, PARAMETER :: DNS_H2O_LQD_STD = 1000.0d0 + + !----------------- + ! Local variables + !----------------- + + ! Longitude index + INTEGER :: LON_IDX + + ! [kg m-3] Bulk density of dry surface soil + REAL*8 :: DNS_BLK_DRY(IIPAR) + + !================================================================= + ! VWC2GWC begins here! + !================================================================= + GWC_SFC(:) = 0.0D0 + DNS_BLK_DRY(:) = 0.0D0 + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! If this is a mobilization candidate then... + IF ( FLG_MBL(LON_IDX) ) THEN + + ! Assume volume of air pores when dry equals saturated VWC + ! This implies air pores are completely filled by water in + ! saturated soil + + ! Bulk density of dry surface soil [kg m-3] + DNS_BLK_DRY(LON_IDX) = DNS_PRT_SFC + & * ( 1.0d0 - VWC_SAT(LON_IDX) ) + + ! Gravimetric water content [ kg kg-1] + GWC_SFC(LON_IDX) = VWC_SFC(LON_IDX) + & * DNS_H2O_LQD_STD + & / DNS_BLK_DRY(LON_IDX) + + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE VWC2GWC + +!------------------------------------------------------------------------------ + + SUBROUTINE FRC_THR_NCR_WTR_GET( FLG_MBL, FRC_THR_NCR_WTR, + & MSS_FRC_CLY, GWC_SFC ) +! +!****************************************************************************** +! Subroutine FRC_THR_NCR_WTR_GET computes the factor by which soil moisture +! increases threshold friction velocity. This parameterization is based on +! FMB99. Zender et al., exp. (5). (tdf, bmy, 4/5/04) +! +! Arguments as Input: +! =========================================================================== +! (1 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [flags ] +! (3 ) MSS_FRC_CLY (REAL*8 ) : Mass fraction of clay [fraction] +! (4 ) GWC_SFC (REAL*8 ) : Gravimetric water content [kg/kg ] +! +! Arguments as Output: +! =========================================================================== +! (2 ) FRC_THR_NCR_WTR (REAL*8 ) : Factor by which moisture increases +! threshold friction velocity [fraction] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_CLY(IIPAR) + REAL*8, INTENT(IN) :: GWC_SFC(IIPAR) + REAL*8, INTENT(OUT) :: FRC_THR_NCR_WTR(IIPAR) + + ! local variables + INTEGER :: LON_IDX ! [idx] Counting index + REAL*8 :: GWC_THR(IIPAR) ! [kg/kg] Threshold GWC + + !================================================================= + ! FRC_THR_NCR_WTR_GET begins here! + !================================================================= + + ! Initialize + frc_thr_ncr_wtr(:) = 1.0D0 + gwc_thr(:) = 0.0D0 + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! If this is a candidate for mobilization... + IF ( FLG_MBL(LON_IDX) ) THEN + + !=========================================================== + ! Adjust threshold velocity for inhibition by moisture + ! frc_thr_ncr_wtr(lon_idx)=exp(22.7D0*vwc_sfc(lon_idx)) + ! [frc] SRL96 + ! + ! Compute threshold soil moisture based on clay content + ! GWC_THR=MSS_FRC_CLY*(0.17D0+0.14D0*MSS_FRC_CLY) [m3/m3] + ! FMB99 p. 155 (14) + ! + ! 19991105 remove factor of mss_frc_cly from gwc_thr to + ! improve large scale behavior. + !=========================================================== + + ! [m3 m-3] + GWC_THR(LON_IDX) = 0.17D0 + 0.14D0 * MSS_FRC_CLY(LON_IDX) + + IF ( GWC_SFC(LON_IDX) > GWC_THR(LON_IDX) ) + & FRC_THR_NCR_WTR(LON_IDX) = SQRT(1.0D0+1.21D0 + & * (100.0D0 * (GWC_SFC(LON_IDX)-GWC_THR(LON_IDX))) + & ** 0.68D0) ! [frc] FMB99 p. 155 (15) + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE FRC_THR_NCR_WTR_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE FRC_THR_NCR_DRG_GET( FRC_THR_NCR_DRG, FLG_MBL, + & Z0M, ZS0M ) +! +!****************************************************************************** +! Subroutine FRC_THR_NCR_DRG_GET computes factor by which surface roughness +! increases threshold friction velocity. Zender et al., expression (3) +! This parameterization is based on MaB95 and GMB98. (tdf, bmy, 4/5/04) +! +! Arguments as Input: +! =========================================================================== +! (2 ) FLG_MBL (LOGICAL) : Mobilization candidate flag +! (3 ) Z0M (REAL*8 ) : Roughness length momentum +! : for erodible surfaces [m] +! (4 ) ZS0M (REAL*8 ) : Smooth roughness length [m] +! +! Arguments as Output: +! =========================================================================== +! (1 ) FRC_THR_NCR_DRG (REAL*8 ) : Factor by which surface roughness +! increases threshold fric. velocity [frac] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters ! Size parameters + + !----------------- + ! Arguments + !----------------- + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: Z0M + REAL*8, INTENT(IN) :: ZS0M + REAL*8, INTENT(OUT) :: FRC_THR_NCR_DRG(IIPAR) + + !----------------- + ! Local variables + !----------------- + + ! [idx] Counting index + integer lon_idx + + ! [frc] Efficient fraction of wind friction + real*8 Feff + + ! [frc] Reciprocal of Feff + real*8 Feff_rcp + + !================================================================= + ! FRC_THR_NCR_DRG_GET begins here! + !================================================================= + FRC_THR_NCR_DRG(:) = 1.0D0 + + ! Adjust threshold velocity for inhibition by roughness elements + ! Zender et al. Equ. (3), fd. + + ! [frc] MaB95 p. 16420, GMB98 p. 6207 + FEFF = 1.0D0 - LOG( Z0M /ZS0M ) + & / LOG( 0.35D0*( (0.1D0/ZS0M)**0.8D0) ) + + ! Error check + if ( FEFF <= 0.0D0 .OR. FEFF > 1.0D0 ) THEN + CALL ERROR_STOP( 'Feff out of range!', + & 'FRC_THR_NCR_DRG_GET ("dust_dead_mod.f")' ) + + ENDIF + + ! Reciprocal of FEFF [fraction] + FEFF_RCP = 1.0D0 / FEFF + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! If this is a mobilization candidate... + IF ( FLG_MBL(LON_IDX) ) THEN + + ! Save into FRC_THR_NCR_DRG + FRC_THR_NCR_DRG(LON_IDX) = FEFF_RCP + + ! fxm: 19991012 + ! Set frc_thr_ncr_drg=1.0, equivalent to assuming mobilization + ! takes place at smooth roughness length + FRC_THR_NCR_DRG(LON_IDX) = 1.0D0 + + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE FRC_THR_NCR_DRG_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE WND_FRC_SLT_GET( FLG_MBL, WND_FRC, WND_FRC_SLT, + & WND_RFR, WND_RFR_THR_SLT ) +! +!****************************************************************************** +! Subroutine WND_FRC_SLT_GET computes the saltating friction velocity. +! Saltation increases friction speed by roughening surface, AKA "Owen's +! effect". This acts as a positive feedback to the friction speed. GMB98 +! parameterized this feedback in terms of 10 m windspeeds, Zender et al. +! equ. (4). (tdf, bmy, 4/5/04, 1/25/07) +! +! Arguments as Input: +! =========================================================================== +! (1 ) FLG_MBL (LOGICAL) : Mobilization candidate flag +! (2 ) WND_FRC (REAL*8 ) : Surface friction velocity [m/s] +! (4 ) WND_RFR (REAL*8 ) : Wind speed at reference height [m/s] +! (5 ) WND_RFR_THR_SLT (REAL*8 ) : Thresh. 10m wind speed for saltation [m/s] +! +! Arguments as Output: +! =========================================================================== +! (3 ) WND_FRC_SLT (REAL*8 ) : Saltating friction velocity [m/s] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +! (2 ) Now eliminate Owen effect (tdf, bmy, 1/25/07) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! Size parameters + + !------------------- + ! Arguments + !------------------- + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: WND_FRC(IIPAR) + REAL*8, INTENT(IN) :: WND_RFR(IIPAR) + REAL*8, INTENT(IN) :: WND_RFR_THR_SLT(IIPAR) + REAL*8, INTENT(OUT) :: WND_FRC_SLT(IIPAR) + + !------------------- + ! Local variables + !------------------- + + ! [idx] Counting index + INTEGER :: LON_IDX + + !--------------------------------------------------------------------- + ! Prior to 1/25/07: + ! Eliminate Owen effect, so comment out this code (tdf, bmy, 1/25/07) + ! + ! %%%%% DO NOT DELETE -- LEAVE THIS CODE COMMENTED OUT %%%%% + ! + !! [m/s] Reference windspeed excess over threshold + !REAL*8 :: WND_RFR_DLT + ! + !! [m/s] Friction velocity increase from saltation + !REAL*8 :: WND_FRC_SLT_DLT + !--------------------------------------------------------------------- + + !================================================================= + ! WND_FRC_SLT_GET begins here! + !================================================================= + + ! [m/s] Saltating friction velocity + WND_FRC_SLT(:) = WND_FRC(:) + +!------------------------------------------------------------------------------ +! Prior to 1/25/07: +! Eliminate the Owen effect. Note that the more computationally +! efficient way to do this is to just comment out the entire IF block. +! (tdf, bmy, 1/25/07) +! +! %%%%% DO NOT DELETE -- LEAVE THIS CODE COMMENTED OUT %%%%% +! +! ! Loop over longitudes +! DO LON_IDX = 1, IIPAR +! +! ! If this is a mobilization candidate, then only +! ! only apply Owen effect only when Uref > Ureft (tdf 4/5/04) +! IF ( FLG_MBL(LON_IDX) .AND. +! & WND_RFR(LON_IDX) >= WND_RFR_THR_SLT(LON_IDX) ) THEN +! +! !================================================================== +! ! Saltation roughens the boundary layer, AKA "Owen's effect" +! ! GMB98 p. 6206 Fig. 1 shows observed/computed u* dependence +! ! on observed U(1 m). GMB98 p. 6209 (12) has u* in cm s-1 and +! ! U, Ut in m s-1, personal communication, D. Gillette, 19990529 +! ! With everything in MKS, the 0.3 coefficient in GMB98 (12) +! ! becomes 0.003. Increase in friction velocity due to saltation +! ! varies as square of difference between reference wind speed +! ! and reference threshold speed. +! !================================================================== +! WND_RFR_DLT = WND_RFR(LON_IDX) - WND_RFR_THR_SLT(LON_IDX) +! +! ! Friction velocity increase from saltation GMB98 p. 6209 [m/s] +! wnd_frc_slt_dlt = 0.003D0 * wnd_rfr_dlt * wnd_rfr_dlt +! +! ! Saltation friction velocity, U*,s, Zender et al. Equ. (4). +! WND_FRC_SLT(LON_IDX) = WND_FRC(LON_IDX) +! & + WND_FRC_SLT_DLT ! [m s-1] +! +! ! +!ctdf Eliminate Owen effect tdf 01/13/2K5 +! wnd_frc_slt(:) = wnd_frc(:) +! +! ENDIF +! ENDDO +!------------------------------------------------------------------------------ + + ! Return to calling program + END SUBROUTINE WND_FRC_SLT_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE FLX_MSS_CACO3_MSK( DMT_VWR, FLG_MBL, + & FLX_MSS_VRT_DST_CACO3,MSS_FRC_CACO3, + & MSS_FRC_CLY, MSS_FRC_SND ) +! +!****************************************************************************** +! Subroutine FLX_MSS_CACO3_MSK masks dust mass flux by CaCO3 mass fraction at +! source. Theory: Uses soil CaCO3 mass fraction from Global Soil Data Task, +! 1999 (Sch99). Uses size dependent apportionment of CaCO3 from Claquin et +! al, 1999 (CSB99). (tdf, bmy, 4/5/04) +! +! Arguments as Input: +! =========================================================================== +! (1 ) DMT_VWR (REAL*8 ) : Mass weighted diameter resolved [m] +! (2 ) FLG_MBL (LOGICAL) : Mobilization candidate flag +! (3 ) FLX_MSS_VRT_DST_CACO3 (REAL*8 ) : Vert. mass flux of dust [kg/m2/s ] +! (4 ) MSS_FRC_CACO3 (REAL*8 ) : Mass fraction of CaCO3 [fraction] +! (5 ) MSS_FRC_CLY (REAL*8 ) : Mass fraction of clay [fraction] +! (6 ) MSS_FRC_SND (REAL*8 ) : Mass fraction of sand [fraction] +! +! Arguments as Output: +! =========================================================================== +! (3 ) FLX_MSS_VRT_DST_CACO3 (REAL*8 ) : Vertical mass flux of CaCO3 [kg/m2/s] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters ! Size parameters + + !------------------ + ! Arguments + !------------------ + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: DMT_VWR(NDSTBIN) + REAL*8, INTENT(IN) :: MSS_FRC_CACO3(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_CLY(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_SND(IIPAR) + REAL*8, INTENT(INOUT) :: FLX_MSS_VRT_DST_CACO3(IIPAR,NDSTBIN) + + !------------------ + ! Parameters + !------------------ + + ! Maximum diameter of Clay soil texture CSB99 p. 22250 [m] + REAL*8, PARAMETER :: DMT_CLY_MAX = 2.0d-6 + + ! Maximum diameter of Silt soil texture CSB99 p. 22250 [m] + REAL*8, PARAMETER :: DMT_SLT_MAX = 50.0d-6 + + ! Density of CaCO3 http://www.ssc.on.ca/mandm/calcit.htm [kg/m3] + REAL*8, PARAMETER :: DNS_CACO3 = 2950.0d0 + + !------------------ + ! Local variables + !------------------ + + ! [idx] Counting index + INTEGER :: M + + ! [idx] Counting index for lon + INTEGER :: LON_IDX + + ! [frc] Mass fraction of silt + REAL*8 :: MSS_FRC_SLT(IIPAR) + + ! [frc] Fraction of soil CaCO3 in size bin + REAL*8 :: MSS_FRC_CACO3_SZ_CRR + + ! [frc] Fraction of CaCO3 in clay + REAL*8 :: MSS_FRC_CACO3_CLY + + ! [frc] Fraction of CaCO3 in silt + REAL*8 :: MSS_FRC_CACO3_SLT + + ! [frc] Fraction of CaCO3 in sand + REAL*8 :: MSS_FRC_CACO3_SND + + !================================================================= + ! FLX_MSS_CACO3_MSK + !================================================================= + + ! INITIALIZE + MSS_FRC_SLT(:) = 0.0D0 + + ! Loop over dust bins + DO M = 1, NDSTBIN + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + !=========================================================== + ! Simple technique is to mask dust mass by tracer mass + ! fraction. The model transports (hence conserves) CaCO3 + ! rather than total dust itself. The method assumes source, + ! transport, and removal processes are linear with tracer + ! mass + !=========================================================== + + ! If this is a mobilization candidate, then... + IF ( FLG_MBL(LON_IDX) ) THEN + + ! 20000320: Currently this is only process in + ! dust model requiring mss_frc_slt + + ! [frc] Mass fraction of silt + MSS_FRC_SLT(LON_IDX) = + & MAX(0.0D0, 1.0D0 -MSS_FRC_CLY(LON_IDX) + & -MSS_FRC_SND(LON_IDX)) + + ! CSB99 showed that CaCO3 is not uniformly distributed + ! across sizes. There is more CaCO3 per unit mass of + ! silt than per unit mass of clay. + + ! Fraction of CaCO3 in clay CSB99 p. 22249 Figure 1b + MSS_FRC_CACO3_CLY = MAX(0.0D0,-0.045D0+0.5D0 + & * MIN(0.5D0,MSS_FRC_CLY(LON_IDX))) + + ! Fraction of CaCO3 in silt CSB99 p. 22249 Figure 1a + MSS_FRC_CACO3_SLT = MAX(0.0D0,-0.175D0+1.4D0 + & * MIN(0.5D0,MSS_FRC_SLT(LON_IDX))) + + ! Fraction of CaCO3 in sand CSB99 p. 22249 Figure 1a + MSS_FRC_CACO3_SND = 1.0D0 - MSS_FRC_CACO3_CLY + & - MSS_FRC_CACO3_SND + + ! Set CaCO3 fraction of total CaCO3 for each transport bin + IF ( DMT_VWR(M) < DMT_CLY_MAX ) THEN + + ! Transport bin carries Clay + ! Fraction of soil CaCO3 in size bin + MSS_FRC_CACO3_SZ_CRR = MSS_FRC_CACO3_CLY + + ELSE IF ( DMT_VWR(M) < DMT_SLT_MAX ) THEN + + ! Transport bin carries Silt + ! Fraction of soil CaCO3 in size bin + MSS_FRC_CACO3_SZ_CRR = MSS_FRC_CACO3_SLT + + ELSE + + ! Transport bin carries Sand + ! Fraction of soil CaCO3 in size bin + MSS_FRC_CACO3_SZ_CRR = MSS_FRC_CACO3_SND + + ENDIF + + ! Error checks + IF ( MSS_FRC_CACO3_SZ_CRR < 0.0D0 .OR. + & MSS_FRC_CACO3_SZ_CRR > 1.0D0 ) THEN + CALL ERROR_STOP( + & 'mss_frc_CaC_s < 0.0.or.mss_frc_CaC_s > 1.0!', + & 'FLX_MSS_CACO3_MSK ("dust_dead_mod.f")' ) + ENDIF + + IF ( MSS_FRC_CACO3(LON_IDX) < 0.0D0 .OR. + & MSS_FRC_CACO3(LON_IDX) > 1.0D0 ) THEN + CALL ERROR_STOP( + & 'mss_frc_CaCO3_s < 0.0.or.mss_frc_CaCO3 > 1.0!', + & ' FLX_MSS_CACO3_MSK ("dust_dead_mod.f")' ) + ENDIF + + ! Convert dust flux to CaCO3 flux + FLX_MSS_VRT_DST_CACO3(LON_IDX,M) = + & FLX_MSS_VRT_DST_CACO3(LON_IDX,M) ! [KG m-2 s-1] + & * MSS_FRC_CACO3(LON_IDX) ! [frc] Mass fraction of + ! CaCO3 (at this location) + ! 20020925 fxm: Remove size dependence of CaCO3 + & * 1.0D0 + + ENDIF + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE FLX_MSS_CACO3_MSK + +!------------------------------------------------------------------------------ + + SUBROUTINE FLX_MSS_HRZ_SLT_TTL_WHI79_GET( DNS_MDP, FLG_MBL, + & QS_TTL, U_S, U_ST ) +! +!****************************************************************************** +! Subroutine FLX_MSS_HRZ_SLT_TTL_WHI79_GET computes vertically integrated +! streamwise mass flux of particles. Theory: Uses method proposed by White +! (1979). See Zender et al., expr (10). fxm: use surface air density not +! midlayer density (tdf, bmy, 4/5/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) DNS_MDP (REAL*8 ) : Midlayer density [g/m3 ] +! (2 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [flag ] +! (4 ) U_S (REAL*8 ) : Surface friction velocity [m/s ] +! (5 ) U_ST (REAL*8 ) : Threshold friction spd for saltation [m/s ] +! +! Arguments as Output: +! ============================================================================ +! (3 ) QS_TTL (REAL*8 ) : Vertically integrated streamwise mass flux [kg/m/s] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + !------------------ + ! Arguments + !------------------ + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: DNS_MDP(IIPAR) + REAL*8, INTENT(IN) :: U_S(IIPAR) + REAL*8, INTENT(IN) :: U_ST(IIPAR) + REAL*8, INTENT(OUT) :: QS_TTL(IIPAR) + + !------------------ + ! Parameters + !------------------ + + ! [frc] Saltation constant Whi79 p. 4648, MaB97 p. 16422 + REAL*8, PARAMETER :: CST_SLT = 2.61d0 + + !------------------ + ! Local variables + !------------------ + + ! [frc] Ratio of wind friction threshold to wind friction + real*8 :: U_S_rat + + ! [idx] Counting index for lon + integer :: lon_idx + + !================================================================= + ! FLX_MSS_HRZ_SLT_TTL_WHI79_GET begins here! + !================================================================= + + ! Initialize + QS_TTL(:) = 0.0D0 + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! If this is a mobilization candidate and the friction + ! velocity is above the threshold for saltation... + IF ( FLG_MBL(LON_IDX) .AND. + & U_S(LON_IDX) > U_ST(LON_IDX) ) THEN + + ! Ratio of wind friction threshold to wind friction + U_S_RAT = U_ST(LON_IDX) / U_S(LON_IDX) + + ! Whi79 p. 4648 (19), MaB97 p. 16422 (28) + QS_TTL(LON_IDX) = ! [kg m-1 s-1] + & CST_SLT * DNS_MDP(LON_IDX) * (U_S(LON_IDX)**3.0D0) + & * (1.0D0-U_S_RAT) * (1.0D0+U_S_RAT) + & * (1.0D0+U_S_RAT) / GRV_SFC + + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE FLX_MSS_HRZ_SLT_TTL_WHI79_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE FLX_MSS_VRT_DST_TTL_MAB95_GET( DST_SLT_FLX_RAT_TTL, + & FLG_MBL, + & FLX_MSS_HRZ_SLT_TTL, + & FLX_MSS_VRT_DST_TTL, + & MSS_FRC_CLY ) +! +!****************************************************************************** +! Subroutine FLX_MSS_VRT_DST_TTL_MAB95_GET diagnoses total vertical mass flux +! of dust from vertically integrated streamwise mass flux, Zender et al., +! expr. (11). (tdf, bmy, 4/5/04) +! +! Theory: Uses clay-based method proposed by Marticorena & Bergametti (1995) +! Their parameterization is based only on data for mss_frc_cly < 0.20 +! For clayier soils, dst_slt_flx_rat_ttl may behave dramatically differently +! Whether this behavior changes when mss_frc_cly > 0.20 is unknown +! Anecdotal evidence suggests vertical flux decreases for mss_frc_cly > 0.20 +! Thus we use min[mss_frc_cly,0.20] in MaB95 parameterization +! +! Arguments as Input: +! ============================================================================ +! (2 ) FLG_MBL (LOGICAL) : Mobilization candidate flag +! (3 ) FLX_MSS_HRZ_SLT_TTL (REAL*8 ) : Vertically integrated streamwise +! mass flux [kg/m/s] +! (5 ) MSS_FRC_CLY (REAL*8 ) : Mass fraction clay [fraction] +! +! Arguments as Output: +! ============================================================================ +! (1 ) DST_SLT_FLX_RAT_TTL (REAL*8 ) : Ratio of vertical dust flux t +! to streamwise mass flux [1/m] +! (4 ) FX_MSS_VRT_DST_TTL (REAL*8 ) : Total vert. mass flux of dust [kg/m2/s] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! Size parameters + + !----------------- + ! Arguments + !----------------- + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: FLX_MSS_HRZ_SLT_TTL(IIPAR) + REAL*8, INTENT(IN) :: MSS_FRC_CLY(IIPAR) + REAL*8, INTENT(OUT) :: DST_SLT_FLX_RAT_TTL(IIPAR) + REAL*8, INTENT(OUT) :: FLX_MSS_VRT_DST_TTL(IIPAR) + + !----------------- + ! Local variables + !----------------- + + ! [idx] Counting index for lon + INTEGER :: LON_IDX + + ! [frc] Mass fraction clay limited to 0.20 + REAL*8 :: MSS_FRC_CLY_VLD + + ! [frc] Natural log of 10 + REAL*8 :: LN10 + + !================================================================= + ! FLX_MSS_VRT_DST_TTL_MAB95_GET + !================================================================= + + ! Initialize + LN10 = LOG(10.0D0) + DST_SLT_FLX_RAT_TTL(:) = 0.0D0 + FLX_MSS_VRT_DST_TTL(:) = 0.0D0 + + ! Loop over longitudes + DO LON_IDX = 1, IIPAR + + ! If this is a mobilization candidate... + IF ( FLG_MBL(LON_IDX) ) then + + ! 19990603: fxm: Dust production is EXTREMELY sensitive to + ! this parameter, which changes flux by 3 orders of magnitude + ! in 0.0 < mss_frc_cly < 0.20 + MSS_FRC_CLY_VLD = MIN(MSS_FRC_CLY(LON_IDX),0.2D0) ! [frc] + + DST_SLT_FLX_RAT_TTL(LON_IDX) = ! [m-1] + & 100.0D0 * EXP(LN10*(13.4D0*MSS_FRC_CLY_VLD-6.0D0)) + ! MaB95 p. 16423 (47) + + FLX_MSS_VRT_DST_TTL(LON_IDX) = ! [kg M-1 s-1] + & FLX_MSS_HRZ_SLT_TTL(LON_IDX) + & * DST_SLT_FLX_RAT_TTL(LON_IDX) + + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE FLX_MSS_VRT_DST_TTL_MAB95_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE DST_PSD_MSS( OVR_SRC_SNK_FRC, MSS_FRC_SRC, + & OVR_SRC_SNK_MSS, NDSTBIN, DST_SRC_NBR ) +! +!****************************************************************************** +! Subroutine DST_PSD_MSS computes OVR_SRC_SNK_MSS from OVR_SRC_SNK_FRC +! and MSS_FRC_SRC. (tdf, bmy, 4/5/04) +! +! Multiply ovr_src_snk_frc(src_idx,*) by mss_frc(src_idx) to obtain +! absolute mass fraction mapping from source dists. to sink bins +! +! Arguments as Input: +! ============================================================================ +! (1 ) OVR_SRC_SNK_FRC (REAL*8 ) : Mass overlap, Mij, Zender p. 5, Equ. 12 +! (2 ) MSS_FRC_SRC (REAL*8 ) : Mass fraction in each mode (Table 1, M) +! (4 ) NDSTBIN (INTEGER) : Number of GEOS_CHEM dust bins +! (5 ) DST_SRC_NBR (INTEGER) : Number of source modes +! +! Arguments as Output: +! ============================================================================ +! (3 ) OVR_SRC_SNK_MSS (REAL*8 ) : Mass of stuff ??? +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! + !----------------- + ! Arguments + !----------------- + INTEGER, INTENT(IN) :: DST_SRC_NBR, NDSTBIN + REAL*8, INTENT(IN) :: OVR_SRC_SNK_FRC(DST_SRC_NBR,NDSTBIN) + REAL*8, INTENT(IN) :: MSS_FRC_SRC(DST_SRC_NBR) + REAL*8, INTENT(OUT) :: OVR_SRC_SNK_MSS(DST_SRC_NBR,NDSTBIN) + + !----------------- + ! Local variables + !----------------- + INTEGER :: SRC_IDX, SNK_IDX + REAL*8 :: MSS_FRC_TRN_DST_SRC(NDSTBIN) + REAL*8 :: OVR_SRC_SNK_MSS_TTL + + !================================================================= + ! DST_PSD_MSS begins here! + !================================================================= + + ! Fraction of vertical dust flux which is transported + OVR_SRC_SNK_MSS_TTL = 0.0D0 + + ! Fraction of transported dust mass at source + DO SNK_IDX = 1, NDSTBIN + MSS_FRC_TRN_DST_SRC(SNK_IDX) = 0.0D0 + ENDDO + + DO SNK_IDX = 1, NDSTBIN + DO SRC_IDX = 1, DST_SRC_NBR + OVR_SRC_SNK_MSS (SRC_IDX,SNK_IDX) = ! [frc] + & OVR_SRC_SNK_FRC (SRC_IDX,SNK_IDX) + & * MSS_FRC_SRC (SRC_IDX) ! [frc] + ENDDO + ENDDO + + ! Split double do loop into 2 parts tdf 10/22/2K3 + DO SNK_IDX = 1, NDSTBIN + DO SRC_IDX = 1, DST_SRC_NBR + + ! [frc] Fraction of transported dust mass at source + MSS_FRC_TRN_DST_SRC(SNK_IDX) = + & MSS_FRC_TRN_DST_SRC(SNK_IDX) + & + OVR_SRC_SNK_MSS(SRC_IDX,SNK_IDX) + + ! [frc] Compute total transported mass fraction of dust flux + OVR_SRC_SNK_MSS_TTL = OVR_SRC_SNK_MSS_TTL + & + OVR_SRC_SNK_MSS (SRC_IDX,snk_idx) + ENDDO + ENDDO + + ! Convert fraction of mobilized mass to fraction of transported mass + DO SNK_IDX = 1, NDSTBIN + MSS_FRC_TRN_DST_SRC (SNK_IDX) = + & MSS_FRC_TRN_DST_SRC (SNK_IDX) / OVR_SRC_SNK_MSS_TTL + ENDDO + + ! Return to calling program + END SUBROUTINE DST_PSD_MSS + +!------------------------------------------------------------------------------ + + SUBROUTINE FLX_MSS_VRT_DST_PRT( FLG_MBL, + & FLX_MSS_VRT_DST, + & FLX_MSS_VRT_DST_TTL ) +! +!****************************************************************************** +! Subroutine FLX_MSS_VRT_DST_PRT partitions total vertical mass flux of dust +! into transport bins. Assumes a trimodal lognormal probability density +! function (see Zender et al., p. 5). (tdf, bmy, 4/5/04) +! +! DST_SRC_NBR = 3 - trimodal size distribution in source c regions (p. 5) +! OVR_SRC_SNK_MSS [frc] computed in dst_psd_mss, called from dust_mod.f +! +! Arguments as Input: +! ============================================================================ +! (1 ) FLG_MBL (LOGICAL) : Mobilization candidate flag +! (3 ) FLX_MSS_VRT_DST_TTL (REAL*8 ) : Total vert. mass flux of dust [kg/m2/s] +! +! Arguments as Output: +! ============================================================================ +! (2 ) FLX_MSS_VRT_DST (REAL*8 ) : Vertical mass flux of dust [kg/m2/s] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Arguments + LOGICAL, INTENT(IN) :: FLG_MBL(IIPAR) + REAL*8, INTENT(IN) :: FLX_MSS_VRT_DST_TTL(IIPAR) + REAL*8, INTENT(OUT) :: FLX_MSS_VRT_DST(IIPAR,NDSTBIN) + + ! Local variables + INTEGER :: LON_IDX ! [idx] Counting index for lon + INTEGER :: SRC_IDX ! [idx] Counting index for src + INTEGER :: SNK_IDX ! [idx] Counting index for snk + INTEGER :: SNK_NBR ! [nbr] Dimension size + + !================================================================= + ! FLX_MSS_VRT_DST_PRT begins here! + !================================================================= + + ! Initialize + FLX_MSS_VRT_DST(:,:) = 0.0D0 ! [frc] + + ! Loop over longitudes (NB: Inefficient loop order) + DO LON_IDX = 1, IIPAR + + ! If this is a mobilization candidate... + IF ( FLG_MBL(LON_IDX) ) THEN + + ! Loop over source & sink indices + DO SNK_IDX = 1, NDSTBIN + DO SRC_IDX = 1, DST_SRC_NBR + FLX_MSS_VRT_DST(LON_IDX,SNK_IDX) = ! [kg m-2 s-1] + & FLX_MSS_VRT_DST(LON_IDX,SNK_IDX) + & + OVR_SRC_SNK_MSS(SRC_IDX,SNK_IDX) + & * FLX_MSS_VRT_DST_TTL(LON_IDX) + ENDDO + ENDDO + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE FLX_MSS_VRT_DST_PRT + +!------------------------------------------------------------------------------ + + SUBROUTINE TM_2_IDX_WGT() + + ! routine eliminated: see original code + END SUBROUTINE TM_2_IDX_WGT + +!------------------------------------------------------------------------------ + + SUBROUTINE LND_FRC_MBL_GET( DOY, FLG_MBL, LAT_RDN, + & LND_FRC_DRY, LND_FRC_MBL, MBL_NBR, + & ORO, SFC_TYP, SNW_FRC, + & TPT_SOI, TPT_SOI_FRZ, VAI_DST ) +! +!****************************************************************************** +! Subroutine LND_FRC_MBL_GET returns the fraction of each GEOS-CHEM grid +! box which is suitable for dust mobilization. This routine is called +! by DST_MBL. (tdf, bmy, 4/5/04, 1/13/10) +! +! The DATE is used to obtain the time-varying vegetation cover. +! Routine currently uses latitude slice of VAI from time-dependent surface +! boundary dataset (tdf, 10/27/03). LAI/VAI algorithm is from CCM:lsm/phenol +! () Bon96. The LSM data are mid-month values, i.e., valid on the 15th of ! +! the month.! +! +! Criterion for mobilisation candidate (tdf, 4/5/04): +! (1) first, must be a land point, not ocean, not ice +! (2) second, it cannot be an inland lake, wetland or ice +! (3) modulated by vegetation type +! (4) modulated by subgridscale wetness +! (5) cannot be snow covered +! +! Arguments as Input: +! ============================================================================ +! (1 ) DOY (REAL*8 ) : Day of year [1.0-366.0] +! (3 ) LAT_RDN (REAL*8 ) : Latitude [radians ] +! (4 ) LND_FRC_DRY (REAL*8 ) : Dry land fraction [fraction ] +! (7 ) ORO (REAL*8 ) : Orography: land/ocean/ice [flags ] +! (8 ) SFC_TYP (INTEGER) : LSM surface type (0..28) [unitless ] +! (9 ) SNW_FRC (REAL*8 ) : Fraction of surface covered by snow [fraction ] +! (10) TPT_SOI (REAL*8 ) : Soil temperature [K ] +! (11) TPT_SOI_FRZ (REAL*8 ) : Temperature of frozen soil [K ] +! (12) VAI_DST (REAL*8 ) : Vegetation area index, one-sided [m2/m2 ] +! +! Arguments as Output: +! ============================================================================ +! (2 ) FLG_MBL (LOGICAL) : Mobilization candidate flag [flag ] +! (5 ) LND_FRC_MBL (REAL*8 ) : Bare ground fraction [fraction ] +! (6 ) MBL_NBR (INTEGER) : Number of mobilization candidates [unitless ] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +! (2 ) For the GOCART source function, we don't use VAI, so set FLG_VAI_TVBDS +! = .FALSE. and disable calls to ERROR_STOP (tdf, bmy, 1/25/07) +! (3 ) Modification for GEOS-4 1 x 1.25 grids (lok, bmy, 1/13/10) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP + +# include "CMN_SIZE" ! Size parameters ! Size parameters +# include "CMN_GCTM" ! Size parameters ! Size parameters + + !------------------ + ! Arguments + !------------------ + INTEGER, INTENT(IN) :: SFC_TYP(IIPAR) + REAL*8, INTENT(IN) :: DOY + REAL*8, INTENT(IN) :: LAT_RDN + REAL*8, INTENT(IN) :: LND_FRC_DRY(IIPAR) + REAL*8, INTENT(IN) :: ORO(IIPAR) + REAL*8, INTENT(IN) :: SNW_FRC(IIPAR) + REAL*8, INTENT(IN) :: TPT_SOI(IIPAR) + REAL*8, INTENT(IN) :: TPT_SOI_FRZ + REAL*8, INTENT(IN) :: VAI_DST(IIPAR) + INTEGER, INTENT(OUT) :: MBL_NBR + LOGICAL, INTENT(OUT) :: FLG_MBL(IIPAR) + REAL*8, INTENT(OUT) :: LND_FRC_MBL(IIPAR) + + !------------------ + ! Parameters + !------------------ + + ! VAI threshold quench [m2/m2] + REAL*8, PARAMETER :: VAI_MBL_THR = 0.30D0 + + !------------------ + ! Local variables + !------------------ + + ! [idx] Counting index + INTEGER :: IDX_IDX + + ! [idx] Interpolation month, future + INTEGER :: IDX_MTH_GLB + + ! [idx] Interpolation month, past + INTEGER :: IDX_MTH_LUB + + ! [idx] Longitude index array (land) + INTEGER :: LND_IDX(IIPAR) + + ! [nbr] Number of land points + INTEGER :: LND_NBR + + ! [idx] Counting index for longitude + INTEGER :: LON_IDX + + ! [idx] Surface type index + INTEGER :: SFC_TYP_IDX + + ! [idx] Surface sub-gridscale index + INTEGER :: SGS_IDX + + !------------------------------------------------------------------- + ! Prior to 1/25/07: + ! For GOCART source function, we don't use VAI (tdf, bmy, 1/25/07) + ! + ! %%%%% DO NOT DELETE -- LEAVE THIS CODE COMMENTED OUT %%%%% + ! + !! [flg] Use VAI data from time-varying boundary dataset + ! LOGICAL :: FLG_VAI_TVBDS = .TRUE. + !------------------------------------------------------------------- + + ! For GOCART source function, we do not use VAI (tdf, bmy, 1/25/07) + LOGICAL :: FLG_VAI_TVBDS = .FALSE. + + ! [flg] Add 182 days in southern hemisphere + LOGICAL :: FLG_SH_ADJ = .TRUE. + + ! [dgr] Latitude + REAL*8 :: LAT_DGR + + ! [m2 m-2] Leaf + stem area index, one-sided + REAL*8 :: VAI_SGS + + !================================================================= + ! LND_FRC_MBL_GET begins here! + !================================================================= + + ! Error check + IF ( VAI_MBL_THR <= 0.0d0 ) THEN + CALL ERROR_STOP( 'VAI_MBL_THR <= 0.0!', + & 'LND_FRC_MBL_GET ("dust_dead_mod.f")' ) + ENDIF + + ! Latitude (degrees) + LAT_DGR = 180.0D0 * LAT_RDN/PI + + ! Initialize outputs + MBL_NBR = 0 + + DO LON_IDX = 1, IIPAR + FLG_MBL(LON_IDX) = .FALSE. + ENDDO + + LND_FRC_MBL(:) = 0.0D0 + + !================================================================= + ! For dust mobilisation, we need to have land! tdf 10/27/2K3 + ! Set up lnd_idx to hold the longitude indices for land + ! Land ahoy! + !================================================================= + LND_NBR = 0 + DO LON_IDX = 1, IIPAR + IF ( ORO_IS_LND( ORO(LON_IDX)) ) THEN + LND_NBR = LND_NBR + 1 + LND_IDX(LND_NBR) = LON_IDX + ENDIF + ENDDO + + ! Much ado about nothing (no land points) + IF ( LND_NBR == 0 ) RETURN + +!----------------------------------------------------------------------------- +! Prior to 1/25/07: +! When GOCART source function is used, VAI flag is NOT used, so +! we need to disable the ERROR_STOP call (tdf, bmy, 1/25/07) +! +! %%%%% DO NOT DELETE -- LEAVE THIS CODE COMMENTED OUT %%%%% +! +! ! Introduce error message for flg_vai_tvbds=F (VAI not used!) +! IF ( .not. FLG_VAI_TVBDS ) THEN +!c print *,' FLG_VAI_TVBDS is false: GOCART source function used' +! CALL ERROR_STOP( 'FLG_VAI_TVBDS=F', +! & 'LND_FRC_MBL_GET ("dust_dead_mod.f")' ) +! ENDIF +!----------------------------------------------------------------------------- + + !================================================================= + ! Only land points are possible candidates for dust mobilization + !================================================================= + + ! Loop over land points + DO IDX_IDX = 1, LND_NBR + LON_IDX = LND_IDX(IDX_IDX) + + ! Store surface blend of current gridpoint + SFC_TYP_IDX = SFC_TYP(LON_IDX) + + ! Check for wet or frozen conditions - no mobilisation allowed + ! Surface type 1 = inland lakes & land ice + ! Surface type 27 = wetlands + IF ( SFC_TYP_IDX <= 1 .OR. SFC_TYP_IDX >= 27 .OR. + & TPT_SOI(LON_IDX) < TPT_SOI_FRZ ) THEN + + ! SET bare ground fraction to zero + LND_FRC_MBL(LON_IDX) = 0.0D0 + + ELSE + + !------------------------- + ! If we are using VAI... + !------------------------- + IF ( FLG_VAI_TVBDS ) THEN + + ! "bare ground" fraction of current gridcell decreases + ! linearly from 1.0 to 0.0 as VAI increases from 0.0 to + ! vai_mbl_thr. NOTE: vai_mbl_thr set to 0.3 (tdf, 4/5/04) + LND_FRC_MBL(LON_IDX) = + & 1.0D0 - MIN(1.0D0, MIN(VAI_DST(LON_IDX), + & VAI_MBL_THR) / VAI_MBL_THR) + + !--------------------------- + ! If we're not using VAI... + !--------------------------- + ELSE + +!----------------------------------------------------------------------------- +! Prior to 1/25/07: +! When GOCART source function is used, VAI flag is NOT used, so +! we need to disable the ERROR_STOP call. (tdf, bmy, 1/25/07) +! +! %%%%% DO NOT DELETE -- LEAVE THIS CODE COMMENTED OUT %%%%% +! +! CALL ERROR_STOP( 'FLG_VAI_TVBDS=F', +! & 'LND_FRC_MBL_GET ("dust_dead_mod.f")' ) +!----------------------------------------------------------------------------- + + ! For GOCART source function, set the bare + ! ground fraction to 1 (tdf, bmy, 1/25/07) + LND_FRC_MBL(LON_IDX) = 1.0D0 + + ENDIF + + ENDIF ! endif normal land + + !============================================================== + ! We have now filled "lnd_frc_mbl" the land fraction suitable + ! for mobilisation. Adjust for factors which constrain entire + ! gridcell LND_FRC_MBL modulated by LND_FRC_DRY and SNW_FRC. + ! (tdf, 4/5/04) + !============================================================== + + ! Take the bare ground fraction, multiply by the fraction + ! that is dry and that is NOT covered by snow + LND_FRC_MBL(LON_IDX) = LND_FRC_MBL(LON_IDX) + & * LND_FRC_DRY(LON_IDX) + & * ( 1.0D0 - SNW_FRC(LON_IDX) ) + + ! Temporary fix for 1 x 1.25 grids -- Lok Lamsal 1/13/10 + IF ( LND_FRC_MBL(LON_IDX) .GT. 1.0D0 ) THEN + LND_FRC_MBL(LON_IDX) = 0.99D0 + ENDIF + + ! Error check + IF ( LND_FRC_MBL(lon_idx) > 1.0D0 ) THEN + CALL ERROR_STOP( 'LND_FRC_MBL > 1!', + & 'LND_FRC_MBL_GET ("dust_dead_mod.f")' ) + ENDIF + + IF ( LND_FRC_MBL(LON_IDX) < 0.0D0 ) then + CALL ERROR_STOP( 'LND_FRC_MBL < 0!', + & 'LND_FRC_MBL_GET ("dust_dead_mod.f")' ) + ENDIF + + ! If there is dry land in this longitude + if ( LND_FRC_MBL(LON_IDX) > 0.0D0 ) then + + ! Set flag, we have a candidate! + FLG_MBL(LON_IDX) = .TRUE. + + ! Increment # of candidates + MBL_NBR = MBL_NBR + 1 + ENDIF + + ENDDO + + ! Return to calling program + END SUBROUTINE LND_FRC_MBL_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE DST_ADD_LON( Q, Q_TTL ) +! +!****************************************************************************** +! Subroutine DST_ADD_LON dst_add_lon() computes and returns the total +! property (e.g., mixing ratio, flux), obtained by simply adding along the +! (dust) constituent dimension, when given an 3-D array of an additive +! property (e.g., mixing ratio, flux). (tdf, bmy, 4/5/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) q (REAL*8) : Total property +! +! Arguments as Output: +! ============================================================================ +! (2 ) q_ttl (REAL*8) : Property for each size class +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Arguments + REAL*8, INTENT(IN) :: Q(IIPAR,NDSTBIN) + REAL*8, INTENT(OUT) :: Q_TTL(IIPAR) + + ! Local variables + INTEGER :: I, M + + !================================================================= + ! DST_ADD_LON begins here! + !================================================================= + + ! Initialize + Q_TTL = 0d0 + + ! Loop over dust bins + DO M = 1, NDSTBIN + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Integrate! + Q_TTL(I) = Q_TTL(I) + Q(I,M) + + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE DST_ADD_LON + +!------------------------------------------------------------------------------ + + SUBROUTINE DST_TVBDS_GET( LAT_IDX, VAI_DST_OUT ) +! +!****************************************************************************** +! Subroutine DST_TVBDS_GET returns a specifed latitude slice of VAI data. +! (tdf, bmy, 4/5/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) LAT_IDX (INTEGER) : Latitude index +! +! Arguments as Output: +! ============================================================================ +! (2 ) VAI_DST_OUT (REAL*8 ) : Vegetation area index, 1-sided, current [m2/m2] +! +! NOTES: +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: LAT_IDX + REAL*8, INTENT(OUT) :: VAI_DST_OUT(:) + + ! Local variables + INTEGER :: LON_IDX + + !================================================================= + ! DST_TVBDS_GET begins here! + !================================================================= + + ! Return lat slice of VAI [m2/m2] + DO LON_IDX = 1, IIPAR + VAI_DST_OUT(LON_IDX) = VAI_DST(LON_IDX,LAT_IDX) + ENDDO + + ! Return to calling program + END SUBROUTINE DST_TVBDS_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE OVR_SRC_SNK_FRC_GET( SRC_NBR, MDN_SRC, + & GSD_SRC, SNK_NBR, + & DMT_MIN_SNK, DMT_MAX_SNK, + & OVR_SRC_SNK_FRC ) +! +!****************************************************************************** +! Subroutine OVR_SRC_SNK_FRC_GET, given one set (the "source") of lognormal +! distributions, and one set of bin boundaries (the "sink"), computes and +! returns the overlap factors between the source distributions and the sink +! bins. (tdf, bmy, 4/5/04) +! +! The output is a matrix, Mij, OVR_SRC_SNK_FRC(SRC_NBR,SNK_NBR) +! Element ovr_src_snk_frc(i,j) is the fraction of size distribution i +! in group src that overlaps sink bin j +! +! Arguments as Input: +! ============================================================================ +! (1 ) SRC_NBR (INTEGER) : Dimension size [unitless] +! (2 ) MDN_SRC (REAL*8 ) : Mass median particle size [m ] +! (3 ) GSD_SRC (REAL*8 ) : Geometric standard deviation [fraction] +! (4 ) SNK_NBR (INTEGER) : Dimension size [unitless] +! (5 ) DMT_MIN_SNK (REAL*8 ) : Minimum diameter in bin [m ] +! (6 ) DMT_MAX_SNK (REAL*8 ) : Maximum diameter in bin [m ] +! +! Arguments as Output: +! ============================================================================ +! (7 ) OVR_SRC_SNK_FRC (REAL*8 ) : Fractional overlap of src with snk, Mij. +! +! NOTES +! (1 ) Updated comments, cosmetic changes. Also now forces double-precision +! with "D" exponents. (tdf, bmy, 4/5/04) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : GEOS_CHEM_STOP + + ! Arguments + INTEGER, INTENT(IN) :: SRC_NBR + REAL*8, INTENT(IN) :: MDN_SRC(SRC_NBR) + REAL*8, INTENT(IN) :: GSD_SRC(SRC_NBR) + INTEGER, INTENT(IN) :: SNK_NBR + REAL*8, INTENT(IN) :: DMT_MIN_SNK(SNK_NBR) + REAL*8, INTENT(IN) :: DMT_MAX_SNK(SNK_NBR) + REAL*8, INTENT(OUT) :: OVR_SRC_SNK_FRC(SRC_NBR,SNK_NBR) + + ! Local + LOGICAL :: FIRST = .TRUE. + INTEGER :: SRC_IDX ! [idx] Counting index for src + INTEGER :: SNK_IDX ! [idx] Counting index for snk + REAL*8 :: LN_GSD ! [frc] ln(gsd) + REAL*8 :: SQRT2LNGSDI ! [frc] Factor in erf() argument + REAL*8 :: LNDMAXJOVRDMDNI ! [frc] Factor in erf() argument + REAL*8 :: LNDMINJOVRDMDNI ! [frc] Factor in erf() argument + + !================================================================= + ! OVR_SRC_SNK_FRC_GET begins here + !================================================================= + + IF ( FIRST ) THEN + + ! Test if ERF is implemented OK on this platform + ! 19990913: erf() in SGI /usr/lib64/mips4/libftn.so is bogus + IF ( ABS( 0.8427d0 - ERF(1.0d0) ) / 0.8427d0 > 0.001d0 ) THEN + WRITE(6,'(a,f12.10)' ) 'erf(1.0D0) = ',ERF(1.0D0) + WRITE( 6, '(a)' ) 'ERF error in OVR_SRC_SNK_FRC_GET!' + CALL GEOS_CHEM_STOP + ENDIF + + ! Another ERF check + IF ( ERF( 0.0D0 ) /= 0.0D0 ) THEN + WRITE (6,'(a,f12.10)') 'erf(0.0D0) = ',ERF(0.0D0) + WRITE( 6, '(a)' ) 'ERF error in OVR_SRC_SNK_FRC_GET!' + CALL GEOS_CHEM_STOP + ENDIF + + ! Reset first-time flag + FIRST = .FALSE. + ENDIF + + + ! Loop over source index (cf Zender et al eq 12) + DO SRC_IDX = 1, SRC_NBR + + ! Fraction + SQRT2LNGSDI = SQRT(2.0D0) * LOG( GSD_SRC(SRC_IDX) ) + + ! Loop over sink index + DO SNK_IDX = 1, SNK_NBR + + ! [fraction] + LNDMAXJOVRDMDNI = LOG(DMT_MAX_SNK(SNK_IDX)/MDN_SRC(SRC_IDX)) + + ! [fraction] + LNDMINJOVRDMDNI = LOG(DMT_MIN_SNK(SNK_IDX)/MDN_SRC(SRC_IDX)) + + ! [fraction] + OVR_SRC_SNK_FRC (SRC_IDX,SNK_IDX)= ! [frc] + & 0.5D0 * (ERF(LNDMAXJOVRDMDNI/SQRT2LNGSDI) + & - ERF(LNDMINJOVRDMDNI/SQRT2LNGSDI) ) + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE OVR_SRC_SNK_FRC_GET + +!------------------------------------------------------------------------------ + + FUNCTION ERF( X ) RESULT( ERF_VAL ) +! +!****************************************************************************** +! Function ERF returns the error function erf(x). See comments heading +! routine CALERF below. Author/Date: W. J. Cody, January 8, 1985 +! (tdf, bmy, 4/5/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) X (REAL*8) : Argument to erf(x) +! +! NOTES: +! (1 ) Updated comments (bmy, 4/5/04) +!****************************************************************************** +! + IMPLICIT NONE +# include "define.h" + + ! Arguments + REAL*8, INTENT(IN) :: X + + ! Local variables + INTEGER :: JINT + REAL*8 :: RESULT, ERF_VAL + + !================================================================ + ! ERF begins here! + !================================================================ + JINT = 0 + CALL CALERF( X, RESULT, JINT ) + ERF_VAL = RESULT + + ! Return to calling program + END FUNCTION ERF + +!------------------------------------------------------------------------------ + + SUBROUTINE CALERF( ARG, RESULT, JINT ) +! +!****************************************************************************** +! This packet evaluates erf(x), erfc(x), and exp(x*x)*erfc(x) +! for a real argument x. It contains three function type +! subprograms: erf, erfc, and erfcx (or derf, derfc, and derfcx), +! and one subroutine type subprogram, calerf. The calling +! statements for the primary entries are: +! +! y=erf(x) (or y=derf(x)), +! y=erfc(x) (or y=derfc(x)), +! and +! y=erfcx(x) (or y=derfcx(x)). +! +! The routine calerf is intended for internal packet use only, +! all computations within the packet being concentrated in this +! routine. The function subprograms invoke calerf with the +! statement +! call calerf(arg,result,jint) +! where the parameter usage is as follows +! +! Function Parameters for calerf +! Call Arg Result Jint +! +! erf(arg) any real argument erf(arg) 0 +! erfc(arg) abs(arg) < xbig erfc(arg) 1 +! erfcx(arg) xneg < arg < xmax erfcx(arg) 2 +! +! The main computation evaluates near-minimax approximations: +! from "Rational Chebyshev Approximations for the Error Function" +! by W. J. Cody, Math. Comp., 1969, pp. 631-638. This +! transportable program uses rational functions that theoretically +! approximate erf(x) and erfc(x) to at least 18 significant +! decimal digits. The accuracy achieved depends on the arithmetic +! system, the compiler, the intrinsic functions, and proper +! selection of the machine-dependent constants. +! +! Explanation of machine-dependent constants: +! xmin = The smallest positive floating-point number. +! xinf = The largest positive finite floating-point number. +! xneg = The largest negative argument acceptable to erfcx; +! the negative of the solution to the equation +! 2*exp(x*x) = xinf. +! xsmall = Argument below which erf(x) may be represented by +! 2*x/sqrt(pi) and above which x*x will not underflow. +! A conservative value is the largest machine number x +! such that 1.0 + x = 1.0 to machine precision. +! xbig = Largest argument acceptable to erfc; solution to +! the equation: w(x)* (1-0.5/x**2) = xmin, where +! w(x) = exp(-x*x)/[x*sqrt(pi)]. +! xhuge = Argument above which 1.0 - 1/(2*x*x) = 1.0 to +! machine precision. a conservative value is +! 1/[2*sqrt(xsmall)] +! xmax = Largest acceptable argument to erfcx; the minimum +! of xinf and 1/[sqrt(pi)*xmin]. +! +! Approximate values for some important machines are: +! xmin xinf xneg xsmall +! CDC 7600 (s.p.) 3.13e-294 1.26e+322 -27.220 7.11e-15 +! Cray-1 (s.p.) 4.58e-2467 5.45e+2465 -75.345 7.11e-15 +! IEEE (IBM/XT, +! Sun, etc.) (s.p.) 1.18e-38 3.40e+38 -9.382 5.96e-8 +! IEEE (IBM/XT, +! Sun, etc.) (d.p.) 2.23d-308 1.79d+308 -26.628 1.11d-16 +! IBM 195 (d.p.) 5.40d-79 7.23e+75 -13.190 1.39d-17 +! Univac 1108 (d.p.) 2.78d-309 8.98d+307 -26.615 1.73d-18 +! Vax d-format (d.p.) 2.94d-39 1.70d+38 -9.345 1.39d-17 +! Vax g-format (d.p.) 5.56d-309 8.98d+307 -26.615 1.11d-16 +! +! xbig xhuge xmax +! CDC 7600 (s.p.) 25.922 8.39e+6 1.80x+293 +! Cray-1 (s.p.) 75.326 8.39e+6 5.45e+2465 +! IEEE (IBM/XT, +! Sun, etc.) (s.p.) 9.194 2.90e+3 4.79e+37 +! IEEE (IBM/XT, +! Sun, etc.) (d.p.) 26.543 6.71d+7 2.53d+307 +! IBM 195 (d.p.) 13.306 1.90d+8 7.23e+75 +! Univac 1108 (d.p.) 26.582 5.37d+8 8.98d+307 +! Vax d-format (d.p.) 9.269 1.90d+8 1.70d+38 +! Vax g-format (d.p.) 26.569 6.71d+7 8.98d+307 +! +! Error returns: +! The program returns erfc = 0 for arg >= xbig; +! erfcx = xinf for arg < xneg; +! and +! erfcx = 0 for arg >= xmax. +! +! Intrinsic functions required are: +! abs, aint, exp +! +! Author: W. J. Cody +! Mathematics And Computer Science Division +! Argonne National Laboratory +! Argonne, IL 60439 +! Latest modification: March 19, 1990 +! +! NOTES: +! (1 ) Now force double-precision w/ "D" exponents (bmy, 4/5/04) +!****************************************************************************** +! + IMPLICIT NONE +# include "define.h" + INTEGER I,JINT + REAL*8 A,ARG,B,C,D,DEL,FOUR,HALF,P,ONE,Q,RESULT,SIXTEN,SQRPI, + & TWO,THRESH,X,XBIG,XDEN,XHUGE,XINF,XMAX,XNEG,XNUM,XSMALL, + & Y,YSQ,ZERO + DIMENSION A(5),B(4),C(9),D(8),P(6),Q(5) + + ! Mathematical constants + data four,one,half,two,zero/4.0d0,1.0d0,0.5d0,2.0d0,0.0d0/, + & sqrpi/5.6418958354775628695d-1/,thresh/0.46875d0/, + & sixten/16.0d0/ + + ! Machine-dependent constants + data xinf,xneg,xsmall/3.40d+38,-9.382d0,5.96d-8/, + & xbig,xhuge,xmax/9.194d0,2.90d3,4.79d37/ + + ! Coefficients for approximation to erf in first interval + data a /3.16112374387056560d00,1.13864154151050156d02, + & 3.77485237685302021d02,3.20937758913846947d03, + & 1.85777706184603153d-1/ + + data b /2.36012909523441209d01,2.44024637934444173d02, + & 1.28261652607737228d03,2.84423683343917062d03/ + + ! Coefficients for approximation to erfc in second interval + data c /5.64188496988670089d-1,8.88314979438837594d0, + & 6.61191906371416295d01,2.98635138197400131d02, + & 8.81952221241769090d02,1.71204761263407058d03, + & 2.05107837782607147d03,1.23033935479799725d03, + & 2.15311535474403846d-8/ + + data d /1.57449261107098347d01,1.17693950891312499d02, + & 5.37181101862009858d02,1.62138957456669019d03, + & 3.29079923573345963d03,4.36261909014324716d03, + & 3.43936767414372164d03,1.23033935480374942d03/ + + ! Coefficients for approximation to erfc in third interval + data p /3.05326634961232344d-1,3.60344899949804439d-1, + & 1.25781726111229246d-1,1.60837851487422766d-2, + & 6.58749161529837803d-4,1.63153871373020978d-2/ + + data q /2.56852019228982242d00,1.87295284992346047d00, + & 5.27905102951428412d-1,6.05183413124413191d-2, + & 2.33520497626869185d-3/ + +c Main Code + x=arg + y=abs(x) + if (y <= thresh) then +c Evaluate erf for |x| <= 0.46875 + ysq=zero + if (y > xsmall) ysq=y*y + xnum=a(5)*ysq + xden=ysq + do i=1,3 + xnum=(xnum+a(i))*ysq + xden=(xden+b(i))*ysq + end do + result=x*(xnum+a(4))/(xden+b(4)) + if (jint /= 0) result=one-result + if (jint == 2) result=exp(ysq)*result + go to 800 + +c Evaluate erfc for 0.46875 <= |x| <= 4.0 + else if (y <= four) then + xnum=c(9)*y + xden=y + do i=1,7 + xnum=(xnum+c(i))*y + xden=(xden+d(i))*y + end do + result=(xnum+c(8))/(xden+d(8)) + if (jint /= 2) then + ysq=aint(y*sixten)/sixten + del=(y-ysq)*(y+ysq) + result=exp(-ysq*ysq)*exp(-del)*result + end if + +c Evaluate erfc for |x| > 4.0 + else + result=zero + if (y >= xbig) then + if ((jint /= 2).or.(y >= xmax)) go to 300 + if (y >= xhuge) then + result=sqrpi/y + go to 300 + end if + end if + ysq=one/(y*y) + xnum=p(6)*ysq + xden=ysq + do i=1,4 + xnum=(xnum+p(i))*ysq + xden=(xden+q(i))*ysq + end do + result=ysq*(xnum+p(5))/(xden+q(5)) + result=(sqrpi-result)/y + if (jint /= 2) then + ysq=aint(y*sixten)/sixten + del=(y-ysq)*(y+ysq) + result=exp(-ysq*ysq)*exp(-del)*result + end if + end if + +c Fix up for negative argument, erf, etc. + 300 if (jint == 0) then + result=(half-result)+half + if (x < zero) result=-result + else if (jint == 1) then + if (x < zero) result=two-result + else + if (x < zero) then + if (x < xneg) then + result=xinf + else + ysq=aint(x*sixten)/sixten + del=(x-ysq)*(x+ysq) + y=exp(ysq*ysq)*exp(del) + result=(y+y)-result + end if + end if + end if + 800 return + + ! Return to calling program + END SUBROUTINE CALERF + +!------------------------------------------------------------------------------ + + SUBROUTINE PLN_TYP_GET( PLN_TYP, PLN_FRC, TAI ) + +! +!****************************************************************************** +! Subroutine PLN_TYPE_GET returns LSM information needed by the DEAD +! dust parameterization. (tdf, bmy, 4/5/04) +! +! Arguments as Output: +! ============================================================================ +! (1 ) PLN_TYP (INTEGER) : LSM plant type index (1..14) +! (2 ) PLN_TYP (REAL*8 ) : Weight of corresponding plant type (sums to 1.0) +! (3 ) TAI (REAL*8 ) : Leaf-area index (one sided) [index] +! +! NOTES: +! (1 ) Updated comments. Now force double-precision w/ "D" exponents. +! (bmy, 4/5/04) +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(OUT) :: PLN_TYP(0:28,3) + REAL*8, INTENT(OUT) :: PLN_FRC(0:28,3) + REAL*8, INTENT(OUT) :: TAI(14,12) + + ! Local variables + INTEGER :: I, J + + !================================================================= + ! There are 29 land surface types: 0 = ocean, 1 to 28 = land. + ! Each land point has up to three vegetation types, ranging in + ! value from 1 to 14. PLN_TYPE contains the vegetation type of + ! the 3 subgrid points for each surface type. PLN_FRC contains + ! the fractional area of the 3 subgrid points for each surface + ! type. + !================================================================= + PLN_TYP(0:28,1) = (/ 0, + & 14, 14, 1, 2, 4, 1 , 1, + & 4, 1, 3, 5, 13, 1, 2, + & 11, 11, 6, 13, 9, 7, 8, + & 8, 12, 11, 12, 11, 3, 14/) + + PLN_FRC(0:28,1) = (/ 0.00d0, + & 1.00d0, 1.00d0, 0.75d0, 0.50d0, + & 0.75d0, 0.37d0, 0.75d0, + & 0.75d0, 0.37d0, 0.95d0, 0.75d0, + & 0.70d0, 0.25d0, 0.25d0, + & 0.40d0, 0.40d0, 0.60d0, 0.60d0, + & 0.30d0, 0.80d0, 0.80d0, + & 0.10d0, 0.85d0, 0.85d0, 0.85d0, + & 0.85d0, 0.80d0, 1.00d0/) + + + PLN_TYP(0:28,2) = (/ 0, + & 14, 14, 14, 14, 14, 4 ,14, + & 14, 4, 14, 14, 5, 10, 10, + & 4, 4, 13, 6, 10, 14, 14, + & 14, 14, 14, 14, 14, 14, 14/) + + PLN_FRC(0:28,2) = (/ 0.00d0, + & 0.00d0, 0.00d0, 0.25d0, 0.50d0, + & 0.25d0, 0.37d0, 0.25d0, + & 0.25d0, 0.37d0, 0.05d0, 0.25d0, + & 0.30d0, 0.25d0, 0.25d0, + & 0.30d0, 0.30d0, 0.20d0, 0.20d0, + & 0.30d0, 0.20d0, 0.20d0, + & 0.90d0, 0.15d0, 0.15d0, 0.15d0, + & 0.15d0, 0.20d0, 0.00d0/) + + PLN_TYP(0:28,3) = (/ 0, + & 14, 14, 14, 14, 14, 14, 14, + & 14, 14, 14, 14, 14, 14, 14, + & 1, 1, 14, 14, 14, 14, 14, + & 14, 14, 14, 14, 14, 14, 14/) + + PLN_FRC(0:28,3) = (/ 0.00d0, + & 0.00d0, 0.00d0, 0.00d0, 0.00d0, + & 0.00d0, 0.26d0, 0.00d0, + & 0.00d0, 0.26d0, 0.00d0, 0.00d0, + & 0.00d0, 0.50d0, 0.50d0, + & 0.30d0, 0.30d0, 0.20d0, 0.20d0, + & 0.40d0, 0.00d0, 0.00d0, + & 0.00d0, 0.00d0, 0.00d0, 0.00d0, + & 0.00d0, 0.00d0, 0.00d0/) + + !================================================================= + ! ---------------------------------------------------------------- + ! description of the 29 surface types + ! ---------------------------------------------------------------- + ! + ! no vegetation + ! ------------- + ! 0 ocean + ! 1 land ice (glacier) + ! 2 desert + ! + ! forest vegetation + ! ----------------- + ! 3 cool needleleaf evergreen tree + ! 4 cool needleleaf deciduous tree + ! 5 cool broadleaf deciduous tree + ! 6 cool mixed needleleaf evergreen and broadleaf deciduous tree + ! 7 warm needleleaf evergreen tree + ! 8 warm broadleaf deciduous tree + ! 9 warm mixed needleleaf evergreen and broadleaf deciduous tree + ! 10 tropical broadleaf evergreen tree + ! 11 tropical seasonal deciduous tree + ! + ! interrupted woods + ! ---------------- + ! 12 savanna + ! 13 evergreen forest tundra + ! 14 deciduous forest tundra + ! 15 cool forest crop + ! 16 warm forest crop + ! + ! non-woods + ! --------- + ! 17 cool grassland + ! 18 warm grassland + ! 19 tundra + ! 20 evergreen shrub + ! 21 deciduous shrub + ! 22 semi-desert + ! 23 cool irrigated crop + ! 24 cool non-irrigated crop + ! 25 warm irrigated crop + ! 26 warm non-irrigated crop + ! + ! wetlands + ! -------- + ! 27 forest (mangrove) + ! 28 non-forest + ! + ! ---------------------------------------------------------------- + ! description of the 14 plant types. see vegconi.F for + ! parameters that depend on vegetation type + ! ---------------------------------------------------------------- + ! + ! 1 = needleleaf evergreen tree + ! 2 = needleleaf deciduous tree + ! 3 = broadleaf evergreen tree + ! 4 = broadleaf deciduous tree + ! 5 = tropical seasonal tree + ! 6 = cool grass (c3) + ! 7 = evergreen shrub + ! 8 = deciduous shrub + ! 9 = arctic deciduous shrub + ! 10 = arctic grass + ! 11 = crop + ! 12 = irrigated crop + ! 13 = warm grass (c4) + ! 14 = not vegetated + !================================================================= + + ! TAI = monthly leaf area index + stem area index, one-sided + TAI(1,1:12) = (/ 4.5d0, 4.7d0, 5.0d0, 5.1d0, 5.3d0, 5.5d0, + & 5.3d0, 5.3d0, 5.2d0, 4.9d0, 4.6d0, 4.5d0 /) + + TAI(2,1:12) = (/ 0.3d0, 0.3d0, 0.3d0, 1.0d0, 1.6d0, 2.4d0, + & 4.3d0, 2.9d0, 2.0d0, 1.3d0, 0.8d0, 0.5d0 /) + + TAI(3,1:12) = (/ 5.0d0, 5.0d0, 5.0d0, 5.0d0, 5.0d0, 5.0d0, + & 5.0d0, 5.0d0, 5.0d0, 5.0d0, 5.0d0, 5.0d0 /) + + TAI(4,1:12) = (/ 0.4d0, 0.4d0, 0.7d0, 1.6d0, 3.5d0, 5.1d0, + & 5.4d0, 4.8d0, 3.8d0, 1.7d0, 0.6d0, 0.4d0 /) + + TAI(5,1:12) = (/ 1.2d0, 1.0d0, 0.9d0, 0.8d0, 0.8d0, 1.0d0, + & 2.0d0, 3.7d0, 3.2d0, 2.7d0, 1.9d0, 1.2d0 /) + + TAI(6,1:12) = (/ 0.7d0, 0.8d0, 0.9d0, 1.0d0, 1.5d0, 3.4d0, + & 4.3d0, 3.8d0, 1.8d0, 1.0d0, 0.9d0, 0.8d0 /) + + TAI(7,1:12) = (/ 1.3d0, 1.3d0, 1.3d0, 1.3d0, 1.3d0, 1.3d0, + & 1.3d0, 1.3d0, 1.3d0, 1.3d0, 1.3d0, 1.3d0 /) + + TAI(8,1:12) = (/ 1.0d0, 1.0d0, 0.8d0, 0.3d0, 0.6d0, 0.0d0, + & 0.1d0, 0.3d0, 0.5d0, 0.6d0, 0.7d0, 0.9d0 /) + + TAI(9,1:12) = (/ 0.1d0, 0.1d0, 0.1d0, 0.1d0, 0.1d0, 0.3d0, + & 1.5d0, 1.7d0, 1.4d0, 0.1d0, 0.1d0, 0.1d0 /) + + TAI(10,1:12) = (/ 0.7d0, 0.8d0, 0.9d0, 1.0d0, 1.5d0, 3.4d0, + & 4.3d0, 3.8d0, 1.8d0, 1.0d0, 0.9d0, 0.8d0 /) + + TAI(11,1:12) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0, 1.0d0, 2.0d0, + & 3.0d0, 3.0d0, 1.5d0, 0.0d0, 0.0d0, 0.0d0 /) + + TAI(12,1:12) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0, 1.0d0, 2.0d0, + & 3.0d0, 3.0d0, 1.5d0, 0.0d0, 0.0d0, 0.0d0 /) + + TAI(13,1:12) = (/ 0.7d0, 0.8d0, 0.9d0, 1.0d0, 1.5d0, 3.4d0, + & 4.3d0, 3.8d0, 1.8d0, 1.0d0, 0.9d0, 0.8d0 /) + + TAI(14,1:12) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0, 0.0d0, 0.0d0, + & 0.0d0, 0.0d0, 0.0d0, 0.0d0, 0.0d0, 0.0d0 /) + + ! Return to calling program + END SUBROUTINE PLN_TYP_GET + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_TIME_INVARIANT_DATA +! +!****************************************************************************** +! Subroutine GET_TIME_INVARIANT_DATA gets data for the DEAD model which +! does not vary w/ time. This routine is called from SRC_DUST_DEAD in +! "dust_mod.f" only on the first timestep. (bmy, 4/5/04, 1/25/07) +! +! NOTES: +! (1 ) Now reference DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +! (2 ) Now can read data for both GEOS & GCAP grids (bmy, 8/16/05) +! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (4 ) Now references "file_mod.f", "transfer_mod.f". Also now read from +! dust_200605 directory. Now reads GOCART source function from a +! separate file. (tdf, bmy, 1/25/07) +!****************************************************************************** +! + ! 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 + USE FILE_MOD, ONLY : IOERROR + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Local variables + INTEGER :: I, IOS + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*8 :: XTAU + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! GET_TIME_INVARIANT_DATA begins here! + !================================================================= + + ! Initialize data arrays + CALL INIT_DUST_DEAD + + !================================================================= + ! Compute mass overlaps, Mij, between "source" PDFs + ! and size bins (Zender et al., 2K3, Equ. 12, and Table 1) + !================================================================= + CALL OVR_SRC_SNK_FRC_GET( DST_SRC_NBR, DMT_VMA_SRC, + & GSD_ANL_SRC, NDSTBIN, + & DMT_MIN, DMT_MAX, + & OVR_SRC_SNK_FRC ) + + !================================================================= + ! Compute OVR_SRC_SNK_MSS, the fraction of dust transported, given + ! the mass overlap, OVR_SRC_SNK_FRC, and the mass fraction + ! MSS_FRC_SRC. OVR_SRC_SNK_MSS is used in routine + ! FLX_MSS_VRT_DST_PRT which partitions the total vertical + ! dust flux into transport + !============================================================== + CALL DST_PSD_MSS( OVR_SRC_SNK_FRC, MSS_FRC_SRC, + & OVR_SRC_SNK_MSS, NDSTBIN, DST_SRC_NBR ) + + !================================================================= + ! Get plant type, cover, and Leaf area index from land sfc model + !================================================================= + CALL PLN_TYP_GET( PLN_TYP, PLN_FRC, TAI ) + + !================================================================= + ! Need also to provide surface boundary information here + ! read time-invariant boundary fields data set (labelled 1,1,1985) + ! + ! The following time-invariant fields are read in + ! ERD_FCT_GEO ; geomorphic erodibility: IIPAR JJPAR + ! ERD_FCT_HYDRO ; hydrologic erodibility: IIPAR JJPAR + ! ERD_FCT_TOPO ; topog. erodibility (Ginoux): IIPAR JJPAR + ! ERD_FCT_UNITY ; uniform erodibility: IIPAR JJPAR + ! MBL_BSN_FCT ; overall erodibility factor : IIPAR JJPAR + ! + ! Erodibility field should be copied onto mbl_bsn_fct + ! which is the one used by the DEAD code Duncan 8/1/2003 + ! + ! LND_FRC_DRY ; dry land fraction: IIPAR JJPAR + ! MSS_FRC_CACO3 ; mass fraction of soil CaCO3: IIPAR JJPAR + ! MSS_FRC_CLY ; mass fraction of clay: IIPAR JJPAR + ! MSS_FRC_SND ; mass fraction of sand: IIPAR JJPAR + ! SFC_TYP ; surface type: IIPAR JJPAR + !================================================================= + + ! Filename + FILENAME = TRIM( DATA_DIR ) // + & 'dust_200605/dst_tibds.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! TAU value for reading the bpch files + XTAU = GET_TAU0( 1, 1, 1985 ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - GET_TIME_INVARIANT_DATA: Reading ', a ) + + !----------------- + ! ERD_FCT_GEO + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 1, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), ERD_FCT_GEO ) + + !----------------- + ! ERD_FCT_HYDRO + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 2, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), ERD_FCT_HYDRO ) + + !----------------- + ! ERD_FCT_TOPO + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 3, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), ERD_FCT_TOPO ) + + !----------------- + ! ERD_FCT_UNITY + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 4, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), ERD_FCT_UNITY ) + + !----------------- + ! MBL_BSN_FCT + !----------------- +!----------------------------------------------------------------------------- +! To read MBL_BSN_FCT, uncomment these lines: +! CALL READ_BPCH2( FILENAME, 'DEAD-2D', 5, +! & XTAU, IIPAR, JJPAR, +! & 1, ARRAY, QUIET=.TRUE. ) +! +! CALL TRANSFER_2D( ARRAY(:,:,1), MBL_BSN_FCT ) +!----------------------------------------------------------------------------- + + ! ??? Is this correct (bmy, 4/9/04) + ! + ! Set erodibility to a global uniform value of 5.707 + ! as recommended by Zender et al 2003 (tdf, 4/9/04) + MBL_BSN_FCT(:,:) = 1.0d0 + + !----------------- + ! LND_FRC_DRY + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 6, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), LND_FRC_DRY ) + + !----------------- + ! MSS_FRC_CACO3 + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 7, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), MSS_FRC_CACO3 ) + + !----------------- + ! MSS_FRC_CLY + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 8, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), MSS_FRC_CLY ) + + !----------------- + ! MSS_FRC_SND + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 9, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + CALL TRANSFER_2D( ARRAY(:,:,1), MSS_FRC_SND ) + + !----------------- + ! SFC_TYP + !----------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 10, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + ! NINT is not defined for REAL*8 + !CALL TRANSFER_2D( ARRAY(:,:,1), SFC_TYP ) + + ! Also round off + SFC_TYP = NINT( ARRAY(:,:,1) ) + + !------------------------ + ! GOCART source function + ! (tdf, bmy, 1/25/07) + !------------------------ + + ! File name + FILENAME = TRIM( DATA_DIR ) // + & 'dust_200605/GOCART_src_fn.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + + ! Read data + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 14, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 + CALL TRANSFER_2D( ARRAY(:,:,1), SRCE_FUNC ) + + ! Return to calling program + END SUBROUTINE GET_TIME_INVARIANT_DATA + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_MONTHLY_DATA +! +!****************************************************************************** +! Subroutine GET_MONTHLY_DATA gets data for the DEAD model which varies by +! month. This routine is called from SRC_DUST_DEAD in "dust_mod.f". +! (tdf, bmy, 4/5/04, 1/25/07) +! +! NOTES: +! (1 ) Now reference DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +! (2 ) Now can read data for both GEOS & GCAP grids (bmy, 8/16/05) +! (3 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (4 ) Now read from dust_200605 directory (tdf, bmy, 1/25/07) +!****************************************************************************** +! + ! 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 + USE TIME_MOD, ONLY : GET_MONTH, ITS_A_NEW_MONTH + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters ! Size parameters + + ! Local variables + INTEGER :: THISMONTH + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*8 :: XTAU + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! GET_MONTHLY_DATA begins here! + !================================================================= + + ! Filename and time + FILENAME = TRIM( DATA_DIR ) // + & 'dust_200605/dst_tvbds.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! TAU for reading the bpch files + THISMONTH = GET_MONTH() + XTAU = GET_TAU0( THISMONTH, 1, 1985 ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - GET_MONTHLY_DATA: Reading ', a ) + + !----------------------- + ! Veg. Area Index (VAI) + !----------------------- + CALL READ_BPCH2( FILENAME, 'DEAD-2D', 13, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 and resize + CALL TRANSFER_2D( ARRAY(:,:,1), VAI_DST ) + + ! Return to calling program + END SUBROUTINE GET_MONTHLY_DATA + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_DUST_DEAD +! +!****************************************************************************** +! Subroutine INIT_DUST_DEAD initializes all allocatable module arrays. +! (tdf, bmy, 3/30/04, 1/25/07) +! +! NOTES: +! (1 ) Now allocate SRCE_FUNC (tdf, bmy, 1/25/07) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_DUST_DEAD begins here! + !================================================================= + ALLOCATE( ERD_FCT_GEO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ERD_FCT_GEO' ) + ERD_FCT_GEO = 0d0 + + ALLOCATE( ERD_FCT_HYDRO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ERD_FCT_HYDRO' ) + ERD_FCT_HYDRO = 0d0 + + ALLOCATE( ERD_FCT_TOPO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ERD_FCT_TOPO' ) + ERD_FCT_TOPO = 0d0 + + ALLOCATE( ERD_FCT_UNITY( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'ERD_FCT_UNITY' ) + ERD_FCT_UNITY = 0d0 + + ALLOCATE( MBL_BSN_FCT( IIPAR, JJPAR), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'MBL_BSN_FCT' ) + MBL_BSN_FCT = 0d0 + + ALLOCATE( LND_FRC_DRY( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'LND_FRC_DRY' ) + LND_FRC_DRY = 0d0 + + ALLOCATE( MSS_FRC_CACO3( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'MSS_FRC_CACO3' ) + MSS_FRC_CACO3 = 0d0 + + ALLOCATE( MSS_FRC_CLY( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'MSS_FRC_CLY' ) + MSS_FRC_CLY = 0d0 + + ALLOCATE( MSS_FRC_SND( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'MSS_FRC_SND' ) + MSS_FRC_SND = 0d0 + + ALLOCATE( SFC_TYP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SFC_TYP' ) + SFC_TYP = 0d0 + + ALLOCATE( FLX_LW_DWN_SFC( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FLX_LW_DWN_SFC' ) + FLX_LW_DWN_SFC = 0d0 + + ALLOCATE( FLX_SW_ABS_SFC( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'FLX_SW_ABS_SFC' ) + FLX_SW_ABS_SFC = 0d0 + + ALLOCATE( TPT_GND( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'TPT_GND' ) + TPT_GND = 0d0 + + ALLOCATE( TPT_SOI( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'TPT_SOI' ) + TPT_SOI = 0d0 + + ALLOCATE( VWC_SFC( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'VWC_SFC' ) + VWC_SFC = 0d0 + + ALLOCATE( VAI_DST( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'VAI_DST' ) + VAI_DST = 0d0 + + ALLOCATE( SRC_STR( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SRC_STR' ) + SRC_STR = 0d0 + + ! (tdf, bmy, 1/25/07) + ALLOCATE( SRCE_FUNC( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'SRCE_FUNC' ) + SRCE_FUNC = 0d0 + + ALLOCATE( PLN_TYP( 0:28, 3 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'PLN_TYP' ) + PLN_TYP = 0 + + ALLOCATE( PLN_FRC( 0:28, 3 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'PLN_FRC' ) + PLN_FRC = 0d0 + + ALLOCATE( TAI( MVT, 12 ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'TAI' ) + TAI = 0d0 + + ALLOCATE( DMT_VWR( NDSTBIN ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'DMT_VWR' ) + DMT_VWR = 0d0 + + ALLOCATE( DNS_AER( NDSTBIN ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'DNS_AER' ) + DNS_AER = 0d0 + + ALLOCATE( OVR_SRC_SNK_FRC( DST_SRC_NBR, NDSTBIN ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OVR_SRC_SNK_FRC' ) + OVR_SRC_SNK_FRC = 0d0 + + ALLOCATE( OVR_SRC_SNK_MSS( DST_SRC_NBR, NDSTBIN ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OVR_SRC_SNK_MSS' ) + OVR_SRC_SNK_MSS = 0d0 + + ALLOCATE( OROGRAPHY( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'OROGRAPHY' ) + OROGRAPHY = 0 + + ! Bin size min diameter [m] + ALLOCATE( DMT_MIN( NDSTBIN ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'DMT_MIN' ) + DMT_MIN(1) = 0.2d-6 + DMT_MIN(2) = 2.0d-6 + DMT_MIN(3) = 3.6d-6 + DMT_MIN(4) = 6.0d-6 + + ! Bin size max diameter [m] + ALLOCATE( DMT_MAX( NDSTBIN ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'DMT_MAX' ) + DMT_MAX(1) = 2.0d-6 + DMT_MAX(2) = 3.6d-6 + DMT_MAX(3) = 6.0d-6 + DMT_MAX(4) = 1.2d-5 + + ! DMT_VMA_SRC: D'Almeida's (1987) "Background" modes + ! as default [m] (Zender et al. p.5 Table 1) + ! These modes also summarized in BSM96 p. 73 Table 2 + ! Mass median diameter BSM96 p. 73 Table 2 + ALLOCATE( DMT_VMA_SRC( DST_SRC_NBR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'DMT_VMA_SRC' ) + DMT_VMA_SRC(1) = 0.832d-6 + DMT_VMA_SRC(2) = 4.82d-6 + DMT_VMA_SRC(3) = 19.38d-6 + + ! GSD_ANL_SRC: Geometric standard deviation [fraction] + ! BSM96 p. 73 Table 2 + ALLOCATE( GSD_ANL_SRC( DST_SRC_NBR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'GSD_ANL_SRC' ) + GSD_ANL_SRC(1) = 2.10d0 + GSD_ANL_SRC(2) = 1.90d0 + GSD_ANL_SRC(3) = 1.60d0 + + ! MSS_FRC_SRC: Mass fraction BSM96 p. 73 Table 2 + ALLOCATE( MSS_FRC_SRC( DST_SRC_NBR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'MSS_FRC_SRC' ) + MSS_FRC_SRC(1) = 0.036d0 + MSS_FRC_SRC(2) = 0.957d0 + MSS_FRC_SRC(3) = 0.007d0 + + ! Return to calling program + END SUBROUTINE INIT_DUST_DEAD + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_DUST_DEAD +! +!****************************************************************************** +! Subroutine CLEANUP_DUST_DEAD deallocates all module variables. +! (tdf, bmy, 3/30/04, 1/25/07) +! +! NOTES: +! (1 ) Now deallocate SRCE_FUNC (tdf, bmy, 1/25/07) +!****************************************************************************** +! + !================================================================= + ! CLEANUP_DUST_DEAD begins here! + !================================================================= + IF ( ALLOCATED( ERD_FCT_GEO ) ) DEALLOCATE( ERD_FCT_GEO ) + IF ( ALLOCATED( ERD_FCT_HYDRO ) ) DEALLOCATE( ERD_FCT_HYDRO ) + IF ( ALLOCATED( ERD_FCT_TOPO ) ) DEALLOCATE( ERD_FCT_TOPO ) + IF ( ALLOCATED( ERD_FCT_UNITY ) ) DEALLOCATE( ERD_FCT_UNITY ) + IF ( ALLOCATED( MBL_BSN_FCT ) ) DEALLOCATE( MBL_BSN_FCT ) + IF ( ALLOCATED( LND_FRC_DRY ) ) DEALLOCATE( LND_FRC_DRY ) + IF ( ALLOCATED( MSS_FRC_CACO3 ) ) DEALLOCATE( MSS_FRC_CACO3 ) + IF ( ALLOCATED( MSS_FRC_CLY ) ) DEALLOCATE( MSS_FRC_CLY ) + IF ( ALLOCATED( MSS_FRC_SND ) ) DEALLOCATE( MSS_FRC_SND ) + IF ( ALLOCATED( SFC_TYP ) ) DEALLOCATE( SFC_TYP ) + IF ( ALLOCATED( FLX_LW_DWN_SFC ) ) DEALLOCATE( FLX_LW_DWN_SFC ) + IF ( ALLOCATED( FLX_SW_ABS_SFC ) ) DEALLOCATE( FLX_SW_ABS_SFC ) + IF ( ALLOCATED( TPT_GND ) ) DEALLOCATE( TPT_GND ) + IF ( ALLOCATED( TPT_SOI ) ) DEALLOCATE( TPT_SOI ) + IF ( ALLOCATED( VWC_SFC ) ) DEALLOCATE( VWC_SFC ) + IF ( ALLOCATED( VAI_DST ) ) DEALLOCATE( VAI_DST ) + IF ( ALLOCATED( SRC_STR ) ) DEALLOCATE( SRC_STR ) + IF ( ALLOCATED( PLN_TYP ) ) DEALLOCATE( PLN_TYP ) + IF ( ALLOCATED( PLN_FRC ) ) DEALLOCATE( PLN_FRC ) + IF ( ALLOCATED( TAI ) ) DEALLOCATE( TAI ) + IF ( ALLOCATED( DMT_VWR ) ) DEALLOCATE( DMT_VWR ) + IF ( ALLOCATED( DNS_AER ) ) DEALLOCATE( DNS_AER ) + IF ( ALLOCATED( OVR_SRC_SNK_FRC ) ) DEALLOCATE( OVR_SRC_SNK_FRC ) + IF ( ALLOCATED( OVR_SRC_SNK_MSS ) ) DEALLOCATE( OVR_SRC_SNK_MSS ) + IF ( ALLOCATED( OROGRAPHY ) ) DEALLOCATE( OROGRAPHY ) + IF ( ALLOCATED( DMT_MIN ) ) DEALLOCATE( DMT_MIN ) + IF ( ALLOCATED( DMT_MAX ) ) DEALLOCATE( DMT_MAX ) + IF ( ALLOCATED( DMT_VMA_SRC ) ) DEALLOCATE( DMT_VMA_SRC ) + IF ( ALLOCATED( GSD_ANL_SRC ) ) DEALLOCATE( GSD_ANL_SRC ) + IF ( ALLOCATED( MSS_FRC_SRC ) ) DEALLOCATE( MSS_FRC_SRC ) + IF ( ALLOCATED( SRCE_FUNC ) ) DEALLOCATE( SRCE_FUNC ) + + ! Return to calling program + END SUBROUTINE CLEANUP_DUST_DEAD + +!------------------------------------------------------------------------------ + + END MODULE DUST_DEAD_MOD diff --git a/code/edgar_mod.f b/code/edgar_mod.f new file mode 100644 index 0000000..9679404 --- /dev/null +++ b/code/edgar_mod.f @@ -0,0 +1,2902 @@ +! $Id: edgar_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE EDGAR_MOD +! +!****************************************************************************** +! Module EDGAR_MOD contains variables and routines to read anthropogenic +! emissions from the EDGAR inventory for NOx, CO and SO2. +! (avd, bmy, phs, 7/14/06, 3/10/08) +! +! Module Routines: +! ============================================================================ +! (1 ) EMISS_EDGAR : Driver program for EDGAR emissions +! (2 ) COMPUTE_EDGAR_NOx : Computes EDGAR NOx emissions +! (3 ) READ_EDGAR_NOx : Reads EDGAR NOx data from disk +! (4 ) SEASCL_EDGAR_NOx : Applies seasonal scale factors to anthro NOx +! (5 ) COMPUTE_EDGAR_CO : Computes EDGAR CO emissions +! (6 ) READ_EDGAR_CO : Reads EDGAR CO data from disk +! (7 ) COMPUTE_EDGAR_SO2 : Computes EDGAR SO2 emissions +! (8 ) READ_EDGAR_SO2 : Reads EDGAR SO2 data from disk +! (9 ) SEASCL_EDGAR_ANTH_SO2 : Applies seasonal scale factors to anthro SO2 +! (10) SEASCL_EDGAR_SHIP_SO2 : Applies monthy scale factors to ship SO2 +! (11) READ_EDGAR_DATA : Reads an EDGAR data file for a given sector +! (12) ADD_EDGAR_DATA : Sums EDGAR data for several sectors +! (13) GET_EDGAR_NOx : Returns NOx emissions at grid box (I,J) +! (14) GET_EDGAR_CO : Returns CO emissions at grid box (I,J) +! (15) GET_EDGAR_ANTH_SO2 : Returns SOx anth emissions at grid box (I,J) +! (16) GET_EDGAR_SHIP_SO2 : Returns SOx ship emissions at grid box (I,J) +! (17) GET_EDGAR_TODN : Returns NOx time-of-day scale factors at (I,J) +! (18) READ_AROMATICS : Reads EDGAR aromatics emissions from disk +! (19) READ_C2H4 : Reads EDGAR C2H4 emissions from disk +! (20) READ_C2H2 : Reads EDGAR C2H2 emissions from disk +! (21) READ_AROMATICS_05x0666: Reads EDGAR aromatics emissions from disk +! for 0.5x0.666 resolution +! (22) READ_C2H4_05x0666 : Reads EDGAR C2H4 emissions from disk +! for 0.5x0.666 resolution +! (23) READ_C2H2_05x0666 : Reads EDGAR C2H2 emissions from disk +! for 0.5x0.666 resolution +! (24) INIT_EDGAR : Allocates and zeroes module arrays +! (25) CLEANUP_EDGAR : Deallocates module arrays +! +! GEOS-CHEM modules referenced by "edgar_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) directory_mod.f : Module w/ GEOS-CHEM data & met field dirs +! (3 ) error_mod.f : Module w/ I/O error and NaN check routines +! (4 ) file_mod.f : Module w/ file unit numbers and error checks +! (5 ) future_emissions_mod.f: Module w/ routines for IPCC future emissions +! (6 ) grid_mod.f : Module w/ horizontal grid information +! (7 ) logical_mod.f : Module w/ GEOS-CHEM logical switches! +! (8 ) regrid_1x1_mod.f : Module w/ routines to regrid 1x1 data +! (9 ) time_mod.f : Module w/ routines for computing time and date +! (10) scale_anthro_mod.f : Module w/ routines to get annual scale factor +! +! NOTES: +! (1 ) Now pass the unit string to DO_REGRID_G2G_1x1 (bmy, 8/9/06) +! (2 ) Replaced READ_EDGAR_SCALE with GET_ANNUAL_SCALAR and +! GET_ANNAUL_SCALAR_1x1 from SCALE_ANTHRO_MOD (amv, phs, 3/10/08) +! (3 ) Added EDGAR_NOx_SHIP and EDGAR_CO_SHIP variables. Added SHIP flag +! to GET_EDGAR_NOx and GET_EDGAR_CO, so they can be accessed from +! outside the module (5/13/08, phs) +! (4 ) Added subroutines READ_AROMATICS, READ_C2H4 and READ_C2H2 for GLYX +! chemistry. They are PUBLIC routines as they are used by anthroems.f +! (ccc, 3/2/09) +! (5 ) Added subroutines READ_AROMATICS_05x0666, READ_C2H4_05x0666 and +! READ_C2H2_05x0666 for 0.5x0.666 resolution emissions. +! They are PUBLIC routines as they are used by anthroems.f.(ccc, 3/2/09) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "edgar_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these routines + PUBLIC :: CLEANUP_EDGAR + PUBLIC :: EMISS_EDGAR + PUBLIC :: GET_EDGAR_CO + PUBLIC :: GET_EDGAR_NOx + PUBLIC :: GET_EDGAR_ANTH_SO2 + PUBLIC :: GET_EDGAR_SHIP_SO2 + PUBLIC :: GET_EDGAR_TODN + PUBLIC :: READ_AROMATICS + PUBLIC :: READ_C2H4 + PUBLIC :: READ_C2H2 + PUBLIC :: READ_AROMATICS_05x0666 + PUBLIC :: READ_C2H4_05x0666 + PUBLIC :: READ_C2H2_05x0666 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Variables + REAL*8 :: SEC_IN_SEASON + REAL*8 :: SEC_IN_MONTH + REAL*8 :: SEASON_TAU0 + REAL*8 :: MONTH_TAU0 + CHARACTER(LEN=3) :: SEASON_NAME + CHARACTER(LEN=3) :: MONTH_NAME + + ! Parameters + INTEGER, PARAMETER :: N_HOURS = 24 + REAL*8, PARAMETER :: SEC_IN_DAY = 86400d0 + REAL*8, PARAMETER :: SEC_IN_2000 = SEC_IN_DAY * 366d0 ! leapyear + REAL*8, PARAMETER :: XNUMOL_NO2 = 6.0225d23 / 46d-3 + REAL*8, PARAMETER :: XNUMOL_CO = 6.0225d23 / 28d-3 + REAL*8, PARAMETER :: XNUMOL_SO2 = 6.0225d23 / 64d-3 + + ! Arrays + REAL*8, ALLOCATABLE :: A_CM2(:) + REAL*8, ALLOCATABLE :: EDGAR_NOx(:,:) + REAL*8, ALLOCATABLE :: EDGAR_CO(:,:) + REAL*8, ALLOCATABLE :: EDGAR_SO2(:,:) + REAL*8, ALLOCATABLE :: EDGAR_SO2_SHIP(:,:) + REAL*8, ALLOCATABLE :: EDGAR_NOx_SHIP(:,:) + REAL*8, ALLOCATABLE :: EDGAR_CO_SHIP(:,:) + REAL*8, ALLOCATABLE :: EDGAR_TODN(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE EMISS_EDGAR( YEAR, MONTH ) +! +!****************************************************************************** +! Subroutine EMISS_EDGAR fills emission arrays with emissions based upon +! the EDGAR inventory (avd, bmy, 7/14/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) YEAR (INTEGER) : Compute EDGAR emissions for this year ... +! (2 ) MONTH (INTEGER) : ... and for this month +! +! NOTES: +!****************************************************************************** +! + ! Reference to F90 modules + USE BPCH2_MOD, ONLY : GET_TAU0 + USE LOGICAL_MOD, ONLY : LEDGARCO, LEDGARNOx + USE LOGICAL_MOD, ONLY : LEDGARSHIP, LEDGARSOx + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER, SAVE :: YEAR_SAVE = -1 + INTEGER, SAVE :: MONTH_SAVE = -1 + REAL*8 :: E_NOX(IIPAR,JJPAR) + REAL*8 :: E_NOX_1x1(I1x1,J1x1) + REAL*8 :: E_NOX_HRLY_1x1(I1x1,J1x1) + REAL*8 :: TEMP(I1x1,J1x1,1) + + ! Days of year 2000 + INTEGER :: M(12) = (/ 31, 29, 31, 30, 31, 30, + & 31, 31, 30, 31, 30, 31 /) + + ! Month names + CHARACTER(LEN=3) :: MON(12) = (/ 'JAN', 'FEB', 'MAR', + & 'APR', 'MAY', 'JUN', + & 'JUL', 'AUG', 'SEP', + & 'OCT', 'NOV', 'DEC' /) + + !================================================================= + ! EMISS_EDGAR begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_EDGAR + FIRST = .FALSE. + ENDIF + + ! Get variables for this month + SEC_IN_MONTH = M(MONTH) * SEC_IN_DAY + MONTH_NAME = MON(MONTH) + MONTH_TAU0 = GET_TAU0( MONTH, 1, 1985 ) + + ! Get variables for this season + SELECT CASE( MONTH ) + CASE( 12, 1, 2 ) + SEC_IN_SEASON = ( M(12) + M(1 ) + M(2 ) ) * SEC_IN_DAY + SEASON_NAME = 'DJF' + SEASON_TAU0 = -744d0 + CASE( 3, 4, 5 ) + SEC_IN_SEASON = ( M(3 ) + M(4 ) + M(5 ) ) * SEC_IN_DAY + SEASON_NAME = 'MAM' + SEASON_TAU0 = 1416d0 + CASE( 6, 7, 8 ) + SEC_IN_SEASON = ( M(6 ) + M(7 ) + M(8 ) ) * SEC_IN_DAY + SEASON_NAME = 'JJA' + SEASON_TAU0 = 3624d0 + CASE( 9, 10, 11 ) + SEC_IN_SEASON = ( M(9 ) + M(10) + M(11) ) * SEC_IN_DAY + SEASON_NAME = 'SON' + SEASON_TAU0 = 5832d0 + END SELECT + + !================================================================= + ! CO emissions are read once per year + !================================================================= + IF ( YEAR /= YEAR_SAVE ) THEN + + ! CO + IF ( LEDGARCO ) THEN + IF ( LEDGARSHIP) THEN + CALL COMPUTE_EDGAR_CO( YEAR, EDGAR_CO, EDGAR_CO_SHIP ) + ELSE + CALL COMPUTE_EDGAR_CO( YEAR, EDGAR_CO ) + ENDIF + ENDIF + + ! Reset YEAR_SAVE + YEAR_SAVE = YEAR + ENDIF + + !================================================================= + ! NOx and SOX are annual emissions. However, we will apply a + ! seasonal scale factor to NOx and anthropogenic SO2, and a + ! monthly scale factor to ship SO2. So read these every month. + !================================================================= + IF ( MONTH /= MONTH_SAVE ) THEN + +!--------------- +! prior 3/10/08 +! ! NOx +! IF ( LEDGARNOx ) THEN +! CALL COMPUTE_EDGAR_NOX( YEAR, MONTH, EDGAR_NOx ) +! ENDIF +!--------------- + ! Now always read NOX to get TODN (amv, phs, 3/10/08) + IF ( LEDGARSHIP ) THEN + CALL COMPUTE_EDGAR_NOX( YEAR, MONTH, + & EDGAR_NOx, EDGAR_NOx_SHIP ) + ELSE + CALL COMPUTE_EDGAR_NOX( YEAR, MONTH, + & EDGAR_NOx ) + ENDIF + + ! SO2 + IF ( LEDGARSOx ) THEN + IF ( LEDGARSHIP ) THEN + CALL COMPUTE_EDGAR_SO2( YEAR, MONTH, + & EDGAR_SO2, EDGAR_SO2_SHIP ) + ELSE + CALL COMPUTE_EDGAR_SO2( YEAR, MONTH, + & EDGAR_SO2 ) + ENDIF + ENDIF + + ! Reset MONTH_SAVE + MONTH_SAVE = MONTH + ENDIF + + !================================================================= + ! Print EDGAR emission totals + !================================================================= + CALL EDGAR_TOTAL_Tg( YEAR, MONTH ) + + !### For Debug + !CALL OUTPUT_TOTAL_2D( 'EDGAR NOx', EDGAR_NOx, 'kg/season' ) + !CALL OUTPUT_TOTAL_2D( 'EDGAR CO', EDGAR_CO , 'kg/yr' ) + !CALL OUTPUT_TOTAL_2D( 'EDGAR SO2', EDGAR_SO2, 'kg/season' ) + + ! Return to calling program + END SUBROUTINE EMISS_EDGAR + +!------------------------------------------------------------------------------ + + SUBROUTINE COMPUTE_EDGAR_NOx( YEAR, MONTH, E_NOx, E_NOx_SHIP ) +! +!****************************************************************************** +! Subroutine COMPUTE_EDGAR_NOx computes the total EDGAR NOx emissions +! (summing over several individual sectors) and also the time-of-day +! scale factors for NOx. (avd, bmy, 7/14/06) +! +! EDGAR NOx is read as [kg NO2/yr], then converted to [molec/cm2/s] when +! you call the access function GET_EDGAR_NOx( I, J, MOLEC_CM2_S=.TRUE. ) +! +! Arguments as Input: +! ============================================================================ +! (1 ) YEAR (INTEGER) : Current year +! (2 ) MONTH (INTEGER) : Current month +! +! Arguments as Output: +! ============================================================================ +! (3 ) E_NOX (REAL*4 ) : EDGAR NOx emissions [kg NO2/season] +! (4 ) E_NOX_SHIP (REAL*4 ) : EDGAR NOx ship emissions [kg NO2/season] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE LOGICAL_MOD, ONLY : LEDGARSHIP + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE TIME_MOD, ONLY : EXPAND_DATE + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_1x1 + + ! (lzh,02/01/2015) update regridding + USE REGRID_A2A_MOD, ONLY : DO_REGRID_A2A + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + REAL*8, INTENT(OUT) :: E_NOX(IIPAR,JJPAR) + REAL*8, INTENT(OUT), OPTIONAL :: E_NOX_SHIP(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J, H, YYYYMMDD + REAL*8 :: E_NOX_1x1(I1x1,J1x1) + REAL*8 :: E_NOX_SHIP_1x1(I1x1,J1x1) + REAL*8 :: E_NOX_HRLY_1x1(I1x1,J1x1,N_HOURS) + REAL*8 :: SC_NOx_1x1(I1x1,J1x1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + REAL*8 :: TEMP_HRLY(IIPAR,JJPAR) + REAL*8 :: TEMP_TOT(IIPAR,JJPAR) + CHARACTER(LEN=255) :: NAME + + ! (lzh, 02/01/2015) + CHARACTER(LEN=255) :: LLFILENAME + REAL*8 :: INGRID(I1x1,J1x1) + REAL*8 :: OUTGRID(IIPAR,JJPAR) + + !================================================================= + ! COMPUTE_EDGAR_NOx begins here! + !================================================================= + + ! Initialize + E_NOx_1x1 = 0d0 + E_NOX_HRLY_1x1 = 0d0 + GEOS_1x1 = 0d0 + SC_NOx_1x1 = 1d0 + + !---------------------------------- + ! Read NOx data from disk + !---------------------------------- + + ! Read EDGAR anthro and ship NOx, and hourly NOx [kg NO2/yr] + CALL READ_EDGAR_NOx( E_NOx_1x1, E_NOX_SHIP_1x1, E_NOx_HRLY_1x1 ) + + !---------------------------------- + ! Compute NOx hourly scale factors + ! (these average out to 1.0) + !---------------------------------- + + ! Regrid anthro emissions to current resolution + !GEOS_1x1(:,:,1) = E_NOx_1x1(:,:) + !CALL DO_REGRID_1x1( 'unitless', GEOS_1x1, TEMP_TOT ) + + ! (lzh,02/01/2015) + ! File with lat/lon edges for regridding + LLFILENAME = TRIM( DATA_DIR_1x1) // + & 'MAP_A2A_Regrid_201203/MAP_A2A_latlon_geos1x1.nc' + + ! Regrid anthro emissions to current resolution + INGRID = E_NOx_1x1(:,:) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, TEMP_TOT, IS_MASS=1, + & netCDF=.TRUE. ) + + ! Loop over hours + DO H = 1, N_HOURS + + ! Regrid hourly emissions to current resolution + !GEOS_1x1(:,:,1) = E_NOx_HRLY_1x1(:,:,H) + !CALL DO_REGRID_1x1( 'unitless', GEOS_1x1, TEMP_HRLY ) + + ! (lzh,02/01/2015) + INGRID = E_NOx_HRLY_1x1(:,:,H) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, TEMP_HRLY, IS_MASS=1, + & netCDF=.TRUE. ) + + ! Scale factors are just the normalized hourly emissions + DO J = 1, JJPAR + DO I = 1, IIPAR + IF ( TEMP_TOT(I,J) > 0d0 ) THEN + EDGAR_TODN(I,J,H) = TEMP_HRLY(I,J) / TEMP_TOT(I,J) + ELSE + EDGAR_TODN(I,J,H) = 1d0 + ENDIF + ENDDO + ENDDO + ENDDO + + !---------------------------------- + ! Scale NOx from 2000 -> this year + !---------------------------------- +!------------------ +! prior to 3/4/08 +! ! Skip scaling if it's 2000 +! IF ( YEAR /= 2000 ) THEN +! +! ! Scale factor file +! NAME = 'NOxScalar-YYYY-2000' +! +! ! YYYYMMDD date +! YYYYMMDD = ( MAX( MIN( YEAR, 2002 ), 1985 ) * 10000 ) + 0101 +! +! ! Replace YYYY with year +! CALL EXPAND_DATE( NAME, YYYYMMDD, 000000 ) +! +! ! Read NOx scale file +! CALL READ_EDGAR_SCALE( NAME, 71, 2000, SC_NOx_1x1 ) +! +! ENDIF +! + CALL GET_ANNUAL_SCALAR_1x1( 71, 2000, YEAR, SC_NOx_1x1 ) + + ! Apply scale factors at 1x1 + GEOS_1x1(:,:,1) = E_NOx_1x1(:,:) * SC_NOx_1x1(:,:) + + !---------------------------------- + ! Do the regridding + !---------------------------------- + + ! Regrid NOx emissions to current model resolution [kg/yr] + !CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, E_NOx ) + ! (lzh,02/01/2015) + INGRID = GEOS_1x1(:,:,1) !! E_NOx_1x1(:,:) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_NOx = OUTGRID + + !---------------------------------- + ! Scale ship NOX and regrid + !---------------------------------- + + IF ( LEDGARSHIP ) THEN + + ! Re-initialize + GEOS_1x1(:,:,:) = 0d0 + + ! Apply scale factors at 1x1 + GEOS_1x1(:,:,1) = E_NOX_SHIP_1x1(:,:) * SC_NOX_1x1(:,:) + + ! Regrid NOX emissions to current model resolution [kg/yr] + !CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, E_NOX_SHIP ) + ! (lzh,02/01/2015) + INGRID = GEOS_1x1(:,:,1) !! E_NOX_SHIP_1x1(:,:) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_NOX_SHIP = OUTGRID + + ENDIF + + ! Return to calling program + END SUBROUTINE COMPUTE_EDGAR_NOx + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_EDGAR_NOx( E_1x1, E_SHIP_1x1, E_HRLY_1x1 ) +! +!****************************************************************************** +! Subroutine READ_EDGAR_NOx reads EDGAR NOx emissions for the various sectors +! and returns total and hourly emissions. The EDGAR emissions are on the +! GENERIC 1x1 GRID and are regridded to the GEOS 1x1 grid. +! (avd, bmy, 7/14/06, 8/9/06) +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_1x1 (REAL*8 ) : Anthro NOx on GEOS 1x1 grid [kg NO2/season] +! (2 ) E_SHIP_1x1 (REAL*8 ) : Ship NOx on GEOS 1x1 grid [kg NO2/season] +! (2 ) E_HRLY_1x1 (REAL*8 ) : Hourly NOx on GEOS 1x1 grid [kg NO2/season] +! +! NOTES: +! (1 ) Now pass the unit string to DO_REGRID_G2G_1x1 (bmy, 8/9/06) +!****************************************************************************** +! + ! References to F90 modules + USE LOGICAL_MOD, ONLY : LEDGARSHIP + USE REGRID_1x1_MOD, ONLY : DO_REGRID_G2G_1x1 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(OUT) :: E_1x1(I1x1,J1x1) + REAL*8, INTENT(OUT) :: E_SHIP_1x1(I1x1,J1x1) + REAL*8, INTENT(OUT) :: E_HRLY_1x1(I1x1,J1x1,N_HOURS) + + ! Local variables + INTEGER :: H + REAL*4 :: E_IN(I1x1,J1x1) + REAL*8 :: SC(N_HOURS) + REAL*8 :: T_1x1(I1x1,J1x1-1) + REAL*8 :: T_SHIP_1x1(I1x1,J1x1-1) + REAL*8 :: T_HRLY_1x1(I1x1,J1x1-1,N_HOURS) + + !================================================================= + ! READ_EDGAR_NOx begins here! + !================================================================= + + ! Initialize + SC = 0e0 + E_IN = 0e0 + E_1x1 = 0d0 + E_SHIP_1x1 = 0d0 + E_HRLY_1x1 = 0d0 + T_1x1 = 0d0 + T_SHIP_1x1 = 0d0 + T_HRLY_1x1 = 0d0 + + !----------------------------------------------------------------- + ! F10 - Industry (fuel combustion) + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = (/ 0.75d0, 0.75d0, 0.78d0, 0.82d0, 0.88d0, 0.95d0, + & 1.02d0, 1.09d0, 1.16d0, 1.22d0, 1.28d0, 1.30d0, + & 1.22d0, 1.24d0, 1.25d0, 1.16d0, 1.08d0, 1.01d0, + & 0.95d0, 0.90d0, 0.85d0, 0.81d0, 0.78d0, 0.75d0 /) + + ! Read data + CALL READ_EDGAR_DATA( 'f1000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! F20 - Power Generation (fuel combustion) + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = (/ 0.79d0, 0.72d0, 0.72d0, 0.71d0, 0.74d0, 0.80d0, + & 0.92d0, 1.08d0, 1.19d0, 1.22d0, 1.21d0, 1.21d0, + & 1.17d0, 1.15d0, 1.14d0, 1.13d0, 1.10d0, 1.07d0, + & 1.04d0, 1.02d0, 1.02d0, 1.01d0, 0.96d0, 0.88d0 /) + + ! Read data + CALL READ_EDGAR_DATA( 'f2000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! F30 - Conversion (fuel combustion) + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = 1e0 + + ! Read data + CALL READ_EDGAR_DATA( 'f3000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! F40 - Residential (fuel combustion) + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = (/ 0.38d0, 0.36d0, 0.36d0, 0.36d0, 0.37d0, 0.50d0, + & 1.19d0, 1.53d0, 1.57d0, 1.56d0, 1.35d0, 1.16d0, + & 1.07d0, 1.06d0, 1.00d0, 0.98d0, 0.99d0, 1.12d0, + & 1.41d0, 1.52d0, 1.39d0, 1.35d0, 1.00d0, 0.42d0 /) + + ! Read data + CALL READ_EDGAR_DATA( 'f4000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! F51 - Road Transport (fuel combustion) + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = (/ 0.19d0, 0.09d0, 0.06d0, 0.05d0, 0.09d0, 0.22d0, + & 0.86d0, 1.84d0, 1.86d0, 1.41d0, 1.24d0, 1.20d0, + & 1.32d0, 1.44d0, 1.45d0, 1.59d0, 2.03d0, 2.08d0, + & 1.51d0, 1.06d0, 0.74d0, 0.62d0, 0.61d0, 0.44d0 /) + + ! Read data + CALL READ_EDGAR_DATA( 'f5100nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! F54 - Non-Road Land Transport (fuel combustion) + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = (/ 0.19d0, 0.09d0, 0.06d0, 0.05d0, 0.09d0, 0.22d0, + & 0.86d0, 1.84d0, 1.86d0, 1.41d0, 1.24d0, 1.20d0, + & 1.32d0, 1.44d0, 1.45d0, 1.59d0, 2.03d0, 2.08d0, + & 1.51d0, 1.06d0, 0.74d0, 0.62d0, 0.61d0, 0.44d0 /) + + ! Read data + CALL READ_EDGAR_DATA( 'f5400nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + +!------------------------------------------------------------------------------ +! NOTE: We don't use EDGAR aircraft data, so comment out. (avd, bmy, 7/14/06) +! !------------------------------------------------ +! ! F57 - Aircraft (fuel combustion) +! !------------------------------------------------ +! SC(:) = (/ 0.19d0, 0.09d0, 0.06d0, 0.05d0, 0.09d0, 0.22d0, +! & 0.86d0, 1.84d0, 1.86d0, 1.41d0, 1.24d0, 1.20d0, +! & 1.32d0, 1.44d0, 1.45d0, 1.59d0, 2.03d0, 2.08d0, +! & 1.51d0, 1.06d0, 0.74d0, 0.62d0, 0.61d0, 0.44d0 /) +! +! ! Read data +! CALL READ_EDGAR_FILE( 'f5700nox', 1, E_IN )! +! +! ! Add into cumulative arrays +! CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) +!------------------------------------------------------------------------------ + + !----------------------------------------------------------------- + ! F58 - Shipping (fuel combustion) + !----------------------------------------------------------------- + IF ( LEDGARSHIP ) THEN + + ! Hourly scale factors + SC(:) = 1d0 + + ! Read data + CALL READ_EDGAR_DATA( 'f5800nox(IEA)', 1, E_IN ) + + ! Add into cumulative arrays +!------------------------------------------- +! prior to 5/13/08 +! CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) +!------------------------------------------ + CALL ADD_EDGAR_DATA( E_IN, T_SHIP_1x1 ) + ENDIF + + !----------------------------------------------------------------- + ! F80 - Oil Production (fuel combustion) + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = 1d0 + + ! Read data + CALL READ_EDGAR_DATA( 'f8000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! I10 - Iron and Steel Production + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = 1d0 + + ! Read data + CALL READ_EDGAR_DATA( 'i1000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! I30 - Chemical Production + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = 1d0 + + ! Read data + CALL READ_EDGAR_DATA( 'i3000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! I40 - Cement Production + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = 1d0 + + ! Read data + CALL READ_EDGAR_DATA( 'i4000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! I50 - Pulp and Paper Production + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = 1d0 + + ! Read data + CALL READ_EDGAR_DATA( 'i5000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! W40 - Waste Incineration + !----------------------------------------------------------------- + + ! Hourly scale factors + SC(:) = 1d0 + + ! Read data + CALL READ_EDGAR_DATA( 'w4000nox', 1, E_IN ) + + ! Add into cumulative arrays + CALL ADD_EDGAR_DATA( E_IN, T_1x1, SC, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! Force a seasonal variation onto the anthropogenic NOx emissions + ! by applying seasonal scale factors. The scale factors are the + ! ratio of (seasonal GEIA NOx / annual GEIA NOx). + ! + ! The emissions on which these scale factors are based are + ! defined on the GENERIC 1 x 1 GRID, so apply scale factors + ! BEFORE regridding! + !----------------------------------------------------------------- + + ! Convert [kg NO2/yr] to [kg NO2/season] + CALL SEASCL_EDGAR_NOx( T_1x1, T_SHIP_1x1, T_HRLY_1x1 ) + + !----------------------------------------------------------------- + ! Regrid from GENERIC 1x1 grid to GEOS 1x1 grid + !----------------------------------------------------------------- + + ! Total NOx [kg NO2/season] + CALL DO_REGRID_G2G_1x1( 'kg/season', T_1x1, E_1x1 ) + CALL DO_REGRID_G2G_1x1( 'kg/season', T_SHIP_1x1, E_SHIP_1x1 ) + + ! Hourly NOx [kg NO2/season] + DO H = 1, N_HOURS + CALL DO_REGRID_G2G_1x1( 'kg/season', T_HRLY_1x1(:,:,H), + & E_HRLY_1x1(:,:,H) ) + ENDDO + + ! Return to calling program + END SUBROUTINE READ_EDGAR_NOx + +!------------------------------------------------------------------------------ + + SUBROUTINE SEASCL_EDGAR_NOx( E_NOx_1x1, E_NOx_SHIP_1x1, + & E_NOx_HRLY_1x1 ) +! +!****************************************************************************** +! Subroutine SEASCL_EDGAR_NOx applies seasonal scale factors (computed +! as the ratio of seasonal/total GEIA NOx emissions) to the annual EDGAR +! anthropogenic NOx emissions. This is required to impose a seasonality +! onto the EDGAR NOx emissions, which are reported as per year. +! (avd, bmy, 7/14/06) +! +! NOTE: NOx scale factors are on the GENERIC 1x1 GRID. +! +! Arguments as Input: +! ============================================================================ +! (1 ) E_NOx_1x1 (REAL*8 ) : Anthro NOx 1x1 array [kg NO2/yr] +! (2 ) E_NOx_1x1 (REAL*8 ) : Anthro NOx 1x1 hourly array [kg NO2/yr] +! (3 ) E_NOx_SHIP_1x1 (REAL*8 ) : Ship NOx 1x1 array [kg NO2/yr] +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_NOx_1x1 (REAL*8 ) : Anthro NOx 1x1 array [kg NO2/season] +! (2 ) E_NOx_1x1 (REAL*8 ) : Anthro NOx 1x1 hourly array [kg NO2/season] +! (3 ) E_NOx_SHIP_1x1 (REAL*8 ) : Ship NOx 1x1 array [kg NO2/yr] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: E_NOx_1x1(I1x1,J1x1-1) + REAL*8, INTENT(INOUT) :: E_NOx_SHIP_1x1(I1x1,J1x1-1) + REAL*8, INTENT(INOUT) :: E_NOx_HRLY_1x1(I1x1,J1x1-1,N_HOURS) + + ! Local variables + INTEGER :: H + REAL*4 :: ARRAY(I1x1,J1x1-1,1) + REAL*8 :: THIS_TAU + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! SEASCL_EDGAR_NOx begins here! + !================================================================= + + ! File name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'EDGAR_200607/NOx/anth_NOx_scale.' // SEASON_NAME // + & '.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - SEASCL_EDGAR_NOx: Reading ', a ) + + ! Read scale factor data [unitless] + CALL READ_BPCH2( FILENAME, 'EDGAR-2D', 71, + & SEASON_TAU0, I1x1, J1x1-1, + & 1, ARRAY, QUIET=.TRUE. ) + + + ! Apply seasonal scale factors to anthro and ship NOx + E_NOx_1x1(:,:) = E_NOx_1x1(:,:) * ARRAY(:,:,1) + E_NOx_SHIP_1x1(:,:) = E_NOx_SHIP_1x1(:,:) * ARRAY(:,:,1) + + ! Apply seasonal scale factors to hourly anthro NOx + DO H = 1, N_HOURS + E_NOx_HRLY_1x1(:,:,H) = E_NOx_HRLY_1x1(:,:,H) * ARRAY(:,:,1) + ENDDO + + ! Return to calling program + END SUBROUTINE SEASCL_EDGAR_NOx + +!------------------------------------------------------------------------------ + + SUBROUTINE COMPUTE_EDGAR_CO( YEAR, E_CO, E_CO_SHIP ) +! +!****************************************************************************** +! Subroutine COMPUTE_EDGAR_CO computes the total EDGAR CO emissions, summing +! over several individual sectors. (avd, bmy, 7/14/06) +! +! EDGAR CO is read as [kg CO/yr], then converted to [molec/cm2/s] when you +! call the access function GET_EDGAR_CO( I, J, MOLEC_CM2_S=.TRUE. ) +! +! Arguments as Input: +! ============================================================================ +! (1 ) YEAR (INTEGER) : Current year +! +! Arguments as Output: +! ============================================================================ +! (2 ) E_CO (REAL*4 ) : EDGAR CO emissions [kg CO/year] +! (3 ) E_CO_SHIP (REAL*4 ) : EDGAR CO shipping emissions [kg CO/year] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE LOGICAL_MOD, ONLY : LEDGARSHIP + USE TIME_MOD, ONLY : EXPAND_DATE + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_1x1 + + USE REGRID_A2A_MOD, ONLY : DO_REGRID_A2A ! (lzh,02/01/2015) + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR + REAL*8, INTENT(OUT) :: E_CO(IIPAR,JJPAR) + REAL*8, INTENT(OUT), OPTIONAL :: E_CO_SHIP(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J, H, YYYYMMDD + REAL*8 :: E_CO_1x1(I1x1,J1x1) + REAL*8 :: E_CO_SHIP_1x1(I1x1,J1x1) + REAL*8 :: SC_CO_1x1(I1x1,J1x1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + CHARACTER(LEN=255) :: NAME + + ! (lzh, 02/01/2015) + CHARACTER(LEN=255) :: LLFILENAME + REAL*8 :: INGRID(I1x1,J1x1) + REAL*8 :: OUTGRID(IIPAR,JJPAR) + + !================================================================= + ! COMPUTE_EDGAR_CO begins here! + !================================================================= + + ! Initialize + GEOS_1x1(:,:,:) = 0e0 + SC_CO_1x1(:,:) = 1e0 + + !---------------------------------- + ! Read CO data from disk + !---------------------------------- + + ! Read EDGAR total NOx and hourly NOx [kg/yr] + CALL READ_EDGAR_CO( E_CO_1x1, E_CO_SHIP_1x1 ) + + !---------------------------------- + ! Scale CO from 2000 -> this year + !---------------------------------- +!------------------- +! prior 3/4/08 +! ! Skip scaling if it's 2000 +! IF ( YEAR /= 2000 ) THEN +! +! ! Scale factor file +! NAME = 'COScalar-YYYY-2000' +! +! ! YYYYMMDD date +! YYYYMMDD = ( MAX( MIN( YEAR, 2002 ), 1985 ) * 10000 ) + 0101 +! +! ! Replace YYYY with year +! CALL EXPAND_DATE( NAME, YYYYMMDD, 000000 ) +! +! ! Read CO scale file +! CALL READ_EDGAR_SCALE( NAME, 72, 2000, SC_CO_1x1 ) +! +! ENDIF +!------------------- + CALL GET_ANNUAL_SCALAR_1x1( 72, 2000, YEAR, SC_CO_1x1 ) + + ! Apply scale factors at 1x1 + GEOS_1x1(:,:,1) = E_CO_1x1(:,:) * SC_CO_1x1(:,:) + + !---------------------------------- + ! Do the regridding + !---------------------------------- + + ! Regrid CO emissions to current model resolution [kg/yr] + !CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, E_CO ) + + ! (lzh,02/01/2015) + ! File with lat/lon edges for regridding + LLFILENAME = TRIM( DATA_DIR_1x1) // + & 'MAP_A2A_Regrid_201203/MAP_A2A_latlon_geos1x1.nc' + + ! Regrid anthro emissions to current resolution + INGRID = GEOS_1x1(:,:,1) !! E_NOx_1x1(:,:) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_CO = OUTGRID + + !---------------------------------- + ! Scale ship CO and regrid + !---------------------------------- + + IF ( LEDGARSHIP ) THEN + + ! Re-initialize + GEOS_1x1(:,:,:) = 0d0 + + ! Apply scale factors at 1x1 + GEOS_1x1(:,:,1) = E_CO_SHIP_1x1(:,:) * SC_CO_1x1(:,:) + + ! Regrid CO emissions to current model resolution [kg/yr] + !CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, E_CO_SHIP ) + ! (lzh, 02/01/2015) + INGRID = GEOS_1x1(:,:,1) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_CO_SHIP = OUTGRID + + ENDIF + + ! Return to calling program + END SUBROUTINE COMPUTE_EDGAR_CO + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_EDGAR_CO( E_CO_1x1, E_CO_SHIP_1x1 ) +! +!****************************************************************************** +! Subroutine READ_EDGAR_CO reads EDGAR CO emissions for the various sectors +! and returns total and hourly emissions. The EDGAR emissions are on the +! GENERIC 1x1 GRID and are regridded to the GEOS 1x1 grid. +! (avd, bmy, 7/14/06, 8/9/06) +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_CO_1x1 (REAL*4) : Total EDGAR CO emissions on GEOS 1x1 grid [kg/yr] +! +! NOTES: +! (1 ) Now pass the unit string to DO_REGRID_G2G_1x1 (bmy, 8/9/06) +!****************************************************************************** +! + ! Reference to F90 modules + USE LOGICAL_MOD, ONLY : LEDGARSHIP + USE REGRID_1x1_MOD, ONLY : DO_REGRID_G2G_1x1 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(OUT) :: E_CO_1x1(I1x1,J1x1) + REAL*8, INTENT(OUT) :: E_CO_SHIP_1x1(I1x1,J1x1) + + ! Local variables + REAL*4 :: E_IN(I1x1,J1x1-1) + REAL*8 :: T_CO_1x1(I1x1,J1x1-1) + REAL*8 :: T_CO_SHIP_1x1(I1x1,J1x1-1) + + !================================================================= + ! READ_EDGAR_CO begins here! + !================================================================= + + ! Initialize + E_IN = 0e0 + E_CO_1x1 = 0d0 + E_CO_SHIP_1x1 = 0d0 + T_CO_1x1 = 0d0 + T_CO_SHIP_1x1 = 0d0 + + !------------------------------------------------ + ! Compute total CO for all sectors + !------------------------------------------------ + + ! F10 - Industrial (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f1000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! F20 - Power Generation (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f2000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! F30 - Conversion (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f3000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! F40 - Residential + Commercial + Other (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f4000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! F51 - Road Transport (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f5100co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! F54 - Land (Non-Road) Transport (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f5400co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! F57 - Air Transport (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f5700co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! F58 - Shipping (fossil fuel combustion) + IF ( LEDGARSHIP ) THEN + CALL READ_EDGAR_DATA( 'f5800co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_SHIP_1x1 ) + ENDIF + + ! F80 - Oil Production (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f8000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! I10 - Iron and Steel Production + CALL READ_EDGAR_DATA( 'i1000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! I20 - Non-Ferrous Production + CALL READ_EDGAR_DATA( 'i2000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! I50 - Pulp and Paper Production + CALL READ_EDGAR_DATA( 'i5000co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + ! W40 - Waste Incineration + CALL READ_EDGAR_DATA( 'w4095co', 4, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_CO_1x1 ) + + !------------------------------------------------ + ! Regrid from GENERIC 1x1 GRID to GEOS 1x1 GRID + !------------------------------------------------ + + ! Anthro CO [kg/yr] + CALL DO_REGRID_G2G_1x1( 'kg/yr', T_CO_1x1, E_CO_1x1 ) + + ! Ship CO [kg/yr] + CALL DO_REGRID_G2G_1x1( 'kg/yr', T_CO_SHIP_1x1, E_CO_SHIP_1x1 ) + + ! Return to calling program + END SUBROUTINE READ_EDGAR_CO + +!------------------------------------------------------------------------------ + + SUBROUTINE COMPUTE_EDGAR_SO2( YEAR, MONTH, E_SO2, E_SO2_SHIP ) +! +!****************************************************************************** +! Subroutine COMPUTE_EDGAR_SO2 computes the total EDGAR SO2 emissions +! (summing over several individual sectors) and also the time-of-day scale +! factors for SO2. (avd, bmy, 7/14/06) +! +! EDGAR anthropogenic SO2 is read as [kg SO2/yr], then converted to [kg/s] +! when you call the access functions GET_EDGAR_ANTH_SO2( I, J, KG_S=.TRUE. ) +! and GET_EDGAR_ANTH_SO2( I, J, KG_S=.TRUE. ) +! +! Arguments as Input: +! ============================================================================ +! (1 ) YEAR (INTEGER) : Current year +! (2 ) MONTH (INTEGER) : Current month +! +! Arguments as Output: +! ============================================================================ +! (3 ) E_SO2 (REAL*4 ) : EDGAR anthropogenic SO2 emissions +! (4 ) E_SO2_SHIP (REAL*4 ) : EDGAR ship exhaust SO2 emissions +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE LOGICAL_MOD, ONLY : LEDGARSHIP + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE TIME_MOD, ONLY : EXPAND_DATE + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_1x1 + + USE REGRID_A2A_MOD, ONLY : DO_REGRID_A2A ! (lzh,02/01/2015) + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + REAL*8, INTENT(OUT) :: E_SO2(IIPAR,JJPAR) + REAL*8, INTENT(OUT), OPTIONAL :: E_SO2_SHIP(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J, H, YYYYMMDD + REAL*8 :: E_SO2_1x1(I1x1,J1x1) + REAL*8 :: E_SO2_SHIP_1x1(I1x1,J1x1) + REAL*8 :: SC_SO2_1x1(I1x1,J1x1) + REAL*8 :: GEOS_1x1(I1x1,J1x1,1) + CHARACTER(LEN=255) :: NAME + + ! (lzh, 02/01/2015) + CHARACTER(LEN=255) :: LLFILENAME + REAL*8 :: INGRID(I1x1,J1x1) + REAL*8 :: OUTGRID(IIPAR,JJPAR) + + !================================================================= + ! COMPUTE_EDGAR_SO2 begins here! + !================================================================= + + ! Initialize + GEOS_1x1(:,:,:) = 0d0 + SC_SO2_1x1(:,:) = 1d0 + + !---------------------------------- + ! Read SO2 data from disk + !---------------------------------- + + ! Read EDGAR anthro SO2 and ship SO2 + CALL READ_EDGAR_SO2( E_SO2_1x1, E_SO2_SHIP_1x1 ) + + !---------------------------------- + ! Scale SO2 from 2000 -> this year + !---------------------------------- +!---------------- +! prior to 3/10/08 +! ! Skip scaling if it's 2000 +! IF ( YEAR /= 2000 ) THEN +! +! ! Scale factor file +! NAME = 'SOxScalar-YYYY-2000' +! +! ! YYYYMMDD date +! YYYYMMDD = ( MAX( MIN( YEAR, 2002 ), 1998 ) * 10000 ) + 0101 +! +! ! Replace YYYY with year +! CALL EXPAND_DATE( NAME, YYYYMMDD, 000000 ) +! +! ! Read SO2 scale file +! CALL READ_EDGAR_SCALE( NAME, 73, 2000, SC_SO2_1x1 ) +! +! ENDIF + + CALL GET_ANNUAL_SCALAR_1x1( 73, 2000, YEAR, SC_SO2_1x1 ) + + !---------------------------------- + ! Scale anthro SO2 and regrid + !---------------------------------- + + ! Apply scale factors at 1x1 + GEOS_1x1(:,:,1) = E_SO2_1x1(:,:) * SC_SO2_1x1(:,:) + + ! Regrid SO2 emissions to current model resolution [kg/yr] + !CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, E_SO2 ) + ! (lzh, 02/01/2015) + ! File with lat/lon edges for regridding + LLFILENAME = TRIM( DATA_DIR_1x1) // + & 'MAP_A2A_Regrid_201203/MAP_A2A_latlon_geos1x1.nc' + + INGRID = GEOS_1x1(:,:,1) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_SO2 = OUTGRID + + !---------------------------------- + ! Scale ship SO2 and regrid + !---------------------------------- + + IF ( LEDGARSHIP ) THEN + + ! Re-initialize + GEOS_1x1(:,:,:) = 0d0 + + ! Apply scale factors at 1x1 + GEOS_1x1(:,:,1) = E_SO2_SHIP_1x1(:,:) * SC_SO2_1x1(:,:) + + ! Regrid SO2 emissions to current model resolution [kg/yr] + !CALL DO_REGRID_1x1( 'kg/yr', GEOS_1x1, E_SO2_SHIP ) + ! (lzh, 02/01/2015) + INGRID = GEOS_1x1(:,:,1) + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_SO2_SHIP = OUTGRID + + ENDIF + + ! Return to calling program + END SUBROUTINE COMPUTE_EDGAR_SO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_EDGAR_SO2( E_SO2_1x1, E_SO2_SHIP_1x1 ) +! +!****************************************************************************** +! Subroutine READ_EDGAR_SO2 reads EDGAR SO2 emissions for the various sectors +! and returns both anthropogenic SO2 emissions and ship exhaust SO2 emissions. +! The EDGAR emissions are on the GENERIC 1x1 GRID and are regridded to the +! GEOS 1x1 GRID. (avd, bmy, 7/14/06, 8/9/06) +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_SO2_1x1 (REAL*8) : EDGAR anth SO2 on GEOS 1x1 GRID [kg/season] +! (2 ) E_SO2_SHIP_1x1 (REAL*8) : EDGAR ship SO2 on GEOS 1x1 GRID [kg/season] +! +! NOTES: +! (1 ) Now pass the unit string to DO_REGRID_G2G_1x1 (bmy, 8/9/06) +!****************************************************************************** +! + ! Reference to F90 modules + USE LOGICAL_MOD, ONLY : LEDGARSHIP + USE REGRID_1x1_MOD, ONLY : DO_REGRID_G2G_1x1 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(OUT) :: E_SO2_1x1(I1x1,J1x1) + REAL*8, INTENT(OUT) :: E_SO2_SHIP_1x1(I1x1,J1x1) + + ! Local variables + REAL*4 :: E_IN(I1x1,J1x1-1) + REAL*8 :: T_SO2_1x1(I1x1,J1x1-1) + REAL*8 :: T_SO2_SHIP_1x1(I1x1,J1x1-1) + + !================================================================= + ! READ_EDGAR_SO2 begins here! + !================================================================= + + ! Initialize + E_IN = 0e0 + E_SO2_1x1 = 0d0 + E_SO2_SHIP_1x1 = 0d0 + T_SO2_1x1 = 0d0 + T_SO2_SHIP_1x1 = 0d0 + + !----------------------------------------------------------------- + ! Read anthropogenic SO2 and ship SO2 emissions + ! (on GENERIC 1x1 GRID) + !----------------------------------------------------------------- + + ! F10 - industrial (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f1000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! F20 - Power Generation (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f2000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! F30 - Conversion (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f3000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! F40 - Residential + Commercial + Other (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f4000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! F51 - Road Transport (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f5100so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! F54 - Land (Non-Road) Transport (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f5400so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! F57 - Air Transport (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f5700so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! F58 - Shipping (fossil fuel combustion) + ! NOTE: Add into separate array for compatibility w/ sulfate_mod.f + IF ( LEDGARSHIP ) THEN + CALL READ_EDGAR_DATA( 'f5800so2(IEA)', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_SHIP_1x1 ) + ENDIF + + ! F80 - Oil Production (fossil fuel combustion) + CALL READ_EDGAR_DATA( 'f8000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! I10 - Iron and Steel Production + CALL READ_EDGAR_DATA( 'i1000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! I20 - Non-Ferrous Production + CALL READ_EDGAR_DATA( 'i2000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! I30 - Chemical Production + CALL READ_EDGAR_DATA( 'i3000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! I40 - Cement Production + CALL READ_EDGAR_DATA( 'i4000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! I50 - Pulp and Paper Production + CALL READ_EDGAR_DATA( 'i5000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + ! W40 - Waste Incineration + CALL READ_EDGAR_DATA( 'w4000so2', 26, E_IN ) + CALL ADD_EDGAR_DATA( E_IN, T_SO2_1x1 ) + + !----------------------------------------------------------------- + ! Force a seasonal variation onto the anthropogenic SO2 emissions + ! by applying seasonal scale factors. The scale factors are the + ! ratio of (seasonal GEIA SO2 / annual GEIA SO2). + ! + ! The emissions on which these scale factors are based are + ! defined on the GENERIC 1 x 1 GRID, so apply scale factors + ! BEFORE regridding! + !----------------------------------------------------------------- + + ! Convert [kg SO2/yr] to [kg SO2/season] + CALL SEASCL_EDGAR_ANTH_SO2( T_SO2_1x1 ) + + !----------------------------------------------------------------- + ! Regrid SO2 from GENERIC 1x1 GRID to GEOS 1x1 GRID + !----------------------------------------------------------------- + + ! Anthro SO2 [kg/season] + CALL DO_REGRID_G2G_1x1( 'kg/season', T_SO2_1x1, E_SO2_1x1 ) + + ! Ship SO2 [kg/season] + CALL DO_REGRID_G2G_1x1( 'kg/season', T_SO2_SHIP_1x1, + & E_SO2_SHIP_1x1 ) + + !----------------------------------------------------------------- + ! Force a monthly variation onto the anthropogenic SO2 emissions + ! by applying monthly scale factors. The scale factors are the + ! ratio of (monthly ship SO2 / total ship SO2) as take from the + ! inventory of Corbett et al. + ! + ! The emissions on which these scale factors are based are + ! defined on the GEOS 1 x 1 GRID, so apply scale factors + ! AFTER regridding! + !----------------------------------------------------------------- + + ! Convert [kg SO2/yr] to [kg SO2/month] + CALL SEASCL_EDGAR_SHIP_SO2( E_SO2_SHIP_1x1 ) + + ! Return to calling program + END SUBROUTINE READ_EDGAR_SO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE SEASCL_EDGAR_ANTH_SO2( E_SO2_1x1 ) +! +!****************************************************************************** +! Subroutine SEASCL_EDGAR_ANTH_SO2 applies seasonal scale factors (computed +! as the ratio of seasonal/total GEIA SO2 emissions) to the annual EDGAR +! anthropogenic SO2 emissions. This is required to impose a seasonality onto +! the EDGAR ship SO2 emissions, which are reported as per year. +! (avd, bmy, 7/14/06) +! +! NOTE: Ship SO2 scale factors are on the GENERIC 1x1 GRID. +! +! Arguments as Input: +! ============================================================================ +! (1 ) E_SO2_1x1 (REAL*8 ) : Anthro SO2 1x1 array [kg SO2/yr] +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_SO2_1x1 (REAL*8 ) : Anthro SO2 1x1 array [kg SO2/season] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: E_SO2_1x1(I1x1,J1x1-1) + + ! Local variables + INTEGER :: I, J + REAL*4 :: ARRAY(I1x1,J1x1-1,1) + REAL*8 :: THIS_TAU + CHARACTER(LEN=3) :: THIS_SEA + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! SEASCL_EDGAR_ANTH_SO2 begins here! + !================================================================= + + ! File name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'EDGAR_200607/SOx/anth_SOx_scale.' // SEASON_NAME // + & '.generic.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - SEASCL_EDGAR_ANTH_SO2: Reading ', a ) + + ! Read scale factor data [unitless] + CALL READ_BPCH2( FILENAME, 'EDGAR-2D', 73, + & SEASON_TAU0, I1x1, J1x1-1, + & 1, ARRAY, QUIET=.TRUE. ) + + + ! Apply seasonal scale factors to anthro SO2 + E_SO2_1x1(:,:) = E_SO2_1x1(:,:) * ARRAY(:,:,1) + + ! Return to calling program + END SUBROUTINE SEASCL_EDGAR_ANTH_SO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE SEASCL_EDGAR_SHIP_SO2( E_SO2_SHIP_1x1 ) +! +!****************************************************************************** +! Subroutine SEASCL_EDGAR_SHIP_SO2 applies monthly scale factors (which are +! computed as the ratio of monthly/total ship SO2 emissions from Corbett et +! al) to the annual EDGAR ship SO2 emissions. This is required to impose a +! seasonality onto the EDGAR ship SO2 emissions, which are reported as per +! year. (avd, bmy, 7/14/06) +! +! NOTE: Ship SO2 scale factors are on the GEOS 1x1 GRID. +! +! Arguments as Input: +! ============================================================================ +! (1 ) E_SO2_SHIP_1x1 (REAL*8 ) : Ship SO2 1x1 array [kg SO2/yr] +! +! Arguments as Input/Output: +! ============================================================================ +! (1 ) E_SO2_SHIP_1x1 (REAL*8 ) : Ship SO2 1x1 array [kg SO2/month] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: E_SO2_SHIP_1x1(I1x1,J1x1) + + ! Local variables + INTEGER :: I, J + REAL*4 :: ARRAY(I1x1,J1x1,1) + REAL*8 :: THIS_TAU + CHARACTER(LEN=3) :: THIS_MON + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! SEASCL_EDGAR_SHIP_SO2 begins here! + !================================================================= + + ! File name + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'EDGAR_200607/SOx/ship_SOx_scale.' // MONTH_NAME // + & '.geos.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - SEASCL_EDGAR_SHIP_SO2: Reading ', a ) + + ! Read scale factor data [unitless] + CALL READ_BPCH2( FILENAME, 'EDGAR-2D', 73, + & MONTH_TAU0, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + + ! Apply monthly scale factors to ship SO2 + E_SO2_SHIP_1x1(:,:) = E_SO2_SHIP_1x1(:,:) * ARRAY(:,:,1) + + ! Return to calling program + END SUBROUTINE SEASCL_EDGAR_SHIP_SO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_EDGAR_DATA( NAME, TRACER, E_1x1 ) +! +!****************************************************************************** +! Subroutine READ_EDGAR_DATA reads EDGAR emissions data for a single sector +! from disk, in binary punch file format. (avd, bmy, 7/14/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FILENAME (CHARACTER) : string with EDGAR inventory filename +! (2 ) TRACER (INTEGER ) : Tracer number +! (3 ) E_1x1 (REAL*4 ) : Array to hold emissions +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: TRACER + REAL*4, INTENT(OUT) :: E_1x1(I1x1,J1x1-1) + CHARACTER(LEN=*), INTENT(IN) :: NAME + + ! Local variables + REAL*8 :: TAU0 + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_EDGAR_DATA begins here! + !================================================================= + + ! Filename + IF ( TRACER == 1 ) THEN + + ! NOx + FILENAME = TRIM( DATA_DIR_1x1 ) // 'EDGAR_200607/NOx/EDGAR.' // + & TRIM( NAME ) // '.generic.1x1' + + ELSE IF ( TRACER == 4 ) THEN + + ! CO + FILENAME = TRIM( DATA_DIR_1x1 ) // 'EDGAR_200607/CO/EDGAR.' // + & TRIM( NAME ) // '.generic.1x1' + + ELSE IF ( TRACER == 26 ) THEN + + ! SO2 + FILENAME = TRIM( DATA_DIR_1x1 ) // 'EDGAR_200607/SOx/EDGAR.' // + & TRIM( NAME ) // '.generic.1x1' + + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_EDGAR_DATA: Reading ', a ) + + ! Use TAU0 for year 2000 + TAU0 = GET_TAU0( 1, 1, 2000 ) + + ! Read data + CALL READ_BPCH2( FILENAME, 'EDGAR-2D', TRACER, + & TAU0, I1x1, J1x1-1, + & 1, E_1x1, QUIET=.TRUE. ) + + ! Return to calling program + END SUBROUTINE READ_EDGAR_DATA + +!------------------------------------------------------------------------------ + + SUBROUTINE ADD_EDGAR_DATA( E, E_1x1, SC, E_HRLY_1x1 ) +! +!****************************************************************************** +! Subroutine ADD_EDGAR_DATA adds emissions for a given sector to cumulative +! data arrays. Computes total emissions arrays and (if requested) totals per +! hour. (avd, bmy, 7/14/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) E (REAL*4) : EDGAR emissions for a given sector [kg/yr] +! (3 ) SC (REAL*8) : OPTIONAL - Hourly EDGAR scale factors [unitless] +! +! Arguments as Output: +! ============================================================================ +! (2 ) E_1x1 (REAL*8) : Cumulative total of EDGAR emissions [kg/yr] +! (4 ) E_HRLY_1x1 (REAL*8) : OPTIONAL - Hourly cum total of emissions [kg/yr] +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(IN) :: E(I1x1,J1x1-1) + REAL*8, INTENT(OUT) :: E_1x1(I1x1,J1x1-1) + REAL*8, INTENT(IN), OPTIONAL :: SC(N_HOURS) + REAL*8, INTENT(OUT), OPTIONAL :: E_HRLY_1x1(I1x1,J1x1-1,N_HOURS) + + ! Local variables + LOGICAL :: IS_HRLY + INTEGER :: I, J, H + + !================================================================= + ! ADD_EDGAR_DATA begins here! + !================================================================= + + ! Are we computing cumulative totals for each hour? + IS_HRLY = ( PRESENT( E_HRLY_1x1 ) .and. PRESENT( SC ) ) + + ! Create total sum + E_1x1(:,:) = E_1x1(:,:) + E(:,:) + + ! Create hourly sum + IF ( IS_HRLY ) THEN +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, H ) + DO H = 1, N_HOURS + DO J = 1, J1x1-1 + DO I = 1, I1x1 + E_HRLY_1x1(I,J,H) = E_HRLY_1x1(I,J,H) + ( SC(H) * E(I,J) ) + ENDDO + ENDDO + ENDDO +!$OMP END PARALLEL DO + ENDIF + + ! Return to calling program + END SUBROUTINE ADD_EDGAR_DATA + +!------------------------------------------------------------------------------ + +!! ######### OBSOLETE (phs, 3/10/08) ######### +!! +! SUBROUTINE READ_EDGAR_SCALE( NAME, TRACER, YEAR, S_1x1 ) +!! +!!****************************************************************************** +!! Subroutine READ_EDGAR_SCALE reads interannual scale factor data from disk. +!! (avd, bmy, 7/14/06) +!! +!! Arguments as Input: +!! ============================================================================ +!! (1 ) FILENAME (CHARACTER) : String with EDGAR inventory filename +!! (2 ) TRACER (INTEGER ) : Tracer number +!! (3 ) YEAR (INTEGER ) : Current year +!! (4 ) S_1x1 (REAL*4 ) : Array to hold scale factors +!! +!! NOTES: ######### OBSOLETE (phs, 3/10/08) ######### +!!****************************************************************************** +!! +! ! References to F90 modules +! USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 +! USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 +! +!# include "CMN_SIZE" ! Size parameters +! +! ! Arguments +! CHARACTER(LEN=*), INTENT(IN) :: NAME +! INTEGER, INTENT(IN) :: TRACER, YEAR +! REAL*8, INTENT(OUT) :: S_1x1(I1x1,J1x1) +! +! ! Local variables +! REAL*4 :: T_1x1(I1x1,J1x1) +! REAL*8 :: TAU0 +! CHARACTER(LEN=255) :: FILENAME +! +! !================================================================= +! ! READ_EDGAR_SCALE begins here! +! !================================================================= +! +! ! Filename +! IF ( TRACER == 71 ) THEN +! +! ! NOx +! FILENAME = TRIM( DATA_DIR_1x1 ) // 'EDGAR_200607/NOx/EDGAR.' // +! & TRIM( NAME ) // '.geos.1x1' +! +! ELSE IF ( TRACER == 72 ) THEN +! +! ! CO +! FILENAME = TRIM( DATA_DIR_1x1 ) // 'EDGAR_200607/CO/EDGAR.' // +! & TRIM( NAME ) // '.geos.1x1' +! +! ELSE IF ( TRACER == 73 ) THEN +! +! ! SO2 +! FILENAME = TRIM( DATA_DIR_1x1 ) // 'EDGAR_200607/SOx/EDGAR.' // +! & TRIM( NAME ) // '.geos.1x1' +! +! ENDIF +! +! ! Echo info +! WRITE( 6, 100 ) TRIM( FILENAME ) +! 100 FORMAT( ' - READ_EDGAR_SCALE: Reading ', a ) +! +! ! Use TAU0 for the current year +! TAU0 = GET_TAU0( 1, 1, YEAR ) +! +! ! Read data +! CALL READ_BPCH2( FILENAME, 'EDGAR-2D', TRACER, +! & TAU0, I1x1, J1x1, +! & 1, T_1x1, QUIET=.TRUE. ) +! +! ! Convert to REAL*8 and return +! S_1x1(:,:) = T_1x1(:,:) +! +! ! Return to calling program +! END SUBROUTINE READ_EDGAR_SCALE +! +!!------------------------------------------------------------------------------ +! + FUNCTION GET_EDGAR_NOx( I, J, KG_S, MOLEC_CM2_S, SHIP ) + & RESULT( NOx ) +! +!****************************************************************************** +! Function GET_EDGAR_NOx returns the EDGAR NOx emissions at grid box (I,J) +! in units of [kg/season], [kg/s], or [molec/cm2/s]. (avd, bmy, 7/14/06) +! +! Arguments: +! ============================================================================ +! (1 ) I (INTEGER) : GEOS-Chem longitude index +! (2 ) J (INTEGER) : GEOS-Chem latitude index +! (3 ) KG_S (LOGICAL) : OPTIONAL - Return data in [kg/s] +! (4 ) MOLEC_CM2_S (LOGICAL) : OPTIONAL - Return data in [molec/cm2/s] +! +! NOTES: +! (1 ) Added the SHIP switch (phs, 5/13/08) +!****************************************************************************** +! + ! References to F90 modules + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxff + USE LOGICAL_MOD, ONLY : LFUTURE + + ! Arguments + INTEGER, INTENT(IN) :: I, J + LOGICAL, INTENT(IN), OPTIONAL :: KG_S, MOLEC_CM2_S, SHIP + + ! Local variables + LOGICAL :: DO_KGS, DO_MCS + REAL*8 :: NOx + + !================================================================= + ! GET_EDGAR_NOx begins here! + !================================================================= + + ! Initialize + DO_KGS = .FALSE. + DO_MCS = .FALSE. + + ! Return data in [kg/s] or [molec/cm2/s]? + IF ( PRESENT( KG_S ) ) DO_KGS = KG_S + IF ( PRESENT( MOLEC_CM2_S ) ) DO_MCS = MOLEC_CM2_S + + ! Get NOx [kg NOx/season] + IF ( PRESENT( SHIP ) ) THEN + IF ( SHIP ) THEN + NOx = EDGAR_NOx_SHIP(I,J) + ELSE + NOx = EDGAR_NOx(I,J) + ENDIF + ELSE + NOx = EDGAR_NOx(I,J) + ENDIF + +!%%%%%%%%%%%%% KLUDGE TO EMITT SHIP NOX AS NOX %%%%%%%%%%%%%% +! ! Get NOx [kg NOx/season] +! IF ( PRESENT( SHIP ) ) THEN +! NOx = 0d0 +! ELSE +! NOx = EDGAR_NOx(I,J) + EDGAR_NOx_SHIP(I,J) +! ENDIF +!%%%%%%%%%%%%% END KLUDGE %%%%%%%%%%%%%% + + + ! Apply scale factor for future emissions (if necessary) + IF ( LFUTURE ) THEN + NOx = NOx * GET_FUTURE_SCALE_NOxff( I, J ) + ENDIF + + ! Convert units (if necessary) + IF ( DO_KGS ) THEN + + ! Convert to [kg NOx/s] + NOx = NOx / SEC_IN_SEASON + + ELSE IF ( DO_MCS ) THEN + + ! Convert to [molec/cm2/s] + NOx = NOx * XNUMOL_NO2 / ( A_CM2(J) * SEC_IN_SEASON ) + + ENDIF + + ! Return to calling program + END FUNCTION GET_EDGAR_NOx + +!------------------------------------------------------------------------------ + + FUNCTION GET_EDGAR_CO( I, J, KG_S, MOLEC_CM2_S, SHIP ) + & RESULT( CO ) +! +!****************************************************************************** +! Function GET_EDGAR_CO returns the EDGAR CO emissions at grid box (I,J) +! in units of [kg/yr], [kg/s], or [molec/cm2/s]. (avd, bmy, 7/14/06) +! +! Arguments: +! ============================================================================ +! (1 ) I (INTEGER) : GEOS-Chem longitude index +! (2 ) J (INTEGER) : GEOS-Chem latitude index +! (3 ) KG_S (LOGICAL) : OPTIONAL - Return data in [kg/s] +! (4 ) MOLEC_CM2_S (LOGICAL) : OPTIONAL - Return data in [molec/cm2/s] +! +! NOTES: +! (1 ) Added the SHIP switch (phs, 5/13/08) +!****************************************************************************** +! + ! References to F90 modules + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_COff + USE LOGICAL_MOD, ONLY : LFUTURE + + ! Arguments + INTEGER, INTENT(IN) :: I, J + LOGICAL, INTENT(IN), OPTIONAL :: KG_S, MOLEC_CM2_S, SHIP + + ! Local variables + LOGICAL :: DO_KGS, DO_MCS + REAL*8 :: CO + + !================================================================= + ! GET_EDGAR_CO begins here! + !================================================================= + + ! Initialize + DO_KGS = .FALSE. + DO_MCS = .FALSE. + + ! Return data in [kg/s] or [molec/cm2/s]? + IF ( PRESENT( KG_S ) ) DO_KGS = KG_S + IF ( PRESENT( MOLEC_CM2_S ) ) DO_MCS = MOLEC_CM2_S + + ! Get CO [kg/yr] + IF ( PRESENT( SHIP ) ) THEN + IF ( SHIP ) THEN + CO = EDGAR_CO_SHIP(I,J) + ELSE + CO = EDGAR_CO(I,J) + ENDIF + ELSE + CO = EDGAR_CO(I,J) + ENDIF + + ! Apply scale factor for future emissions (if necessary) + IF ( LFUTURE ) THEN + CO = CO * GET_FUTURE_SCALE_COff( I, J ) + ENDIF + + ! Convert units (if necessary) + IF ( DO_KGS ) THEN + + ! Convert to [kg CO/s] + CO = CO / SEC_IN_2000 + + ELSE IF ( DO_MCS ) THEN + + ! Convert to [molec/cm2/s] + CO = CO * XNUMOL_CO / ( A_CM2(J) * SEC_IN_2000 ) + + ENDIF + + ! Return to calling program + END FUNCTION GET_EDGAR_CO + +!------------------------------------------------------------------------------ + + FUNCTION GET_EDGAR_ANTH_SO2( I, J, KG_S, MOLEC_CM2_S ) RESULT(SO2) +! +!****************************************************************************** +! Function GET_EDGAR_ANTH_SO2 returns the EDGAR anthropogenic SO2 emissions +! at grid box (I,J) in either [kg/yr] or [molec/cm2/s]. (avd, bmy, 7/14/06) +! +! Arguments: +! ============================================================================ +! (1 ) I (INTEGER) : GEOS-Chem longitude index +! (2 ) J (INTEGER) : GEOS-Chem latitude index +! (3 ) KG_S (LOGICAL) : OPTIONAL - Return data in [kg/s] +! (4 ) MOLEC_CM2_S (LOGICAL) : OPTIONAL - Return data in [molec/cm2/s] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2ff + USE LOGICAL_MOD, ONLY : LFUTURE + + ! Arguments + INTEGER, INTENT(IN) :: I, J + LOGICAL, INTENT(IN), OPTIONAL :: KG_S, MOLEC_CM2_S + + ! Local variables + LOGICAL :: DO_KGS, DO_MCS + REAL*8 :: SO2 + + !================================================================= + ! GET_EDGAR_ANTH_SO2 begins here! + !================================================================= + + ! Initialize + DO_KGS = .FALSE. + DO_MCS = .FALSE. + + ! Return data in [kg SO2/s] or [molec/cm2/s]? + IF ( PRESENT( KG_S ) ) DO_KGS = KG_S + IF ( PRESENT( MOLEC_CM2_S ) ) DO_MCS = MOLEC_CM2_S + + ! Get anthropogenic SO2 [kg SO2/season] + SO2 = EDGAR_SO2(I,J) + + ! Apply scale factor for future emissions (if necessary) + IF ( LFUTURE ) THEN + SO2 = SO2 * GET_FUTURE_SCALE_SO2ff( I, J ) + ENDIF + + ! Convert units + IF ( DO_KGS ) THEN + + ! Convert to [kg SO2/s] + SO2 = SO2 / SEC_IN_SEASON + + ELSE IF ( DO_MCS ) THEN + + ! Convert to [molec/cm2/s] + SO2 = SO2 * XNUMOL_SO2 / ( A_CM2(J) * SEC_IN_SEASON ) + + ENDIF + + ! Return to calling program + END FUNCTION GET_EDGAR_ANTH_SO2 + +!------------------------------------------------------------------------------ + + FUNCTION GET_EDGAR_SHIP_SO2( I, J, KG_S, MOLEC_CM2_S ) RESULT(SO2) +! +!****************************************************************************** +! Function GET_EDGAR_SHIP_SO2 returns the EDGAR ship exhaust SO2 emissions +! at grid box (I,J) in units of [kg/month], [kg/s] or [molec/cm2/s]. +! (avd, bmy, 7/14/06) +! +! Arguments: +! ============================================================================ +! (1 ) I (INTEGER) : GEOS-Chem longitude index +! (2 ) J (INTEGER) : GEOS-Chem latitude index +! (3 ) KG_S (LOGICAL) : OPTIONAL - Return data in [kg/s] +! (4 ) MOLEC_CM2_S (LOGICAL) : OPTIONAL - Return data in [molec/cm2/s] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2ff + USE LOGICAL_MOD, ONLY : LFUTURE + + ! Arguments + INTEGER, INTENT(IN) :: I, J + LOGICAL, INTENT(IN), OPTIONAL :: KG_S, MOLEC_CM2_S + + ! Function value + LOGICAL :: DO_KGS, DO_MCS + REAL*8 :: SO2 + + !================================================================= + ! GET_EDGAR_SHIP_SO2 begins here! + !================================================================= + + ! Initialize + DO_KGS = .FALSE. + DO_MCS = .FALSE. + + ! Return data in [kg/s] or [molec/cm2/s]? + IF ( PRESENT( KG_S ) ) DO_KGS = KG_S + IF ( PRESENT( MOLEC_CM2_S ) ) DO_MCS = MOLEC_CM2_S + + ! Get ship SO2 [kg SO2/month] + SO2 = EDGAR_SO2_SHIP(I,J) + + ! Apply scale factor for future emissions (if necessary) + IF ( LFUTURE ) THEN + SO2 = SO2 * GET_FUTURE_SCALE_SO2ff( I, J ) + ENDIF + + ! Convert units (if necessary) + IF ( DO_KGS ) THEN + + ! Convert to [kg SO2/s] + SO2 = SO2 / SEC_IN_MONTH + + ELSE IF ( DO_MCS ) THEN + + ! Convert to [molec/cm2/s] + SO2 = SO2 * XNUMOL_SO2 / ( A_CM2(J) * SEC_IN_MONTH ) + + ENDIF + + ! Return to calling program + END FUNCTION GET_EDGAR_SHIP_SO2 + +!------------------------------------------------------------------------------ + + FUNCTION GET_EDGAR_TODN( I, J, HOUR ) RESULT( TODN ) +! +!****************************************************************************** +! Function GET_EDGAR_TODN returns the time-of-day diurnal scale factor for +! the EDGAR NOx emissions. (avd, bmy, 7/14/06) +! +! Arguments: +! ============================================================================ +! (1 ) I (INTEGER) : GEOS-Chem longitude index +! (2 ) J (INTEGER) : GEOS-Chem latitude index +! (3 ) HOUR (INTEGER) : GMT hour of the day (0-23) +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J, HOUR + + ! Local variables + INTEGER :: H + REAL*8 :: TODN + + !================================================================= + ! GET_EDGAR_TODN begins here! + !================================================================= + + ! The 1st element of the array is hour 0, so add 1 + H = HOUR + 1 + + ! Get time of day factor for NOx + TODN = EDGAR_TODN(I,J,H) + + ! Return to calling program + END FUNCTION GET_EDGAR_TODN + +!------------------------------------------------------------------------------ + + SUBROUTINE EDGAR_TOTAL_Tg( YEAR, MONTH ) +! +!****************************************************************************** +! Subroutine EDGAR_TOTAL_Tg prints totals of EDGAR emissions species +! in units of Tg. (avd, bmy, 7/14/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) YEAR (INTEGER) : Current year +! (2 ) MONTH (INTEGER) : Current month +! +! NOTES: +!****************************************************************************** +! + USE LOGICAL_MOD, ONLY : LEDGARSHIP + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + + ! Local variables + REAL*8 :: T_NOx, T_CO, T_SO2an, T_SO2sh + REAL*8 :: T_NOxSh, T_COsh + + !================================================================= + ! EDGAR_TOTAL_Tg begins here! + !================================================================= + + ! Compute totals [Tg/yr] + T_NOx = SUM( EDGAR_NOx ) * ( 14d0/46d0 ) / 1d9 ! Tg N + T_CO = SUM( EDGAR_CO ) / 1d9 ! Tg CO + T_SO2an = SUM( EDGAR_SO2 ) * ( 32d0/64d0 ) / 1d9 ! Tg S + IF ( LEDGARSHIP ) THEN + T_NOxSh = SUM( EDGAR_NOx_SHIP ) * ( 14d0/46d0 ) / 1d9 ! Tg N + T_COSh = SUM( EDGAR_CO_SHIP ) / 1d9 ! Tg CO + T_SO2sh = SUM( EDGAR_SO2_SHIP ) * ( 32d0/64d0 ) / 1d9 ! Tg S + ELSE + T_COSh = 0d0 + T_NOxSh = 0d0 + T_SO2sh = 0d0 + ENDIF + + ! Print totals + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a,/)' ) 'E D G A R E M I S S I O N S' + WRITE( 6, 100 ) YEAR, SEASON_NAME, T_NOx + WRITE( 6, 105 ) YEAR, SEASON_NAME, T_NOxSh + WRITE( 6, 110 ) YEAR, T_CO + WRITE( 6, 115 ) YEAR, T_COSh + WRITE( 6, 120 ) YEAR, SEASON_NAME, T_SO2an + WRITE( 6, 130 ) YEAR, MONTH_NAME, T_SO2sh + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! FORMAT statements + 100 FORMAT( 'NOx for year ', i4, ' and season ', a3, + & ' : ', f10.4, ' [Tg N ]' ) + 105 FORMAT( 'NOx Ship for year ', i4, ' and season ', a3, + & ' : ', f10.4, ' [Tg N ]' ) + 110 FORMAT( 'CO for year ', i4, ' (annual total)', + & ' : ', f10.4, ' [Tg CO/yr]' ) + 115 FORMAT( 'CO Ship for year ', i4, ' (annual total)', + & ' : ', f10.4, ' [Tg CO/yr]' ) + 120 FORMAT( 'Anthro SO2 for year ', i4, ' and season ', a3, + & ' : ', f10.4, ' [Tg S ]' ) + 130 FORMAT( 'Ship SO2 for year ', i4, ' and month ', a3, + & ' : ', f10.4, ' [Tg S ]' ) + + ! Return to calling program + END SUBROUTINE EDGAR_TOTAL_Tg + +!------------------------------------------------------------------------------ + SUBROUTINE READ_AROMATICS( E_BENZ, E_TOLU, E_XYLE ) +! +!****************************************************************************** +! Subroutine READ_AROMATICS now reads EDGARv2 inventory for Year 1985 +! from a bpch file (tmf, 1/8/08). +! +! Arguments as Output +! ============================================================================ +! (1 ) E_BENZ (REAL*4) : EDGARv2 anthro BENZ for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! (2 ) E_TOLU (REAL*4) : EDGARv2 anthro TOLU for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! (3 ) E_XYLE (REAL*4) : EDGARv2 anthro XYLE for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE REGRID_A2A_MOD, ONLY : DO_REGRID_A2A !(lzh,02/01/2015) + +! IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT) :: E_BENZ(IGLOB,JGLOB ) + REAL*4, INTENT(OUT) :: E_TOLU(IGLOB,JGLOB ) + REAL*4, INTENT(OUT) :: E_XYLE(IGLOB,JGLOB ) + + ! Local variables + INTEGER :: L + REAL*4 :: ARRAY(I1x1,J1x1 ) + CHARACTER(LEN=255) :: FILENAME + REAL*8 :: GEOS1x1(I1x1,J1x1,1) + REAL*8 :: TEMP(IGLOB,JGLOB) + + ! (lzh, 02/01/2015) + CHARACTER(LEN=255) :: LLFILENAME + REAL*8 :: INGRID(I1x1,J1x1) + REAL*8 :: OUTGRID(IIPAR,JJPAR) + + !================================================================= + ! READ_AROMATICS begins here! + !================================================================= + ! Zero emission arrays + E_BENZ = 0e0 + E_TOLU = 0e0 + E_XYLE = 0e0 + + ! Define the binary punch file name + + !================================================================= + ! Read BENZ (tracer #57): aseasonal + !================================================================= + FILENAME = TRIM( DATA_DIR_1x1 )// + & 'EDGAR_200607/BENZ/BENZ_1985_FF_IND_EDGAR2.1x1geos.bpch' + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 57, + & 0.d0, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Regrid BENZ from GEOS 1x1 to current model resolution + ! [atoms C/cm2/s] (ccc, 3/9/09) +! GEOS1x1(:,:,1) = ARRAY(:,:) +! CALL DO_REGRID_1x1('atoms C/cm2/s', GEOS1x1, TEMP) + +! E_BENZ = TEMP + + ! (lzh, 02/01/2015) + ! File with lat/lon edges for regridding + LLFILENAME = TRIM( DATA_DIR_1x1) // + & 'MAP_A2A_Regrid_201203/MAP_A2A_latlon_geos1x1.nc' + + INGRID = ARRAY + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_BENZ = OUTGRID + + !================================================================= + ! Read TOLU (tracer #58): aseasonal + !================================================================= + FILENAME = TRIM( DATA_DIR_1x1 )// + & 'EDGAR_200607/TOLU/TOLU_1985_FF_IND_EDGAR2.1x1geos.bpch' + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 58, + & 0.d0, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Regrid TOLU from GEOS 1x1 to current model resolution + ! [atoms C/cm2/s] (ccc, 3/9/09) +! GEOS1x1(:,:,1) = ARRAY(:,:) +! CALL DO_REGRID_1x1('atoms C/cm2/s', GEOS1x1, TEMP) + +! E_TOLU = TEMP + + ! (lzh, 02/01/2015) + INGRID = ARRAY + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_TOLU = OUTGRID + + !================================================================= + ! Read XYLE (tracer #59): aseasonal + !================================================================= + FILENAME = TRIM( DATA_DIR_1x1 )// + & 'EDGAR_200607/XYLE/XYLE_1985_FF_IND_EDGAR2.1x1geos.bpch' + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 59, + & 0.d0, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Regrid XYLE from GEOS 1x1 to current model resolution + ! [atoms C/cm2/s] (ccc, 3/9/09) +! GEOS1x1(:,:,1) = ARRAY(:,:) +! CALL DO_REGRID_1x1('atoms C/cm2/s', GEOS1x1, TEMP) + +! E_XYLE = TEMP + + ! (lzh, 02/01/2015) + INGRID = ARRAY + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_XYLE = OUTGRID + + 100 FORMAT( 'READ_AROMATICS: Reading ', a ) + + + ! Return to calling program + END SUBROUTINE READ_AROMATICS + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_C2H4( E_C2H4 ) +! +!****************************************************************************** +! Subroutine READ_C2H4 now reads EDGARv2 inventory for Year 1985 from a bpch file +! (tmf, 11/10/2006). +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_C2H4 (REAL*4) : EDGARv2 anthro C2H4 for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + + USE REGRID_A2A_MOD, ONLY : DO_REGRID_A2A ! (lzh,02/01/2015) + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + +! IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT) :: E_C2H4(IGLOB,JGLOB ) + + ! Local variables + INTEGER :: L + REAL*4 :: ARRAY(I1x1,J1x1 ) + CHARACTER(LEN=255) :: FILENAME + REAL*8 :: GEOS1x1(I1x1,J1x1,1) + REAL*8 :: TEMP(IGLOB,JGLOB) + + ! (lzh, 02/01/2015) + CHARACTER(LEN=255) :: LLFILENAME + REAL*8 :: INGRID(I1x1,J1x1) + REAL*8 :: OUTGRID(IIPAR,JJPAR) + + !================================================================= + ! READ_C2H4 begins here! + !================================================================= + ! Zero emission arrays + E_C2H4 = 0e0 + + ! Define the binary punch file name + FILENAME = '/as2/home/ccarouge/orig.emission/edgar/' // + & 'C2H4_1985_FF_IND_EDGAR2.1x1geos.bpch' + + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_C2H4: Reading ', a ) + + !================================================================= + ! Read C2H4 (tracer #63): aseasonal + !================================================================= + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 63, + & 0.d0, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + + ! Regrid C2H4 from GEOS 1x1 to current model resolution + ! [atoms C/cm2/s] (ccc, 3/9/09) +! GEOS1x1(:,:,1) = ARRAY(:,:) +! CALL DO_REGRID_1x1('atoms C/cm2/s', GEOS1x1, TEMP) + +! E_C2H4 = TEMP + + ! (lzh, 02/01/2015) + ! File with lat/lon edges for regridding + LLFILENAME = TRIM( DATA_DIR_1x1) // + & 'MAP_A2A_Regrid_201203/MAP_A2A_latlon_geos1x1.nc' + + INGRID = ARRAY + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_C2H4 = OUTGRID + + ! Return to calling program + END SUBROUTINE READ_C2H4 + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_C2H2( E_C2H2 ) +! +!****************************************************************************** +! Subroutine READ_C2H2 now reads EDGARv2 C2H2 emissions for year 1985 +! (tmf, 11/10/2006). +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_C2H2 (REAL*4) : EDGARv2 anthro C2H2 for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE REGRID_A2A_MOD, ONLY : DO_REGRID_A2A ! (lzh,02/01/2015) + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + +! IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT) :: E_C2H2(IGLOB,JGLOB ) + + ! Local variables + INTEGER :: L + REAL*4 :: ARRAY(I1x1,J1x1 ) + CHARACTER(LEN=255) :: FILENAME + REAL*8 :: GEOS1x1(I1x1,J1x1,1) + REAL*8 :: TEMP(IGLOB,JGLOB) + + ! (lzh, 02/01/2015) + CHARACTER(LEN=255) :: LLFILENAME + REAL*8 :: INGRID(I1x1,J1x1) + REAL*8 :: OUTGRID(IIPAR,JJPAR) + + !================================================================= + ! READ_C2H2 begins here! + !================================================================= + ! Zero emission arrays + E_C2H2 = 0e0 + + ! Define the binary punch file name + FILENAME = '/as2/home/ccarouge/orig.emission/edgar/' // + & 'C2H2_1985_FF_IND_EDGAR2.1x1geos.bpch' + + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_C2H2: Reading ', a ) + + !================================================================= + ! Read C2H2 (tracer #64): aseasonal + !================================================================= + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 64, + & 0.d0, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Regrid C2H2 from GEOS 1x1 to current model resolution + ! [atoms C/cm2/s] (ccc, 3/9/09) +! GEOS1x1(:,:,1) = ARRAY(:,:) +! CALL DO_REGRID_1x1('atoms C/cm2/s', GEOS1x1, TEMP) + +! E_C2H2 = TEMP + + ! (lzh, 02/01/2015) + ! File with lat/lon edges for regridding + LLFILENAME = TRIM( DATA_DIR_1x1) // + & 'MAP_A2A_Regrid_201203/MAP_A2A_latlon_geos1x1.nc' + + INGRID = ARRAY + CALL DO_REGRID_A2A( LLFILENAME, I1x1, J1x1, + & INGRID, OUTGRID, IS_MASS=0, + & netCDF=.TRUE. ) + E_C2H2 = OUTGRID + + ! Return to calling program + END SUBROUTINE READ_C2H2 + +!------------------------------------------------------------------------------ + SUBROUTINE READ_AROMATICS_05x0666( E_BENZ, E_TOLU, E_XYLE ) +! +!****************************************************************************** +! Subroutine READ_AROMATICS now reads EDGARv2 inventory for Year 1985 +! from a bpch file (tmf, 1/8/08). +! +! Arguments as Output +! ============================================================================ +! (1 ) E_BENZ (REAL*4) : EDGARv2 anthro BENZ for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! (2 ) E_TOLU (REAL*4) : EDGARv2 anthro TOLU for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! (3 ) E_XYLE (REAL*4) : EDGARv2 anthro XYLE for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE DIRECTORY_MOD, ONLY : DATA_DIR + +! IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT) :: E_BENZ(IGLOB,JGLOB ) + REAL*4, INTENT(OUT) :: E_TOLU(IGLOB,JGLOB ) + REAL*4, INTENT(OUT) :: E_XYLE(IGLOB,JGLOB ) + + ! Local variables + INTEGER :: L + REAL*4 :: ARRAY(IGLOB,JGLOB ) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_AROMATICS begins here! + !================================================================= + ! Zero emission arrays + E_BENZ = 0e0 + E_TOLU = 0e0 + E_XYLE = 0e0 + + ! Define the binary punch file name + + !================================================================= + ! Read BENZ (tracer #57): aseasonal + !================================================================= + FILENAME = '/as2/home/ccarouge/orig.emission/edgar/' // + & 'BENZ_1985_FF_IND_EDGAR2.05x0666CH.bpch' + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 57, + & 0.d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + E_BENZ = ARRAY + + !================================================================= + ! Read TOLU (tracer #58): aseasonal + !================================================================= + FILENAME = '/as2/home/ccarouge/orig.emission/edgar/' // + & 'TOLU_1985_FF_IND_EDGAR2.05x0666CH.bpch' + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 58, + & 0.d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + E_TOLU = ARRAY + + !================================================================= + ! Read XYLE (tracer #59): aseasonal + !================================================================= + FILENAME = '/as2/home/ccarouge/orig.emission/edgar/' // + & 'XYLE_1985_FF_IND_EDGAR2.05x0666CH.bpch' + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 59, + & 0.d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + E_XYLE = ARRAY + + 100 FORMAT( 'READ_AROMATICS: Reading ', a ) + + + ! Return to calling program + END SUBROUTINE READ_AROMATICS_05x0666 + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_C2H4_05x0666( E_C2H4 ) +! +!****************************************************************************** +! Subroutine READ_C2H4 now reads EDGARv2 inventory for Year 1985 from a bpch file +! (tmf, 11/10/2006). +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_C2H4 (REAL*4) : EDGARv2 anthro C2H4 for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE DIRECTORY_MOD, ONLY : DATA_DIR + +! IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT) :: E_C2H4(IGLOB,JGLOB ) + + ! Local variables + INTEGER :: L + REAL*4 :: ARRAY(IGLOB,JGLOB ) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_C2H4 begins here! + !================================================================= + ! Zero emission arrays + E_C2H4 = 0e0 + + ! Define the binary punch file name + FILENAME = '/as2/home/ccarouge/orig.emission/edgar/' // + & 'C2H4_1985_FF_IND_EDGAR2.05x0666CH.bpch' + + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_C2H4: Reading ', a ) + + !================================================================= + ! Read C2H4 (tracer #63): aseasonal + !================================================================= + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 63, + & 0.d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + E_C2H4 = ARRAY + + + ! Return to calling program + END SUBROUTINE READ_C2H4_05x0666 + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_C2H2_05x0666( E_C2H2 ) +! +!****************************************************************************** +! Subroutine READ_C2H2 now reads EDGARv2 C2H2 emissions for year 1985 +! (tmf, 11/10/2006). +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_C2H2 (REAL*4) : EDGARv2 anthro C2H2 for year 1985 +! (no seasonality, 1 level ) +! [molec/cm2/s] (tmf, 7/8/05) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_MONTH + USE BPCH2_MOD + USE DIRECTORY_MOD, ONLY : DATA_DIR + +! IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT) :: E_C2H2(IGLOB,JGLOB ) + + ! Local variables + INTEGER :: L + REAL*4 :: ARRAY(IGLOB,JGLOB ) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_C2H2 begins here! + !================================================================= + ! Zero emission arrays + E_C2H2 = 0e0 + + ! Define the binary punch file name + FILENAME = '/as2/home/ccarouge/orig.emission/edgar/' // + & 'C2H2_1985_FF_IND_EDGAR2.05x0666CH.bpch' + + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_C2H2: Reading ', a ) + + !================================================================= + ! Read C2H2 (tracer #64): aseasonal + !================================================================= + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 64, + & 0.d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + E_C2H2 = ARRAY + + ! Return to calling program + END SUBROUTINE READ_C2H2_05x0666 + +!------------------------------------------------------------------------------ +! NOTE: This should be for debugging... +! SUBROUTINE OUTPUT_TOTAL_2D( DESCRIPTION, EMISSIONS, UNITS ) +!! +!!****************************************************************************** +!! Subroutine OUTPUT_TOTAL outputs the total emissions for a given emissions +!! array. (amv 02/14/06) +!! +!! NOTES: +!!****************************************************************************** +! +! USE TIME_MOD, ONLY : GET_TS_EMIS +! +!# include "CMN_SIZE" ! size parameters +! +! ! Local variables +! INTEGER :: I, J, K, IMAX, IMIN, JMAX, JMIN +! REAL*8 :: TOTAL, SCALAR +! CHARACTER(LEN=255) :: LOCATION +! CHARACTER(LEN=255) :: OUTUNITS +! +! ! Arguments +! CHARACTER(LEN=*), INTENT(IN) :: DESCRIPTION +! CHARACTER(LEN=*), INTENT(IN) :: UNITS +! REAL*8, INTENT(IN) :: EMISSIONS(IIPAR, JJPAR) +! +! ! Associate output units with input description +! IF ( TRIM( DESCRIPTION ) == 'EDGAR NOx' ) THEN +! !OUTUNITS = '[Tg N/yr]' +! OUTUNITS = '[Tg N/season]' +! ELSEIF ( TRIM( DESCRIPTION ) == 'GEIA NOx' ) THEN +! OUTUNITS = '[Tg N/yr]' +! ELSEIF ( TRIM( DESCRIPTION ) == 'EDGAR CO' ) THEN +! OUTUNITS = '[Tg CO/yr]' +! ELSEIF ( TRIM( DESCRIPTION ) == 'GEIA CO' ) THEN +! OUTUNITS = '[Tg CO/yr]' +! ELSEIF ( TRIM( DESCRIPTION ) == 'GEIA SO2' ) THEN +! OUTUNITS = '[Tg S/yr]' +! ELSEIF ( TRIM( DESCRIPTION ) == 'EDGAR SO2' ) THEN +! !OUTUNITS = '[Tg SO2/yr]' +! OUTUNITS = '[Tg S/season]' +! ELSE +! OUTUNITS = 'Unknown' +! ENDIF +! +! ! Scalar to convert to kg/yr from received units +! IF ( TRIM( UNITS ) == 'kg/yr' ) THEN +! SCALAR = 1.0 / 1.0d9 +! ELSEIF ( TRIM( UNITS ) == 'kg/s' ) THEN +! SCALAR = 1.d0/ 1.0d9 * 365.25 * 24.0 * 60.0 * 60.0 +! ELSEIF ( TRIM( UNITS ) == 'kg/ts' ) THEN +! SCALAR = 1.0 / 1.0d9 / GET_TS_EMIS() * 365.25 * 24.0 * 60.0 +! ELSEIF ( TRIM( UNITS ) == 'kg/season' ) THEN +! SCALAR = 1.0 / 1d9 +! ELSE +! SCALAR = 1.0 +! ENDIF +! +! ! Extra conversion from NO2 -> N +! ! (NO2 is stored for NOx) +! IF ( TRIM( DESCRIPTION ) == 'EDGAR NOx' .or. +! & TRIM( DESCRIPTION ) == 'GEIA NOx' ) THEN +! SCALAR = SCALAR * 14. / 46. +! ENDIF +! +! ! Extra conversion from SO2 -> S +! ! (NO2 is stored for NOx) +! IF ( TRIM( DESCRIPTION ) == 'EDGAR NOx' .or. +! & TRIM( DESCRIPTION ) == 'GEIA NOx' ) THEN +! SCALAR = SCALAR * 32. / 64. +! ENDIF +! +! ! loop over each region +! DO K = 1,6 +! +! ! reset total +! TOTAL = 0.0 +! +! IF ( K == 1 ) THEN +! LOCATION = ' World' +! IMIN = 1 +! IMAX = IGLOB +! JMIN = 1 +! ! avoid anomylous points at pole +! IF ( TRIM(DESCRIPTION) == 'GEIA SO2') THEN +! JMAX = NINT( 170. / 180. * JGLOB ) +! ELSE +! JMAX = JGLOB +! ENDIF +! ELSEIF ( K == 2 ) THEN +! LOCATION = 'North America' +! IMIN = NINT( 15. / 360. * IGLOB ) +! IMAX = NINT( 140. / 360. * IGLOB ) +! JMIN = NINT( 110. / 180. * JGLOB ) +! JMAX = NINT( 170. / 180. * JGLOB ) +! ELSEIF ( K == 3 ) THEN +! LOCATION = 'South America' +! IMIN = NINT( 90. / 360. * IGLOB ) +! IMAX = NINT( 150. / 360. * IGLOB ) +! JMIN = NINT( 30. / 180. * JGLOB ) +! JMAX = NINT( 105. / 180. * JGLOB ) +! ELSEIF ( K == 4 ) THEN +! LOCATION = ' Europe' +! IMIN = NINT( 165. / 360. * IGLOB ) +! IMAX = NINT( 240. / 360. * IGLOB ) +! JMIN = NINT( 125. / 180. * JGLOB ) +! JMAX = NINT( 170. / 180. * JGLOB ) +! ELSEIF ( K == 5 ) THEN +! LOCATION = ' Asia' +! IMIN = NINT( 240. / 360. * IGLOB ) +! IMAX = NINT( 350. / 360. * IGLOB ) +! JMIN = NINT( 90. / 180. * JGLOB ) +! JMAX = NINT( 170. / 180. * JGLOB ) +! ELSEIF ( K == 6 ) THEN +! LOCATION = ' Africa' +! IMIN = NINT( 160. / 360. * IGLOB ) +! IMAX = NINT( 235. / 360. * IGLOB ) +! JMIN = NINT( 50. / 180. * JGLOB ) +! JMAX = NINT( 125. / 180. * JGLOB ) +! ENDIF +! +! DO I = IMIN,IMAX +! DO J = JMIN,JMAX +! TOTAL = TOTAL + EMISSIONS(I,J) * SCALAR +! ENDDO +! ENDDO +! +! WRITE(6,'(a,a,a,a,a,F7.2,1x,a15)') 'Total ', TRIM(DESCRIPTION), +! & ' Emissions, ', TRIM(LOCATION), ': ', TOTAL, +! & TRIM(OUTUNITS) +! +! ENDDO +! +! ! Return to calling program +! END SUBROUTINE OUTPUT_TOTAL_2D +! + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_EDGAR +! +!****************************************************************************** +! Subroutine INIT_EDGAR allocates and initializes all module arrays. +! (avd, bmy, 7/14/06) +! +! NOTES: +! (1 ) Now allocates SHIP arrays only if LEDGARSHIP is TRUE (5/13/08) +!****************************************************************************** +! + ! Reference to F90 modules + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LEDGARSHIP + +# include "CMN_SIZE" ! Size parameters + + ! Local Variables + INTEGER :: AS, J + + !============================================================ + ! INIT_EDGAR begins here! + !============================================================ + + ALLOCATE( EDGAR_NOx( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EDGAR_NOx' ) + EDGAR_NOx = 0d0 + + ALLOCATE( EDGAR_CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EDGAR_CO' ) + EDGAR_CO = 0d0 + + ALLOCATE( EDGAR_SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EDGAR_SO2' ) + EDGAR_SO2 = 0d0 + +! IF ( LEDGARSHIP ) THEN + + ALLOCATE( EDGAR_SO2_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EDGAR_SO2_SHIP' ) + EDGAR_SO2_SHIP = 0d0 + + ALLOCATE( EDGAR_NOx_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EDGAR_NOx_SHIP' ) + EDGAR_NOx_SHIP = 0d0 + + ALLOCATE( EDGAR_CO_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EDGAR_CO_SHIP' ) + EDGAR_CO_SHIP = 0d0 + +! ENDIF + + ALLOCATE( EDGAR_TODN( IIPAR, JJPAR, N_HOURS ), STAT=AS ) + IF (AS /= 0 ) CALL ALLOC_ERR( 'EDGAR_TODN' ) + EDGAR_TODN = 0d0 + + !--------------------------------------------------- + ! Pre-store array for grid box surface area in cm2 + !--------------------------------------------------- + + ALLOCATE( A_CM2( JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'A_CM2' ) + + DO J = 1, JJPAR + A_CM2(J) = GET_AREA_CM2( J ) + ENDDO + + ! Return to calling program + END SUBROUTINE INIT_EDGAR + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_EDGAR +! +!****************************************************************************** +! Subroutine CLEANUP_EDGAR deallocates all module arrays, (avd, bmy, 7/14/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_EDGAR begins here! + !================================================================= + IF ( ALLOCATED( A_CM2 ) ) DEALLOCATE( A_CM2 ) + IF ( ALLOCATED( EDGAR_NOx ) ) DEALLOCATE( EDGAR_NOx ) + IF ( ALLOCATED( EDGAR_CO ) ) DEALLOCATE( EDGAR_CO ) + IF ( ALLOCATED( EDGAR_SO2 ) ) DEALLOCATE( EDGAR_SO2 ) + IF ( ALLOCATED( EDGAR_SO2_SHIP ) ) DEALLOCATE( EDGAR_SO2_SHIP ) + IF ( ALLOCATED( EDGAR_CO_SHIP ) ) DEALLOCATE( EDGAR_CO_SHIP ) + IF ( ALLOCATED( EDGAR_NOX_SHIP ) ) DEALLOCATE( EDGAR_NOx_SHIP ) + IF ( ALLOCATED( EDGAR_TODN ) ) DEALLOCATE( EDGAR_TODN ) + + ! Return to calling program + END SUBROUTINE CLEANUP_EDGAR + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE EDGAR_MOD + + diff --git a/code/emep_mod.f b/code/emep_mod.f new file mode 100644 index 0000000..ff9fcd9 --- /dev/null +++ b/code/emep_mod.f @@ -0,0 +1,1593 @@ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: emep_mod +! +! !DESCRIPTION: \subsection*{Overview} +! Module EMEP\_MOD contains variables and routines to read the +! EMEP European anthropogenic emission inventory for CO, NOz, and some +! NMVOCs. The EMEP files come from Marion Auvray and Isabelle Bey at EPFL. +! (bdf, bmy, amv, phs, 11/1/05, 1/28/09) +! +!\subsection*{References} +! \begin{enumerate} +! \item Vestreng, V., and H. Klein (2002), \emph{Emission data reported +! to UNECE/EMEP: Quality insurance and trend analysis and +! presentation of Web-Dab}, \underline{MSC-W Status Rep}. 2002:, +! 101 pp., Norw. Meteorol. Inst., Oslo, Norway. This paper is +! on the EMEP web site: +!\begin{verbatim} +! http://www.emep.int/mscw/mscw\_publications.html +! http://www.emep.int/publ/reports/2002/mscw\_note\_1\_2002.pdf +!\end{verbatim} +! \item Auvray, M., and I. Bey, \emph{Long-Range Transport to Europe: +! Seasonal Variations and Implications for the European Ozone +! Budget}, \underline{J. Geophys. Res.}, \textbf{110}, D11303, +! doi: 10.1029/2004JD005503, 2005. +! \end{enumerate} +! +! !INTERFACE: +! + MODULE EMEP_MOD +! +! !USES: +! + IMPLICIT NONE +# include "define.h" + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: EMISS_EMEP + PUBLIC :: EMISS_EMEP_05x0666 + PUBLIC :: CLEANUP_EMEP + PUBLIC :: GET_EUROPE_MASK + PUBLIC :: GET_EMEP_ANTHRO +! +! !PRIVATE MEMBER FUNCTIONS: +! + PRIVATE :: EMEP_SCALE_FUTURE + PRIVATE :: READ_EMEP_UPDATED + PRIVATE :: READ_EMEP_UPDATED_05x0666 + PRIVATE :: READ_EUROPE_MASK + PRIVATE :: READ_EUROPE_MASK_05x0666 + PRIVATE :: INIT_EMEP +! +! !REVISION HISTORY: +! 01 Nov 2005 - B. Field, R. Yantosca - Initial version +! (1 ) Now only print totals for defined tracers (bmy, 2/6/06) +! (2 ) Now modified for IPCC future emissions (swu, bmy, 5/30/06) +! (3 ) Now yearly scale factors can be applied (phs, amv, 3/17/08) +! (4 ) Now include emep SOx and emep emissions to 2005 (amv, 06/08) +! (5 ) Modify to access SHIP emissions from outside (phs, 06/08) +! (6 ) Account for monthly variations (amv, 12/9/08) +! 18 Dec 2009 - Aaron van D - Created routine EMISS_EMEP_05x0666 +! 18 Dec 2009 - Aaron van D - Created routine READ_EMEP_UPDATED_05x0666 +! 18 Dec 2009 - Aaron van D - Created routine READ_EUROPE_MASK_05x0666 +! 11 Jan 2010 - Aaron van D - Max scale year is now 2007, for consistency +! 11 Jan 2010 - Aaron van D - Extend 1x1 emission files to 2007. Routine +! READ_EMEP_UPDATED now mimics routine +! READ_EMEP_UPDATED_05x0666. +! 26 Jan 2010 - R. Yantosca - Minor bug fix in INIT_EMEP +! 31 Aug 2010 - R. Yantosca - Updated comments +! 24 Nov 2010 - G. Vinken - Updated EMEP mask file +!EOP +!------------------------------------------------------------------------------ +! +! !PRIVATE DATA MEMBERS: +! + ! Array for geographic mask + REAL*8, ALLOCATABLE :: EUROPE_MASK(:,:) + + ! Arrays for ground-based emissions + REAL*8, ALLOCATABLE :: EMEP_NOx(:,:) + REAL*8, ALLOCATABLE :: EMEP_CO(:,:) + REAL*8, ALLOCATABLE :: EMEP_SO2(:,:) + REAL*8, ALLOCATABLE :: EMEP_NH3(:,:) + REAL*8, ALLOCATABLE :: EMEP_ALK4(:,:) + REAL*8, ALLOCATABLE :: EMEP_MEK(:,:) + REAL*8, ALLOCATABLE :: EMEP_ALD2(:,:) + REAL*8, ALLOCATABLE :: EMEP_PRPE(:,:) + REAL*8, ALLOCATABLE :: EMEP_C2H6(:,:) + + ! Arrays for ship emissions + REAL*8, ALLOCATABLE :: EMEP_CO_SHIP(:,:) + REAL*8, ALLOCATABLE :: EMEP_SO2_SHIP(:,:) + REAL*8, ALLOCATABLE :: EMEP_NOx_SHIP(:,:) + + CONTAINS +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_europe_mask +! +! !DESCRIPTION: Function GET\_EUROPE\_MASK returns the value of the EUROPE +! mask for EMEP emissions at grid box (I,J). MASK=1 if (I,J) is in the +! European region, or MASK=0 otherwise. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_EUROPE_MASK( I, J ) RESULT( EUROPE ) +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: I ! Longitude index + INTEGER, INTENT(IN) :: J ! Latitude index +! +! !RETURN VALUE: +! + REAL*8 :: EUROPE ! Returns the mask value @ (I,J) +! +! !REVISION HISTORY: +! 01 Nov 2005 - B. Field, R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + !================================================================= + ! GET_EUROPE_MASK begins here! + !================================================================= + EUROPE = EUROPE_MASK(I,J) + + END FUNCTION GET_EUROPE_MASK +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_emep_anthro +! +! !DESCRIPTION: Function GET\_EMEP\_ANTHRO returns the EMEP emission for +! GEOS-CHEM grid box (I,J) and tracer N. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_EMEP_ANTHRO( I, J, N, KG_S, SHIP ) RESULT( EMEP ) +! +! !USES: +! + USE TRACERID_MOD, ONLY : IDTNOX, IDTCO, IDTALK4, IDTMEK + USE TRACERID_MOD, ONLY : IDTALD2, IDTPRPE, IDTC2H6, IDTSO2 + USE TRACERID_MOD, ONLY : IDTNH3 + USE TRACER_MOD, ONLY : XNUMOL + USE GRID_MOD, ONLY : GET_AREA_CM2 +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: I ! Longitude index + INTEGER, INTENT(IN) :: J ! Latitude index + INTEGER, INTENT(IN) :: N ! Tracer number + LOGICAL, INTENT(IN), OPTIONAL :: KG_S ! Return emissions in [kg/s] + LOGICAL, INTENT(IN), OPTIONAL :: SHIP ! Return ship emissions +! +! RETURN VALUE: +! + REAL*8 :: EMEP ! Returns emissions at (I,J) +! +! !REVISION HISTORY: +! 01 Nov 2005 - B. Field, R. Yantosca - Initial version +! (1 ) added SOx, SOx ship and NH3 emissions, plus optional kg/s output +! (amv, 06/2008) +! (2 ) Now returns ship emissions if requested (phs, 6/08) +! (3 ) Added checks to avoid calling unavailable ship emissions (phs, 6/08) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL :: DO_KGS, IS_SHIP + INTEGER :: NN, HAS_SHIP(3) + + !================================================================= + ! GET_EMEP_ANTHRO begins here! + !================================================================= + + ! Initialize + NN = N + IS_SHIP = .FALSE. + DO_KGS = .FALSE. + + IF ( PRESENT( KG_S ) ) DO_KGS = KG_S + IF ( PRESENT( SHIP ) ) IS_SHIP = SHIP + + ! check SHIP availability + HAS_SHIP = (/ IDTNOX, IDTCO, IDTSO2 /) + + IF ( IS_SHIP .AND. .NOT. ANY( HAS_SHIP == N) ) THEN + WRITE(6,*)'WARNING: EMEP SHIP emissions not available for'// + $ 'tracer #',N + EMEP = 0D0 + RETURN + ENDIF + + ! NOx + IF ( N == IDTNOX ) THEN + IF ( IS_SHIP ) THEN + EMEP = EMEP_NOx_SHIP(I,J) + ELSE + EMEP = EMEP_NOx(I,J) + ENDIF +!%%%%%%%%%%%%%KLUDGE TO EMITT SHIP NOX AS NOX %%%%%%%%%%%%%% +! IF ( IS_SHIP ) THEN +! EMEP = 0d0 +! ELSE +! EMEP = EMEP_NOx(I,J) + EMEP_NOx_SHIP(I,J) +! ENDIF +!%%%%%%%%%%%%% END KLUDGE %%%%%%%%%%%%%% + + ! CO + ELSE IF ( N == IDTCO ) THEN + IF ( IS_SHIP ) THEN + EMEP = EMEP_CO_SHIP(I,J) + ELSE + EMEP = EMEP_CO(I,J) + ENDIF + + ! ALK4 (>= C4 alkanes) + ELSE IF ( N == IDTALK4 ) THEN + EMEP = EMEP_ALK4(I,J) + + ! MEK + ELSE IF ( N == IDTMEK ) THEN + EMEP = EMEP_MEK(I,J) + + ! ALD2 (acetaldehyde) + ELSE IF ( N == IDTALD2 ) THEN + EMEP = EMEP_ALD2(I,J) + + ! PRPE (>= C3 alkenes) + ELSE IF ( N == IDTPRPE ) THEN + EMEP = EMEP_PRPE(I,J) + + ! C2H6 + ELSE IF ( N == IDTC2H6 ) THEN + EMEP = EMEP_C2H6(I,J) + + ! SO2 + ELSE IF ( N == IDTSO2 ) THEN + IF ( IS_SHIP ) THEN + EMEP = EMEP_SO2_SHIP(I,J) + ELSE + EMEP = EMEP_SO2(I,J) + ENDIF + + ! NH3 + ELSE IF ( N == IDTNH3 ) THEN + EMEP = EMEP_NH3(I,J) + + ! Otherwise return a negative value to indicate + ! that there are no EMEP emissions for tracer N + ELSE + EMEP = -1d0 + + ENDIF + + !------------------------------ + ! Convert units (if necessary) + !------------------------------ + IF ( DO_KGS ) THEN + + EMEP = EMEP * GET_AREA_CM2(J) / XNUMOL(NN) + + ENDIF + + END FUNCTION GET_EMEP_ANTHRO +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emiss_emep +! +! !DESCRIPTION: Subroutine EMISS\_EMEP reads the EMEP emission fields at +! 1x1 resolution and regrids them to the current model resolution. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_EMEP +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, OPEN_BPCH2_FOR_READ + USE FILE_MOD, ONLY : IU_FILE, IOERROR + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE LOGICAL_MOD, ONLY : LFUTURE + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_YEAR + USE TIME_MOD, ONLY : GET_MONTH + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR + + !USE CMN_SIZE_MOD ! Size parameters + !USE CMN_O3_MOD ! SCALEYEAR +# include "CMN_SIZE" +# include "CMN_O3" +! +! !REVISION HISTORY: +! 01 Nov 2005 - B. Field, R. Yantosca - Initial version +! (1 ) Modified for IPCC future emissions. Now references LFUTURE from +! "logical_mod.f". (bmy, 5/30/06) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: EMEP_NYMD, EMEP_YEAR + REAL*8 :: EMEP_TAU, TAU0 + CHARACTER(LEN=255) :: FILENAME + + ! For bpch file format + INTEGER :: I, J, L, N, IOS + INTEGER :: NTRACER, NSKIP + INTEGER :: HALFPOLAR, CENTER180 + INTEGER :: NI, NJ, NL + INTEGER :: IFIRST, JFIRST, LFIRST + INTEGER :: SCALEYEAR + REAL*4 :: ARRAY(I1x1,J1x1,1) + REAL*4 :: LONRES, LATRES + REAL*4 :: Sc(IIPAR,JJPAR) + REAL*8 :: ZTAU0, ZTAU1 + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=40) :: RESERVED + + !================================================================= + ! EMISS_EMEP begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_EMEP + FIRST = .FALSE. + ENDIF + + ! 1x1 file name for EMEP 2000 + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'EMEP_200510/EMEP.geos.1x1.YYYY' + + IF ( FSCALYR < 0 ) THEN + SCALEYEAR = GET_YEAR() + ELSE + SCALEYEAR = FSCALYR + ENDIF + + ! EMEP 2000 data is only defined from 1985-2000 + EMEP_YEAR = MAX( MIN( SCALEYEAR, 2000 ), 1985 ) + + ! YYYYMMDD value for 1st day of EMEP_YEAR + EMEP_NYMD = ( EMEP_YEAR * 10000 ) + 0101 + + ! TAU0 value corresponding to EMEP_NYMD + EMEP_TAU = GET_TAU0( 1, 1, EMEP_YEAR ) + + ! Expand filename + CALL EXPAND_DATE( FILENAME, EMEP_NYMD, 000000 ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - EMISS_EMEP: Reading ', a ) + + !================================================================= + ! Read data at 1x1 resolution and regrid to current grid size + !================================================================= + + ! Open file + CALL OPEN_BPCH2_FOR_READ( IU_FILE, FILENAME ) + + ! Read the entire file in one pass (for I/O optimization) + DO + + ! Read 1st data block header line + READ( IU_FILE, IOSTAT=IOS ) + & MODELNAME, LONRES, LATRES, HALFPOLAR, CENTER180 + + ! Check for EOF or errors + IF ( IOS < 0 ) EXIT + IF ( IOS > 0 ) CALL IOERROR( IOS, IU_FILE, 'emiss_emep:2' ) + + ! Read 2nd data block header line + READ( IU_FILE, IOSTAT=IOS ) + & CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED, + & NI, NJ, NL, IFIRST, JFIRST, LFIRST, NSKIP + + ! Error check + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'emiss_emep:3' ) + + ! Read data [molec/cm2/s] or [atoms C/cm2/s] + READ( IU_FILE, IOSTAT=IOS ) ARRAY(1:NI,1:NJ,1:NL) + + ! Error check + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'emiss_emep:4' ) + + ! Regrid data from 1x1 + SELECT CASE ( NTRACER ) + + ! NOx [molec/cm2/s] + CASE( 1 ) + CALL DO_REGRID_1x1( UNIT, ARRAY, EMEP_NOx ) + + ! CO [molec/cm2/s] + CASE( 4 ) + CALL DO_REGRID_1x1( UNIT, ARRAY, EMEP_CO ) + + ! ALK4 [atoms C/cm2/s] + CASE( 5 ) + CALL DO_REGRID_1x1( UNIT, ARRAY, EMEP_ALK4 ) + + ! MEK [atoms C/cm2/s] + CASE( 10 ) + CALL DO_REGRID_1x1( UNIT, ARRAY, EMEP_MEK ) + + ! ALD2 [atoms C/cm2/s] + CASE( 11 ) + CALL DO_REGRID_1x1( UNIT, ARRAY, EMEP_ALD2 ) + + ! PRPE [atoms C/cm2/s] + CASE( 18 ) + CALL DO_REGRID_1x1( UNIT, ARRAY, EMEP_PRPE ) + + ! C2H6 [atoms C/cm2/s] + CASE( 21 ) + CALL DO_REGRID_1x1( UNIT, ARRAY, EMEP_C2H6 ) + + CASE DEFAULT + ! Nothing + + END SELECT + + ENDDO + + ! Close file + CLOSE( IU_FILE ) + + !================================================================= + ! Get and apply annual emissions factors (amv, phs, 3/17/08) + !================================================================= + + !================================================================= + ! If we are at or above 1990, can apply updated EMEP emissions for + ! NOx, CO, NH3 and include SOx (amv, 06/04/08) + !================================================================= + + print*, 'SCALEYEAR=', SCALEYEAR + + IF ( SCALEYEAR > 1989 ) THEN + + ! new EMEP data is only defined from 1990-2007 + EMEP_YEAR = MIN( SCALEYEAR, 2007 ) + + CALL READ_EMEP_UPDATED( 1, EMEP_YEAR, EMEP_NOx, 0 ) + CALL READ_EMEP_UPDATED( 4, EMEP_YEAR, EMEP_CO, 0 ) + CALL READ_EMEP_UPDATED( 26, EMEP_YEAR, EMEP_SO2, 0 ) + CALL READ_EMEP_UPDATED( 30, EMEP_YEAR, EMEP_NH3, 1 ) + + + CALL READ_EMEP_UPDATED( 1, EMEP_YEAR, EMEP_NOx_SHIP, 2 ) + CALL READ_EMEP_UPDATED( 4, EMEP_YEAR, EMEP_CO_SHIP, 2 ) + CALL READ_EMEP_UPDATED( 26, EMEP_YEAR, EMEP_SO2_SHIP, 2 ) + + ! Need to use for SOx/NH3 anyways, but SOx scale back further + ELSE + + CALL READ_EMEP_UPDATED( 26, 1990, EMEP_SO2, 0 ) + CALL READ_EMEP_UPDATED( 26, 1990, EMEP_SO2_SHIP, 2 ) + CALL READ_EMEP_UPDATED( 30, 1990, EMEP_NH3, 1 ) + + CALL GET_ANNUAL_SCALAR( 73, 1990, SCALEYEAR, Sc ) + EMEP_SO2(:,:) = EMEP_SO2(:,:) * Sc(:,:) +! EMEP_SO2_SHIP = EMEP_SO2_SHIP * Sc ! do not scale SHIP + + ENDIF + + !================================================================= + ! Compute IPCC future emissions (if necessary) + !================================================================= + IF ( LFUTURE ) THEN + CALL EMEP_SCALE_FUTURE + ENDIF + + !================================================================= + ! Print emission totals + !================================================================= + + ! Print totals for EMEP_YEAR + CALL TOTAL_ANTHRO_TG( EMEP_YEAR, SCALEYEAR, GET_MONTH() ) + + END SUBROUTINE EMISS_EMEP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emiss_emep_05x0666 +! +! !DESCRIPTION: Subroutine EMISS\_EMEP reads the EMEP emission fields at +! 05x0666 resolution and regrids them to the current model resolution. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_EMEP_05x0666 +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE LOGICAL_MOD, ONLY : LFUTURE + USE REGRID_1x1_MOD, ONLY : DO_REGRID_05x0666 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_YEAR + USE TIME_MOD, ONLY : GET_MONTH + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR_05x0666_NESTED + + !USE CMN_SIZE_MOD ! Size parameters + !USE CMN_O3_MOD ! SCALEYEAR +# include "CMN_SIZE" +# include "CMN_O3" +! +! !REVISION HISTORY: +! 23 Oct 2006 - A. v. Donkelaar - Initial version, modified from EMISS_EMEP +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: EMEP_NYMD, EMEP_YEAR + REAL*8 :: EMEP_TAU, TAU0 + CHARACTER(LEN=255) :: FILENAME + + ! For bpch file format + INTEGER :: I, J, L, N, IOS + INTEGER :: NTRACER, NSKIP + INTEGER :: HALFPOLAR, CENTER180 + INTEGER :: NI, NJ, NL + INTEGER :: IFIRST, JFIRST, LFIRST + INTEGER :: SCALEYEAR + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*4 :: LONRES, LATRES + REAL*4 :: Sc(IIPAR,JJPAR) + REAL*8 :: ZTAU0, ZTAU1 + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=40) :: RESERVED + + !================================================================= + ! EMISS_EMEP begins here! + !================================================================= + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_EMEP + FIRST = .FALSE. + ENDIF + + ! 1x1 file name for EMEP 2000 + FILENAME = TRIM( DATA_DIR ) // + & 'EMEP_200510/EMEP.geos.05x0666.YYYY' + + IF ( FSCALYR < 0 ) THEN + SCALEYEAR = GET_YEAR() + ELSE + SCALEYEAR = FSCALYR + ENDIF + + ! EMEP 2000 data is only defined from 1985-2000 + EMEP_YEAR = MAX( MIN( SCALEYEAR, 2000 ), 1985 ) + + ! YYYYMMDD value for 1st day of EMEP_YEAR + EMEP_NYMD = ( EMEP_YEAR * 10000 ) + 0101 + + ! TAU0 value corresponding to EMEP_NYMD + EMEP_TAU = GET_TAU0( 1, 1, EMEP_YEAR ) + + ! Expand filename + CALL EXPAND_DATE( FILENAME, EMEP_NYMD, 000000 ) + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - EMISS_EMEP_05x0666: Reading ', a ) + + !================================================================= + ! Read data at 05x0666 resolution + !================================================================= + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 4, EMEP_TAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + EMEP_CO(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 1, EMEP_TAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + EMEP_NOx(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE',18, EMEP_TAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + EMEP_PRPE(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 5, EMEP_TAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + EMEP_ALK4(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE',21, EMEP_TAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + EMEP_C2H6(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE',11, EMEP_TAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + EMEP_ALD2(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE',10, EMEP_TAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + EMEP_MEK(:,:) = ARRAY(:,:,1) + + !================================================================= + ! Get and apply annual emissions factors (amv, phs, 3/17/08) + !================================================================= + + !================================================================= + ! If we are at or above 1990, can apply updated EMEP emissions for + ! NOx, CO, NH3 and include SOx (amv, 06/04/08) + !================================================================= + + IF ( SCALEYEAR > 1989 ) THEN + + ! new EMEP data is only defined from 1990-2007 + EMEP_YEAR = MIN( SCALEYEAR, 2007 ) + + CALL READ_EMEP_UPDATED_05x0666( 1, EMEP_YEAR, EMEP_NOx, 0 ) + CALL READ_EMEP_UPDATED_05x0666( 4, EMEP_YEAR, EMEP_CO, 0 ) + CALL READ_EMEP_UPDATED_05x0666( 26, EMEP_YEAR, EMEP_SO2, 0 ) + CALL READ_EMEP_UPDATED_05x0666( 30, EMEP_YEAR, EMEP_NH3, 1 ) + + CALL READ_EMEP_UPDATED_05x0666( 1,EMEP_YEAR, EMEP_NOx_SHIP, 2) + CALL READ_EMEP_UPDATED_05x0666( 4,EMEP_YEAR, EMEP_CO_SHIP, 2) + CALL READ_EMEP_UPDATED_05x0666( 26,EMEP_YEAR, EMEP_SO2_SHIP, 2) + + ! Need to use for SOx/NH3 anyways, but SOx scale back further + ELSE + + CALL READ_EMEP_UPDATED_05x0666( 26, 1990, EMEP_SO2, 0 ) + CALL READ_EMEP_UPDATED_05x0666( 26, 1990, EMEP_SO2_SHIP, 2 ) + CALL READ_EMEP_UPDATED_05x0666( 30, 1990, EMEP_NH3, 1 ) + + CALL GET_ANNUAL_SCALAR_05x0666_NESTED(73,1990,SCALEYEAR,Sc) + EMEP_SO2(:,:) = EMEP_SO2(:,:) * Sc(:,:) +! EMEP_SO2_SHIP = EMEP_SO2_SHIP * Sc ! do not scale SHIP + + ENDIF + + + !================================================================= + ! Compute IPCC future emissions (if necessary) + !================================================================= + IF ( LFUTURE ) THEN + CALL EMEP_SCALE_FUTURE + ENDIF + + !================================================================= + ! Print emission totals + !================================================================= + + ! Print totals for EMEP_YEAR + CALL TOTAL_ANTHRO_TG( EMEP_YEAR, SCALEYEAR, GET_MONTH() ) + + END SUBROUTINE EMISS_EMEP_05x0666 +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emep_scale_future +! +! !DESCRIPTION: Subroutine EMEP\_SCALE\_FUTURE applies the IPCC future +! scale factors to the EMEP anthropogenic emissions. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMEP_SCALE_FUTURE +! +! !USES: +! + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_ALK4ff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_C2H6ff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_COff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_PRPEff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_TONEff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_VOCff + + !USE CMN_SIZE_MOD ! Size parameters +# include "CMN_SIZE" +! +! !REVISION HISTORY: +! 30 May 2006 - S. Wu & R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + + !================================================================= + ! EMEP_SCALE_FUTURE begins here! + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Future NOx [molec/cm2/s] + EMEP_NOx(I,J) = EMEP_NOx(I,J) * + & GET_FUTURE_SCALE_NOxff( I, J ) + + ! Future CO [molec/cm2/s] + EMEP_CO(I,J) = EMEP_CO(I,J) * + & GET_FUTURE_SCALE_COff( I, J ) + + ! Future ALK4 [atoms C/cm2/s] + EMEP_ALK4(I,J) = EMEP_ALK4(I,J) * + & GET_FUTURE_SCALE_ALK4ff( I, J ) + + ! Future MEK [atoms C/cm2/s] + EMEP_MEK(I,J) = EMEP_MEK(I,J) * + & GET_FUTURE_SCALE_TONEff( I, J ) + + ! Future ALD2 [atoms C/cm2/s] + EMEP_ALD2(I,J) = EMEP_ALD2(I,J) * + & GET_FUTURE_SCALE_VOCff( I, J ) + + ! Future PRPE [atoms C/cm2/s] + EMEP_PRPE(I,J) = EMEP_PRPE(I,J) * + & GET_FUTURE_SCALE_PRPEff( I, J ) + + ! Future C2H6 [atoms C/cm2/s] + EMEP_C2H6(I,J) = EMEP_C2H6(I,J) * + & GET_FUTURE_SCALE_C2H6ff( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + END SUBROUTINE EMEP_SCALE_FUTURE +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: total_anthro_Tg +! +! !DESCRIPTION: Subroutine TOTAL\_ANTHRO\_TG prints the amount of EMEP +! anthropogenic emissions that are emitted each month in Tg or Tg C. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE TOTAL_ANTHRO_TG( EMEP_YEAR, EMISS_YEAR, EMEP_MONTH ) +! +! !USES: +! + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE LOGICAL_MOD, ONLY : LEMEPSHIP + USE TIME_MOD, ONLY : ITS_A_LEAPYEAR + USE TRACER_MOD, ONLY : XNUMOL + USE TRACERID_MOD, ONLY : IDTNOX, IDTCO, IDTALK4, IDTMEK + USE TRACERID_MOD, ONLY : IDTALD2, IDTPRPE, IDTC2H6, IDTSO2 + USE TRACERID_MOD, ONLY : IDTNH3 + + !USE CMN_SIZE_MOD ! Size parameters +# include "CMN_SIZE" +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: EMEP_YEAR ! EMEP base year + INTEGER, INTENT(IN) :: EMISS_YEAR ! Current simulated year + INTEGER, INTENT(IN) :: EMEP_MONTH ! Current simulated month +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman, R. Yantosca - Initial version +! (1 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (2 ) Now replace FMOL with TRACER_MW_KG (bmy, 10/25/05) +! (3 ) Now only print totals of defined tracers; other totals will be +! printed as zeroes. (bmy, 2/6/06) +! (4 ) Now emissions and base year are arguments. Output in Tg/month +! since this is called monthly (phs, 12/9/08) +! (5 ) Bug fix, now print out correct monthly EMEP totals (bmy, 1/30/09) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + REAL*8 :: A, B(9), NOX, CO, ALK4 + REAL*8 :: MEK, ALD2, PRPE, C2H6, SO2 + REAL*8 :: NH3 + CHARACTER(LEN=3) :: UNIT + + ! Days per month + REAL*8 :: DAYS_IN_MONTH + REAL*8 :: DMON(12) = (/ 31d0, 28d0, 31d0, 30d0, + & 31d0, 30d0, 31d0, 31d0, + & 30d0, 31d0, 30d0, 31d0 /) + + !================================================================= + ! TOTAL_ANTHRO_TG begins here! + !================================================================= + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 100 ) + 100 FORMAT( 'M O N T H L Y E M E P E U R O P E A N + $ E M I S S I O N S', / ) + + ! indicate if we include ship emissions (automatic before 1990) + IF ( LEMEPSHIP .OR. ( EMISS_YEAR < 1990 )) WRITE( 6, 101 ) + 101 FORMAT( '( INCL. SHIP )', / ) + + WRITE( 6, 102 ) EMEP_YEAR + 102 FORMAT( 'Base Year :', i4 ) + + !---------------- + ! Sum emissions + !---------------- + + ! Get the proper # of days in the month for totaling + IF ( EMEP_MONTH == 2 .and. ITS_A_LEAPYEAR( EMISS_YEAR ) ) THEN + DAYS_IN_MONTH = DMON(EMEP_MONTH) + 1 + ELSE + DAYS_IN_MONTH = DMON(EMEP_MONTH) + ENDIF + + ! Define conversion factors for kg/molec + ! (Undefined tracers will be zero) + B(:) = 0d0 + IF ( IDTNOx > 0 ) B(1) = 14d-3 / 6.0225d23 ! Tg N + IF ( IDTCO > 0 ) B(2) = 1d0 / XNUMOL(IDTCO ) + IF ( IDTALK4 > 0 ) B(3) = 1d0 / XNUMOL(IDTALK4) + IF ( IDTMEK > 0 ) B(4) = 1d0 / XNUMOL(IDTMEK ) + IF ( IDTALD2 > 0 ) B(5) = 1d0 / XNUMOL(IDTALD2) + IF ( IDTPRPE > 0 ) B(6) = 1d0 / XNUMOL(IDTPRPE) + IF ( IDTC2H6 > 0 ) B(7) = 1d0 / XNUMOL(IDTC2H6) + IF ( IDTSO2 > 0 ) B(8) = 32d-3 / 6.0225d23 ! Tg S + IF ( IDTNH3 > 0 ) B(9) = 1d0 / XNUMOL(IDTNH3) + + ! Summing variables + NOX = 0d0 + CO = 0d0 + ALK4 = 0d0 + MEK = 0d0 + ALD2 = 0d0 + PRPE = 0d0 + C2H6 = 0d0 + SO2 = 0d0 + NH3 = 0d0 + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Surface area [cm2] * seconds in this year + ! Multiply by 1d-9 to convert from [kg] to [Tg] + A = GET_AREA_CM2( J ) * DAYS_IN_MONTH * 86400d0 * 1d-9 + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Sum emissions (list NOx as Tg N) + NOX = NOX + ( EMEP_NOX (I,J) + EMEP_NOX_SHIP(I,J) ) + $ * A * B(1) + CO = CO + ( EMEP_CO (I,J) + EMEP_CO_SHIP(I,J) ) + $ * A * B(2) + SO2 = SO2 + ( EMEP_SO2 (I,J) + EMEP_SO2_SHIP(I,J) ) + $ * A * B(8) + + ALK4 = ALK4 + EMEP_ALK4(I,J) * A * B(3) + MEK = MEK + EMEP_MEK (I,J) * A * B(4) + ALD2 = ALD2 + EMEP_ALD2(I,J) * A * B(5) + PRPE = PRPE + EMEP_PRPE(I,J) * A * B(6) + C2H6 = C2H6 + EMEP_C2H6(I,J) * A * B(7) + NH3 = NH3 + EMEP_NH3 (I,J) * A * B(9) + ENDDO + ENDDO + + !---------------- + ! Print sums + !---------------- + + ! Print totals in [kg/month] + WRITE( 6, 110 ) 'NOx ', EMISS_YEAR, EMEP_MONTH, NOx, ' N' + WRITE( 6, 110 ) 'CO ', EMISS_YEAR, EMEP_MONTH, CO, ' ' + WRITE( 6, 110 ) 'SO2 ', EMISS_YEAR, EMEP_MONTH, SO2, ' S' + WRITE( 6, 110 ) 'NH3 ', EMISS_YEAR, EMEP_MONTH, NH3, ' ' + WRITE( 6, 110 ) 'ALK4', EMISS_YEAR, EMEP_MONTH, ALK4, ' C' + WRITE( 6, 110 ) 'MEK ', EMISS_YEAR, EMEP_MONTH, MEK, ' C' + WRITE( 6, 110 ) 'ALD2', EMISS_YEAR, EMEP_MONTH, ALD2, ' C' + WRITE( 6, 110 ) 'PRPE', EMISS_YEAR, EMEP_MONTH, PRPE, ' C' + WRITE( 6, 110 ) 'C2H6', EMISS_YEAR, EMEP_MONTH, C2H6, ' C' + 110 FORMAT( 'EMEP anthropogenic ', a4, ' for ', i4, '/', i2.2, + & ': ', f13.6, ' Tg', a2 ) + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + END SUBROUTINE TOTAL_ANTHRO_TG +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_europe_mask +! +! !DESCRIPTION: Subroutine READ\_EUROPE\_MASK reads and regrids the +! Europe mask for the EMEP anthropogenic emissions. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_EUROPE_MASK +! +! !USES: +! + USE BPCH2_MOD, ONLY : READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + + !USE CMN_SIZE_MOD ! Size parameters +# include "CMN_SIZE" + +! !REVISION HISTORY: +! 18 Oct 2006 - R. Yantosca - Initial version +! (1 ) Now read the Europe mask from a disk file instead of defining it as +! a rectangular box (bmy, 10/18/06) +! (2 ) Updated the mask file to correspond with the 200911 EMEP emissions +! (gvinken, 11/24/10) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(I1x1,J1x1,1) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_EUROPE_MASK begins here! + !================================================================= + + ! File name +!----------------------------------------------------------------------- +! Prior to 11/24/10: +! Read in new mask file for EMEP emissions (gvinken, 11/24/10) +! FILENAME = TRIM( DATA_DIR_1x1 ) // +! & 'EMEP_200510/EMEP_mask.geos.1x1' +!----------------------------------------------------------------------- + FILENAME = TRIM( DATA_DIR_1x1 ) // + & 'EMEP_200911/EMEP_mask.geos.1x1' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_EUROPE_MASK: Reading ', a ) + + ! Read data [unitless] + CALL READ_BPCH2( FILENAME, 'LANDMAP', 2, + & 0d0, I1x1, J1x1, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Regrid from GEOS 1x1 GRID to current model resolution + CALL DO_REGRID_1x1( 'unitless', ARRAY, EUROPE_MASK ) + + END SUBROUTINE READ_EUROPE_MASK +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_europe_mask_05x0666 +! +! !DESCRIPTION: Subroutine READ\_EUROPE\_MASK reads and regrids the +! Europe mask for the EMEP anthropogenic emissions. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_EUROPE_MASK_05x0666 +! +! !USES: +! + USE BPCH2_MOD, ONLY : READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE REGRID_1x1_MOD, ONLY : DO_REGRID_05x0666 + + !USE CMN_SIZE_MOD ! Size parameters +# include "CMN_SIZE" +! +! !REVISION HISTORY: +! 18 Oct 2006 - R. Yantosca - Initial version +! (1 ) Now read the Europe mask from a disk file instead of defining it as +! a rectangular box (bmy, 10/18/06) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_EUROPE_MASK begins here! + !================================================================= + + ! File name + FILENAME = TRIM( DATA_DIR ) // + & 'EMEP_200510/EMEP_mask.geos.05x0666' + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_EUROPE_MASK: Reading ', a ) + + ! Read data [unitless] + CALL READ_BPCH2( FILENAME, 'LANDMAP', 2, + & 0d0, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + EUROPE_MASK(:,:) = ARRAY(:,:,1) + + END SUBROUTINE READ_EUROPE_MASK_05x0666 +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_emep_updated +! +! !DESCRIPTION: Subroutine READ\_EMEP\_UPDATED reads updated EMEP emissions +! from the year 1990 including SOx emissions. These are regridded to the +! simulation resolution. Ship emissions can also be included. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_EMEP_UPDATED( TRACER, EMEP_YEAR, ARRAY, wSHIP ) +! +! !USES: +! + USE BPCH2_MOD, ONLY : READ_BPCH2, GET_TAU0 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_MONTH + USE DIRECTORY_MOD, ONLY : DATA_DIR_1x1 + USE REGRID_1x1_MOD, ONLY : DO_REGRID_1x1 + USE LOGICAL_MOD, ONLY : LEMEPSHIP + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE TRACERID_MOD, ONLY : IDTNOx, IDTCO, IDTSO2, IDTNH3 + + !USE CMN_SIZE_MOD ! Size parameters + !USE CMN_O3_MOD ! SCALEYEAR +# include "CMN_SIZE" +# include "CMN_O3" +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: TRACER ! Tracer number + INTEGER, INTENT(IN) :: EMEP_YEAR ! Year of emissions to read + INTEGER, INTENT(IN) :: wSHIP ! Use ground, ship, or both? +! +! !OUTPUT PARAMETERS: +! + REAL*8, INTENT(OUT) :: ARRAY(IIPAR,JJPAR) ! Output array +! +! !REVISION HISTORY: +! 28 Jan 2009 - A. v. Donkelaar, P. Le Sager - Initial version +! 28 Jan 2009 - P. Le Sager - Now account for LEMEPSHIP +! 29 Oct 2009 - Added multi-species seasonality (amv) +! 04 Jan 2010 - Extended to 2007, changed input format (amv) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY_1x1(I1x1,J1x1,1) + REAL*4 :: ARRAY_1x1_SHIP(I1x1,J1x1,1) + REAL*4 :: ARRAY_1x1_LAND(I1x1,J1x1,1) + CHARACTER(LEN=255) :: FILENAME, DIR + REAL*8 :: EMEP_TAU, TAU, A, B + INTEGER :: EMEP_NYMD, MN, RATIOID, I, J + + + ARRAY_1x1_SHIP(:,:,:) = 0.d0 + ARRAY_1x1_LAND(:,:,:) = 0.d0 + + ! YYYYMMDD value for 1st day of EMEP_YEAR + EMEP_NYMD = ( EMEP_YEAR * 10000 ) + 0101 + + ! TAU0 value corresponding to EMEP_NYMD + EMEP_TAU = GET_TAU0( 1, 1, EMEP_YEAR ) + + ! Expand filename + DIR = TRIM( DATA_DIR_1x1 ) // 'EMEP_200911/' + + ! wSHIP = 0 means no ship emissions included + ! wSHIP = 1 means include ships emissions + ! wSHIP = 2 means only ship emissions + + IF ( wSHIP .lt. 2 ) THEN + + FILENAME = TRIM(DIR) // + & 'EMEP-YYYY.geos.1x1' + + CALL EXPAND_DATE( FILENAME, EMEP_NYMD, 000000 ) + + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_EMEP_UPDATED: Reading ', a ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', TRACER, + & EMEP_TAU, I1x1, J1x1, + & 1, ARRAY_1x1_LAND, QUIET=.TRUE. ) + + ENDIF + + IF ( ( wSHIP .gt. 0 ) .AND. LEMEPSHIP ) THEN + + FILENAME = TRIM(DIR) // + & 'EMEP-SHIP-YYYY.geos.1x1' + + CALL EXPAND_DATE( FILENAME, EMEP_NYMD, 000000 ) + + WRITE( 6, 101 ) TRIM( FILENAME ) + 101 FORMAT( ' - READ_EMEP_UPDATED: Reading ', a ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', TRACER, + & EMEP_TAU, I1x1, J1x1, + & 1, ARRAY_1x1_SHIP, QUIET=.TRUE. ) + + ENDIF + + ! Apply monthly variation (courtesy of the GENEMIS project + ! coordinated by the Institute of Energy Economics and the + ! Rational Use of Energy (IER) at the University of + ! Stuttgart) (amv, 11/24/2008) + + IF ( wSHIP .lt. 2 ) THEN + + ! Apply Monthly Factors over land + TAU = GET_TAU0( GET_MONTH(), 1, 2005) + + ! Use hardwired numbers so this works with tagged-CO + ! simulation (zhej, dkh, 02/09/12, adj32_019) + IF ( TRACER .eq. 1 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'NOx-EMEP-SeasonalScalar.geos.1x1' + RATIOID = 71 + ELSEIF ( TRACER .eq. 4 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'CO-EMEP-SeasonalScalar.geos.1x1' + RATIOID = 72 + ELSEIF ( TRACER .eq. 26 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'SOx-EMEP-SeasonalScalar.geos.1x1' + RATIOID = 73 + ELSEIF ( TRACER .eq. 30 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'NH3-EMEP-SeasonalScalar.geos.1x1' + RATIOID = 74 + ENDIF + + ! Echo info + WRITE( 6, 101 ) TRIM( FILENAME ) + + ! Read data + CALL READ_BPCH2( FILENAME, 'RATIO-2D', RATIOID, + & TAU, I1x1, J1x1, + & 1, ARRAY_1x1, QUIET=.TRUE. ) + + ARRAY_1x1_LAND(:,:,1) = ARRAY_1x1_LAND(:,:,1) + & * ARRAY_1x1(:,:,1) + + ENDIF + + IF ( wSHIP .eq. 0 ) ARRAY_1x1(:,:,1) = ARRAY_1x1_LAND(:,:,1) + IF ( wSHIP .eq. 1 ) ARRAY_1x1(:,:,1) = ARRAY_1x1_LAND(:,:,1) + + & ARRAY_1x1_SHIP(:,:,1) + IF ( wSHIP .eq. 2 ) ARRAY_1x1(:,:,1) = ARRAY_1x1_SHIP(:,:,1) + + CALL DO_REGRID_1x1('kg/yr', ARRAY_1x1, ARRAY) + + ! Convert SOx to SO2 assuming a SOx is 95% SO2 over Europe, as used + ! throughout GEOS-Chem, and as per Chin et al, 2000 + IF ( TRACER .eq. 26 ) ARRAY(:,:) = ARRAY(:,:) * 0.95d0 + + ! convert to molec/cm2 for consistency with previous + ! emissions + B = 0d0 + ! Use hardwired numbers so this works with tagged-CO + ! simulation (zhej, dkh, 02/09/12, adj32_019) + IF ( TRACER .eq. 1 ) B = 1.d3 / 46d0 * 6.0225d23 + IF ( TRACER .eq. 4 ) B = 1.d3 / 28d0 * 6.0225d23 + IF ( TRACER .eq. 26 ) B = 1.d3 / 64d0 * 6.0225d23 + IF ( TRACER .eq. 30 ) B = 1.d3 / 17d0 * 6.0225d23 + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Surface area [cm2] * sec per year + A = GET_AREA_CM2( J ) * 365d0 * 86400d0 + + ! Loop over longitudes + DO I = 1, IIPAR + + ARRAY(I,J) = ARRAY(I,J) / A * B + + ENDDO + ENDDO + + + END SUBROUTINE READ_EMEP_UPDATED +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_emep_updated_05x0666 +! +! !DESCRIPTION: Subroutine READ\_EMEP\_UPDATED reads updated EMEP emissions +! from the year 1990 including SOx emissions. These are regridded to the +! simulation resolution. Ship emissions can also be included. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_EMEP_UPDATED_05x0666( TRACER, EMEP_YEAR, ARRAY, + & wSHIP ) +! +! !USES: +! + USE BPCH2_MOD, ONLY : READ_BPCH2, GET_TAU0 + USE TIME_MOD, ONLY : EXPAND_DATE, GET_MONTH + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE REGRID_1x1_MOD, ONLY : DO_REGRID_05x0666 + USE LOGICAL_MOD, ONLY : LEMEPSHIP + USE TRACERID_MOD, ONLY : IDTNOx, IDTCO, IDTSO2, IDTNH3 + USE GRID_MOD, ONLY : GET_AREA_CM2 + + !USE CMN_SIZE_MOD ! Size parameters + !USE CMN_O3_MOD ! SCALEYEAR +# include "CMN_SIZE" +# include "CMN_O3" +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: TRACER ! Tracer number + INTEGER, INTENT(IN) :: EMEP_YEAR ! Year of emissions to read + INTEGER, INTENT(IN) :: wSHIP ! Use ground, ship, or both? +! +! !OUTPUT PARAMETERS: +! + REAL*8, INTENT(OUT) :: ARRAY(IIPAR,JJPAR) ! Output array +! +! !REVISION HISTORY: +! 28 Jan 2009 - A. v. Donkelaar, P. Le Sager - Initial version +! 28 Jan 2009 - P. Le Sager - Now account for LEMEPSHIP +! 29 Oct 2009 - Added multi-species seasonality (amv) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*8 :: ARRAY_05x0666(IIPAR,JJPAR,1) + REAL*4 :: ARRAY_05x0666_R4(IIPAR,JJPAR,1) + REAL*4 :: ARRAY_05x0666_SHIP(IIPAR,JJPAR,1) + REAL*4 :: ARRAY_05x0666_LAND(IIPAR,JJPAR,1) + CHARACTER(LEN=255) :: FILENAME, DIR + REAL*8 :: EMEP_TAU, TAU, A, B + INTEGER :: EMEP_NYMD, MN, RATIOID, I, J + CHARACTER(LEN=2) :: SMN + CHARACTER(LEN=1) :: SSMN + + ARRAY_05x0666_SHIP(:,:,:) = 0.d0 + ARRAY_05x0666_LAND(:,:,:) = 0.d0 + + ! YYYYMMDD value for 1st day of EMEP_YEAR + EMEP_NYMD = ( EMEP_YEAR * 10000 ) + 0101 + + ! TAU0 value corresponding to EMEP_NYMD + EMEP_TAU = GET_TAU0( 1, 1, EMEP_YEAR ) + + ! Expand filename + DIR = TRIM( DATA_DIR ) // 'EMEP_200911/' + + ! wSHIP = 0 means no ship emissions included + ! wSHIP = 1 means include ships emissions + ! wSHIP = 2 means only ship emissions + + IF ( wSHIP .lt. 2 ) THEN + + FILENAME = TRIM(DIR) // + & 'EMEP-YYYY.1p2x2p3.eu.bpch' + + CALL EXPAND_DATE( FILENAME, EMEP_NYMD, 000000 ) + + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_EMEP_UPDATED_05x0666 + & : Reading ', a ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', TRACER, + & EMEP_TAU, IIPAR, JJPAR, + & 1, ARRAY_05x0666_LAND, QUIET=.TRUE. ) + + ENDIF + + IF ( ( wSHIP .gt. 0 ) .AND. LEMEPSHIP ) THEN + + FILENAME = TRIM(DIR) // + & 'EMEP-SHIP-YYYY.1p2x2p3.eu.bpch' + + CALL EXPAND_DATE( FILENAME, EMEP_NYMD, 000000 ) + + WRITE( 6, 101 ) TRIM( FILENAME ) + 101 FORMAT( ' - READ_EMEP_UPDATED_05x0666 + & : Reading ', a ) + + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', TRACER, + & EMEP_TAU, IIPAR, JJPAR, + & 1, ARRAY_05x0666_SHIP, QUIET=.TRUE. ) + + ENDIF + + ! Apply monthly variation (courtesy of the GENEMIS project + ! coordinated by the Institute of Energy Economics and the + ! Rational Use of Energy (IER) at the University of + ! Stuttgart) (amv, 11/24/2008) + + ! Expand filename + DIR = TRIM( DATA_DIR ) // 'EMEP_200806/' + + IF ( wSHIP .lt. 2 ) THEN + + ! Apply Monthly Factors over land + TAU = GET_TAU0( GET_MONTH(), 1, 2005) + + IF ( TRACER .eq. 1 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'NOx-EMEP-SeasonalScalar.geos.05x0666' + RATIOID = 71 + ELSEIF ( TRACER .eq. 4 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'CO-EMEP-SeasonalScalar.geos.05x0666' + RATIOID = 72 + ELSEIF ( TRACER .eq. 26 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'SOx-EMEP-SeasonalScalar.geos.05x0666' + RATIOID = 73 + ELSEIF ( TRACER .eq. 30 ) THEN + FILENAME = TRIM( DIR ) // 'SeasonalVariation/' + & // 'NH3-EMEP-SeasonalScalar.geos.05x0666' + RATIOID = 74 + ENDIF + + ! Echo info + WRITE( 6, 101 ) TRIM( FILENAME ) + + ! Read data + CALL READ_BPCH2( FILENAME, 'RATIO-2D', RATIOID, + & TAU, IIPAR, JJPAR, + & 1, ARRAY_05x0666_R4, QUIET=.TRUE. ) + + ARRAY_05x0666_LAND(:,:,1) = ARRAY_05x0666_LAND(:,:,1) + & * ARRAY_05x0666_R4(:,:,1) + + ENDIF + + IF ( wSHIP .eq. 0 ) ARRAY_05x0666(:,:,1) = + & ARRAY_05x0666_LAND(:,:,1) + IF ( wSHIP .eq. 1 ) ARRAY_05x0666(:,:,1) = + & ARRAY_05x0666_LAND(:,:,1) + ARRAY_05x0666_SHIP(:,:,1) + IF ( wSHIP .eq. 2 ) ARRAY_05x0666(:,:,1) = + & ARRAY_05x0666_SHIP(:,:,1) + + ARRAY(:,:) = ARRAY_05x0666(:,:,1) + + ! Convert SOx to SO2 assuming a SOx is 95% SO2 over Europe, as used + ! throughout GEOS-Chem, and as per Chin et al, 2000 + IF ( TRACER .eq. 26 ) ARRAY(:,:) = ARRAY(:,:) * 0.95d0 + + ! convert to molec/cm2 for consistency with previous + ! emissions + B = 0d0 + ! Use hardwired numbers so this works with tagged-CO + ! simulation (zhej, dkh, 02/09/12, adj32_019) + IF ( TRACER .eq. 1 ) B = 1.d3 / 46d0 * 6.0225d23 + IF ( TRACER .eq. 4 ) B = 1.d3 / 28d0 * 6.0225d23 + IF ( TRACER .eq. 26 ) B = 1.d3 / 64d0 * 6.0225d23 + IF ( TRACER .eq. 30 ) B = 1.d3 / 17d0 * 6.0225d23 + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Surface area [cm2] * sec per year + A = GET_AREA_CM2( J ) * 365d0 * 86400d0 + + ! Loop over longitudes + DO I = 1, IIPAR + + ARRAY(I,J) = ARRAY(I,J) / A * B + + ENDDO + ENDDO + + END SUBROUTINE READ_EMEP_UPDATED_05x0666 +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: init_emep +! +! !DESCRIPTION: Subroutine INIT\_EMEP allocates and zeroes EMEP module +! arrays, and also creates the mask which defines the European region. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE INIT_EMEP +! +! !USES: +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + USE GRID_MOD, ONLY : GET_XMID, GET_YMID + USE LOGICAL_MOD, ONLY : LEMEP + + !USE CMN_SIZE_MOD ! Size parameters +# include "CMN_SIZE" +! +! !REVISION HISTORY: +! 01 Nov 2005 - B. Field, R. Yantosca - Initial version +! (1 ) Now call READ_EUROPE_MASK to read & regrid EUROPE_MASK from disk +! instead of just defining it as a rectangular box. (bmy, 10/18/06) +! 26 Jan 2010 - R. Yantosca - Fixed cut-n-paste error. Now make sure to zero +! EMEP_CO_SHIP and EMEP_NOx_SHIP. +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: AS, I, J, X, Y + + !================================================================= + ! INIT_EMEP begins here! + !================================================================= + + ! Return if LEMEP is false + IF ( .not. LEMEP ) RETURN + + !-------------------------------- + ! Allocate and zero arrays + !-------------------------------- + ALLOCATE( EMEP_NOx( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_NOx' ) + EMEP_NOx = 0d0 + + ALLOCATE( EMEP_CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_CO' ) + EMEP_CO = 0d0 + + ALLOCATE( EMEP_SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_SO2' ) + EMEP_SO2 = 0d0 + + ALLOCATE( EMEP_SO2_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_SO2_SHIP' ) + EMEP_SO2_SHIP = 0d0 + + ALLOCATE( EMEP_CO_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_CO_SHIP' ) + EMEP_CO_SHIP = 0d0 + + ALLOCATE( EMEP_NOx_SHIP( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_NOx_SHIP' ) + EMEP_NOx_SHIP = 0d0 + + ALLOCATE( EMEP_NH3( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_NH3' ) + EMEP_NH3 = 0d0 + + ALLOCATE( EMEP_ALK4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_ALK4' ) + EMEP_ALK4 = 0d0 + + ALLOCATE( EMEP_MEK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_MEK' ) + EMEP_MEK = 0d0 + + ALLOCATE( EMEP_ALD2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_ALD2' ) + EMEP_ALD2 = 0d0 + + ALLOCATE( EMEP_PRPE( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_PRPE' ) + EMEP_PRPE = 0d0 + + ALLOCATE( EMEP_C2H6( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EMEP_C2H6' ) + EMEP_C2H6 = 0d0 + + ALLOCATE( EUROPE_MASK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EUROPE_MASK' ) + EUROPE_MASK = 0d0 + + ! Read and regrid the European mask +#if defined(GRID05x0666) + CALL READ_EUROPE_MASK_05x0666 +#else + CALL READ_EUROPE_MASK +#endif + + END SUBROUTINE INIT_EMEP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: cleanup_emep +! +! !DESCRIPTION: Subroutine CLEANUP\_EMEP deallocates all module arrays. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE CLEANUP_EMEP +! +! !REVISION HISTORY: +! 1 Nov 2005 - R. Yantosca - Initial Version +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! CLEANUP_EMEP begins here! + !================================================================= + IF ( ALLOCATED( EMEP_NOx ) ) DEALLOCATE( EMEP_NOx ) + IF ( ALLOCATED( EMEP_CO ) ) DEALLOCATE( EMEP_CO ) + IF ( ALLOCATED( EMEP_SO2 ) ) DEALLOCATE( EMEP_SO2 ) + IF ( ALLOCATED( EMEP_SO2_SHIP ) ) DEALLOCATE( EMEP_SO2_SHIP ) + IF ( ALLOCATED( EMEP_CO_SHIP ) ) DEALLOCATE( EMEP_CO_SHIP ) + IF ( ALLOCATED( EMEP_NOx_SHIP ) ) DEALLOCATE( EMEP_NOx_SHIP ) + IF ( ALLOCATED( EMEP_NH3 ) ) DEALLOCATE( EMEP_NH3 ) + IF ( ALLOCATED( EMEP_ALK4 ) ) DEALLOCATE( EMEP_ALK4 ) + IF ( ALLOCATED( EMEP_MEK ) ) DEALLOCATE( EMEP_MEK ) + IF ( ALLOCATED( EMEP_ALD2 ) ) DEALLOCATE( EMEP_ALD2 ) + IF ( ALLOCATED( EMEP_PRPE ) ) DEALLOCATE( EMEP_PRPE ) + IF ( ALLOCATED( EMEP_C2H6 ) ) DEALLOCATE( EMEP_C2H6 ) + IF ( ALLOCATED( EUROPE_MASK ) ) DEALLOCATE( EUROPE_MASK ) + + END SUBROUTINE CLEANUP_EMEP +!EOC + END MODULE EMEP_MOD diff --git a/code/emf_scale.f b/code/emf_scale.f new file mode 100644 index 0000000..4d74c59 --- /dev/null +++ b/code/emf_scale.f @@ -0,0 +1,113 @@ +! $Id: emf_scale.f,v 1.1 2009/06/09 21:51:50 daven Exp $ + SUBROUTINE EMF_SCALE( I, J, N, NN, + & IREF, JREF, JSCEN, XEMISR, XEMISRN ) +! +!****************************************************************************** +! Subroutine EMF_SCALE (bmy, 4/2/98, 10/3/05) does the following: +! +! (1) Saves original values of EMISR, EMISRN, EMISPN +! so that they can be restored later (after scaling) +! +! (2) Scales emissions to weekend or weekday usage (using scale factors +! stored in the SCNR89 array) +! +! NOTES: +! (1 ) Use F90 syntax for declarations, etc. (bmy, 4/14/99) +! (2 ) Now test with N instead of NN. N is the emission species, and can +! be equal to zero, which denotes that the species is not emitted. +! This is necessary now, since IDEOX always = 0, but IDTOX is always +! nonzero. (bmy, 4/19/99) +! (3 ) Commented out special cases via ICASE. Also made a few cosmetic +! changes and updated comments. (bmy, 1/2/01) +! (4 ) Remove old obsolete commented-out code (bmy, 4/20/01) +! (5 ) Now references "tracerid_mod.f" (bmy, 11/6/02) +! (6 ) Now references LFFNOX from "logical_mod.f" (bmy, 7/20/04) +! (7 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (8 ) Modified to add weekday/weekend scaling to aromatics, +! C2H4, C2H2 (tmf, 1/7/09) +!****************************************************************************** +! + ! References to F90 modules + USE TRACERID_MOD, ONLY : IDTALK4, IDTC3H8, IDTISOP, IDTCO + USE TRACERID_MOD, ONLY : IDTNOX, IDTOX, IDTPRPE + USE TRACERID_MOD, ONLY : IDTMEK, IDTC2H2, IDTC2H4, IDTACET + USE TRACERID_MOD, ONLY : IDTBENZ, IDTTOLU, IDTXYLE, IDTC2H6 + + IMPLICIT NONE + +# include "CMN_SIZE" +# include "CMN_O3" +# include "comode.h" + + ! Arguments + INTEGER, INTENT(IN) :: I, J, N, NN, IREF, JREF, JSCEN + REAL*8, INTENT(INOUT) :: XEMISR, XEMISRN(NOXLEVELS) + + ! Local Variables + INTEGER :: LL + REAL*8 :: SFAC89, PCRE +! +!***************************************************************************** +! EMF_SCALE begins here! +! +! Define PCRE, PCUE, PCPE scale factors +!***************************************************************************** +! + PCRE = .64d0 +! +!***************************************************************************** +! Save original values in temp variables so that they can be restored later +! Use the appropriate multi-level arrays for NOx emissions +!***************************************************************************** +! + IF ( NN == IDTNOX ) THEN + XEMISRN(1:NOXLEVELS) = EMISRN(IREF,JREF,1:NOXLEVELS) + ELSE + XEMISR = EMISR(IREF,JREF,N) + ENDIF +! +!***************************************************************************** +! Scale emissions by weekend/weekday: +! Saturday: JSCEN = 1; Sunday JSCEN=2; Weekday: JSCEN = 3 +!***************************************************************************** +! + ! NOx weekday/weekend emissions: Use SCNR89(1,JSCEN) as scale factor + IF ( NN == IDTNOX ) THEN + SFAC89 = SCNR89(1,JSCEN) + + EMISRN(IREF,JREF,1:NOXLEVELS) = + & EMISRN(IREF,JREF,1:NOXLEVELS) * SFAC89 + + ! Ox weekday/weekend emissions: Use SCNR89(1,JSCEN) as scale factor + ! CO weekday/weekend emissions: Use SCNR89(2,JSCEN) as scale factor + ! HC weekday/weekend emissions: Use SCNR89(3,JSCEN) as scale factor + ! Otherwise: Use 1d0 as scale factor + ELSE + IF ( NN == IDTOX ) THEN + SFAC89 = SCNR89(1,JSCEN) + + ELSE IF ( NN == IDTCO ) THEN + SFAC89 = SCNR89(2,JSCEN) + + ELSE IF ( NN == IDTALK4 .or. NN == IDTC2H2 .or. + & NN == IDTPRPE .or. NN == IDTC2H4 .or. + & NN == IDTC3H8 .or. NN == IDTTOLU .or. + & NN == IDTXYLE ) THEN + SFAC89 = SCNR89(3,JSCEN) + + ELSE + SFAC89 = 1d0 + + ENDIF + + EMISR(IREF,JREF,N) = EMISR(IREF,JREF,N) * SFAC89 + ENDIF + + ! Return to calling program + END SUBROUTINE EMF_SCALE + + + + + + diff --git a/code/emfossil.f b/code/emfossil.f new file mode 100644 index 0000000..430ef4b --- /dev/null +++ b/code/emfossil.f @@ -0,0 +1,1208 @@ +! $Id: emfossil.f,v 1.3 2011/02/23 00:08:47 daven Exp $ + SUBROUTINE EMFOSSIL( I, J, N, NN, IREF, JREF, JSCEN ) +! +!****************************************************************************** +! Subroutine EMFOSSIL emits fossil fuels into the EMISRR and EMISRRN +! arrays, which are then passed to SMVGEAR. (bmy, 4/19/99, 2/14/08) +! +! Arguments as input: +! ============================================================================ +! (1-2) I, J : longitude and latitude indices +! (3-4) N, NN : Emission index and tracer index +! (5-6) IREF, JREF : Offset indices I+I0 and J+J0 +! (7 ) JSCEN : Day index (Sat=1, Sun=2, Weekday=3) +! +! NOTES: +! (1 ) Uses the correct seasonal NOx and multi-level NOx (anthroems.f) +! (2 ) Uses anthro scale factors for years since 1985 (from anthroems.f) +! (3 ) Scales emissions based on weekday/weekend (emf_scale.f) +! (4 ) Preserves old sensitivity study cases (emf_scale.f, emissdr.f) +! (5 ) Scales emissions based on time of day (emfossil.f) +! (6 ) Get rid of all GISS and PLUMES code (bmy, 4/19/99) +! (7 ) Now use F90 syntax for declarations, etc. (bmy, 4/19/99) +! (8 ) Now use allocatable arrays for ND29 and ND36 diagnostics. +! Also made minor cosmetic changes & updated comments. (bmy, 3/16/00) +! (9 ) Eliminate obsolete code and ND63 diagnostic (bmy, 4/12/00) +! (10) Enhance anthropogenic CO emission by 8%, to account for CO production +! from oxidation of anthropogenic VOC's (bnd, bmy, 1/2/01) +! (11) Comment out scaling by 1.08 for anthro CO (bmy, 2/12/01) +! (12) Eliminate obsolete commented-out code (bmy, 4/20/01) +! (13) Now use 2% as the enhancment factor for CO instead of 1.08, +! according to new jal numbers (bmy, 4/26/01) +! (14) Now references "tracerid_mod.f" (bmy, 11/6/02) +! (15) Now replaced DXYP(JREF)*1d4 with GET_AREA_CM2(J). Now use function +! GET_TS_EMIS() from "time_mod.f" (bmy, 2/11/03) +! (16) Now can overwrite existing emissions with EPA/NEI data over the +! continental USA if LNEI99=T. Now reference LNEI99 from F90 +! module "logical_mod.f". Now reference GET_EPA_ANTHRO and +! GET_USA_MASK from "epa_nei_mod.f". (rch, rjp, bmy, 11/5/04) +! (17) Now references GET_DAY_OF_WEEK from "time_mod.f" to correctly figure +! out if this is a weekday or weekend. (bmy, 7/6/05) +! (18) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (19) Now references XNUMOL from "tracer_mod.f" (bmy, 10/25/05) +! (20) Now apply EMEP European emissions if necessary. Remove reference +! to CMN, it's now obsolete. (bdf, bmy, 11/1/05) +! (21) Rewrite IF statements to avoid seg fault errors when LEMEP and LNEI99 +! are turned off. (bmy, 2/1/06) +! (22) Now apply BRAVO Mexican emissions if necessary (rjp, kfb, bmy, 6/26/06) +! (23) Now apply EDGAR emissions if necessary. Also now only do the the +! EDGAR, EPA, EMEP, and BRAVO function calls in the LL=1 block. +! (avd, bmy, 7/10/06) +! (24) Now do BRAVO emissions before EPA/NEI99 emissions in order to avoid +! zero emissions in some boxes. Now add David Streets emissions for +! NOx over SE Asia and CO over just China (yxw, bmy, 8/17/06) +! (25) Bug fix: Now only execute EDGAR CO block if the tracer is CO. +! Also, David Streets' CO is now applied over SE ASIA. (bmy, 9/8/06) +! (26) Now references ITS_A_TAGCO_SIM from "tracer_mod.f". Enhance CO prod +! by 18.5% for tagged CO sim here instead of in "tagged_co_mod.f". +! (bmy, 2/14/08) +! (27) Use more robust test to only screen out "missing" values in EMEP, +! BRAVO, and David Streets emissions. (avd, phs, bmy, 11/19/08) +! (28) Ship NOx is emitted as HNO3+10*O3 (phs, 3/4/08) +! (29) Apply spatially-varying diurnal scalars for NOx (amv, 08/24/07) +! (30) Now apply CAC Canadian emissions if necessary (amv, 01/09/08) +! (31) Moved down BRAVO parts and add BRAVO and EPA emissions where they +! overlap (phs, 5/7/08) +! (32) Now overwrite USA NOx with VISTAS if necessary (amv, 12/02/08) +! (33) Modified CO scaling (jaf, 2/25/09) +! (34) Add a test on existing emissions for EPA/NEI. (hotp, ccc, 5/29/09) +! (35) Updated ship treatment (phs, 7/0/09) +! (36) Add NEI2005 (amv, phs, 10/20/09) +! (37) Bug fix for tagged CO and 0.5 x 0.666 Nested Grid (yxw, bmy, 11/23/09) +! (38) Bug fix for array EMISRR, if emissions are already present in this +! array (e.g. ship O3 or HNO3) they no longer get overwritten. +! (gvinken, 11/16/10) + +!****************************************************************************** +! + ! References to F90 modules + USE BRAVO_MOD, ONLY : GET_BRAVO_ANTHRO, GET_BRAVO_MASK + USE CAC_ANTHRO_MOD, ONLY : GET_CANADA_MASK, GET_CAC_ANTHRO + USE DAO_MOD, ONLY : IS_WATER + USE DIAG_MOD, ONLY : AD29, AD32_an, AD36 + USE DIAG_MOD, ONLY : EMISS_ANTHR + USE EDGAR_MOD, ONLY : GET_EDGAR_CO, GET_EDGAR_NOx + USE EDGAR_MOD, ONLY : GET_EDGAR_TODN + USE EMEP_MOD, ONLY : GET_EMEP_ANTHRO, GET_EUROPE_MASK + USE EPA_NEI_MOD, ONLY : GET_EPA_ANTHRO, GET_USA_MASK + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE LOGICAL_MOD, ONLY : LBRAVO, LEMEP, LNEI99 + USE LOGICAL_MOD, ONLY : LEDGARNOx, LEDGARCO + USE LOGICAL_MOD, ONLY : LSTREETS, LCAC + USE LOGICAL_MOD, ONLY : LEDGARSHIP, LARCSHIP + USE LOGICAL_MOD, ONLY : LEMEPSHIP, LVISTAS + USE LOGICAL_MOD, ONLY : LICARTT, LNEI05 + USE LOGICAL_MOD, ONLY : LRETRO + USE LOGICAL_MOD, ONLY : LRCP, LRCPSHIP + USE RETRO_MOD, ONLY : GET_RETRO_ANTHRO + USE RCP_MOD, ONLY : GET_RCP_EMISSION + USE C2H6_MOD, ONLY : GET_C2H6_ANTHRO + USE LOGICAL_MOD, ONLY : LNEI08 + USE DIAG49_MOD, ONLY : DO_SAVE_DIAG49 + USE NEI2005_ANTHRO_MOD, ONLY : GET_NEI2005_ANTHRO + USE NEI2008_ANTHRO_MOD, ONLY : GET_NEI2008_ANTHRO + USE NEI2005_ANTHRO_MOD, ONLY : NEI05_MASK => USA_MASK + USE NEI2008_ANTHRO_MOD, ONLY : NEI08_MASK => USA_MASK + USE LOGICAL_MOD, ONLY : LICOADSSHIP !(cklee, 6/30/09) + USE STREETS_ANTHRO_MOD, ONLY : GET_SE_ASIA_MASK + USE STREETS_ANTHRO_MOD, ONLY : GET_STREETS_ANTHRO + USE TIME_MOD, ONLY : GET_TS_EMIS, GET_DAY_OF_WEEK + USE TIME_MOD, ONLY : GET_HOUR + USE TRACER_MOD, ONLY : ITS_A_TAGCO_SIM + USE TRACER_MOD, ONLY : XNUMOL + USE TRACERID_MOD, ONLY : IDENOX, IDEOX, IDEHNO3 + USE TRACERID_MOD, ONLY : IDTOX, IDTCO, IDTHNO3 + USE TRACERID_MOD, ONLY : IDECO, IDTNO + USE VISTAS_ANTHRO_MOD, ONLY : GET_VISTAS_ANTHRO + USE ICOADS_SHIP_MOD, ONLY : GET_ICOADS_SHIP !(cklee, 7/09/09) + USE TRACERID_MOD, ONLY : IDTC2H6, IDTNOX, IDTNO2 + USE LOGICAL_MOD, ONLY : LHTAP + USE HTAP_MOD, ONLY : GET_HTAP + + ! 10/24/12, ckeller: NOX diurnal scale factors fix + USE TIME_MOD, ONLY : GET_LOCALTIME, GET_DAY_OF_WEEK_LT + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! Diagnostic switches & arrays +# include "CMN_O3" ! EMISR, EMISRR, etc... +# include "comode.h" ! IHOUR + + ! Arguments + INTEGER, INTENT(IN) :: I, J, N, NN, IREF, JREF, JSCEN + + ! Local Variables & external functions + LOGICAL :: WEEKDAY + + INTEGER :: L, LL, K, DOW, DOW_LT, HOUR, HOURNEI + REAL*8 :: TODX, DTSRCE, AREA_CM2 + REAL*8 :: EMX(NOXLEVELS) + REAL*8 :: XEMISR + REAL*8 :: XEMISRN(NOXLEVELS) + REAL*8 :: BRAVO, EPA_NEI, EMEP, EDGAR, STREETS + REAL*8 :: CAC, SHIP, VISTAS, NEI05, NEI08 + REAL*8 :: RETRO, RCP + REAL*8 :: C2H6_ANTHRO + REAL*8 :: HTAP + ! 10/24/12, ckeller: NOX diurnal scale factors fix: + INTEGER :: NOXHOUR + + !================================================================= + ! EMFOSSIL begins here! + !================================================================= + + ! Emission timestep [s] + DTSRCE = GET_TS_EMIS() * 60d0 + + ! Surface area of grid box + AREA_CM2 = GET_AREA_CM2( J ) + + ! GMT hour of day + HOUR = GET_HOUR() + + ! GMT hour of day + HOURNEI = GET_HOUR() + 1 ! to go from 1-24 (krt, 5/26/13) + + ! Determine if we should use weekday or weekend NEI + ! emissions at grid box (I,J,L). Since NEI is over + ! the US, then weekend is Sat/Sun. + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + + !================================================================= + ! Call EMF_SCALE to do the following: + ! (1) Save original values of EMISR, EMISRN + ! (2) If LFFNOX=F, turn off NOx, Ox emissions + ! (3) Scale emissions to weekend/weekday usage + !================================================================= + CALL EMF_SCALE( I, J, N, NN, IREF, JREF, JSCEN, XEMISR, XEMISRN ) + + !================================================================= + ! ADD ANTHROPOGENIC EMISSIONS TO TRACER TOTALS + ! NOTE APPROPRIATE TIME-OF-DAY FACTOR (TOD) MUST BE + ! ESTABLISHED FOR EACH TRACER; + ! WITH IHOUR = 1-6 (1 = 10pm-2am) + ! and tracer index distinguishing NOx-HC- BIO + ! + ! NOx only: account for all NOx levels (LL=1,NOXLEVELS) + !================================================================= + IF ( N == IDENOX ) THEN + + ! Initialize work variables + EMX(:) = 0d0 + + ! 10/24/12, ckeller: fix for EDGAR diurnal scale factors: + NOXHOUR = MIN( 23, NINT( GET_LOCALTIME ( I ) ) ) + TODX = GET_EDGAR_TODN(I,J,NOXHOUR) + + ! Use spatially varying diurnal scale factors + ! from EDGAR (amv, phs, 3/10/08) +! TODX = GET_EDGAR_TODN(I,J,HOUR) + + + ! Loop over all of the emission levels for NOx (e.g. surface, 100m) + DO LL = 1, NOXLEVELS + EMX(LL) = TODX * EMISRN(IREF,JREF,LL) + + !----------------------------------------------------------- + ! Get NOx from the EDGAR or RCP inventory (global) + !----------------------------------------------------------- + + ! If we are using EDGAR emissions + IF ( LEDGARNOx ) THEN + + ! Put all emissions into 1st level + IF ( LL == 1 ) THEN + + ! Get EDGAR emissions for NOx [molec/cm2/s] + EDGAR = GET_EDGAR_NOx( I, J, MOLEC_CM2_S=.TRUE. ) + + ! Apply EDGAR time-of-day factor + EDGAR = EDGAR * TODX + + ! Replace GEIA with EPA/NEI emissions at surface + EMX(LL) = EDGAR * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + + ! Zero EDGAR emissions in the 2nd level + EMX(LL) = 0d0 + + ENDIF + + ! If we are using RCP emissions (cdh, 10/14/11) + ELSEIF ( LRCP ) THEN + + ! Put all emissions into 1st level + IF ( LL == 1 ) THEN + + ! Get RCP emissions for NOx [molec/cm2/s] + RCP = GET_RCP_EMISSION( I, J, NN, + & LAND=.TRUE., SHIP=.FALSE. ) + + ! Apply EDGAR time-of-day factor + RCP = RCP * TODX + + ! Replace GEIA with RCP emissions at surface + EMX(LL) = RCP * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + + ! Zero RCP emissions in the 2nd level + EMX(LL) = 0d0 + + ENDIF + ENDIF + + !----------------------------------------------------------- + ! Get NOx from EMEP inventory over Europe + !----------------------------------------------------------- + + ! If we are using EMEP ... + IF ( LEMEP ) THEN + + ! If we are over the European region ... + IF ( GET_EUROPE_MASK( I, J ) > 0d0 ) THEN + + IF ( LL == 1 ) THEN + + ! Get EMEP emissions for NOx + EMEP = GET_EMEP_ANTHRO( I, J, NN, KG_S=.FALSE. ) + + ! Apply time-of-day factor + EMEP = EMEP * TODX + + ! Replace GEIA with EMEP emissions at surface + EMX(LL) = EMEP * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + + ! Zero GEIA emissions in the 2nd level + ! where the EMEP emissions are nonzero + EMX(LL) = 0d0 + + ENDIF + + ENDIF + ENDIF + + !----------------------------------------------------------- + ! Get NOx from EPA/NEI or VISTAS inventory over the USA + !----------------------------------------------------------- + + ! If we are using EPA/NEI emissions + IF ( LNEI99 ) THEN + + ! If we are over the USA ... + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + + IF ( LL == 1 ) THEN + + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + + ! Get EPA emissions for NOx + EPA_NEI = GET_EPA_ANTHRO( I, J, NN, WEEKDAY ) + + ! Apply time-of-day factor + EPA_NEI = EPA_NEI * TODX + + ! Replace GEIA with EPA/NEI emissions at surface + EMX(LL) = EPA_NEI * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + + ! Zero GEIA emissions in the 2nd level + ! where the EPA/NEI emissions are nonzero + EMX(LL) = 0d0 + + ENDIF + ENDIF + + ENDIF + + IF ( LVISTAS ) THEN + + + ! If we are over the USA ... + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + + IF ( LL == 1 ) THEN + + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + + ! Get VISTAS emissions for NOx + VISTAS = GET_VISTAS_ANTHRO( I, J, NN, WEEKDAY ) + + ! Apply time-of-day factor + VISTAS = VISTAS * TODX + + ! Replace with VISTAS emissions at surface + EMX(LL) = VISTAS * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + + EMX(LL) = 0d0 + + ENDIF + ENDIF + + ENDIF + + !----------------------------------------------------------- + ! Get NOx from the David Streets' inventory (SE Asia) + !----------------------------------------------------------- + + ! If we are using David Streets' emissions + IF ( LSTREETS ) THEN + + ! If we are over the SE Asia region + IF ( GET_SE_ASIA_MASK( I, J ) > 0d0 ) THEN + + ! Put all emissions into 1st level + IF ( LL == 1 ) THEN + + ! Get David Streets' emissions for NOx [molec/cm2/s] + STREETS = GET_STREETS_ANTHRO( I, J, NN, + & MOLEC_CM2_S=.TRUE. ) + + ! Apply time-of-day factor + STREETS = STREETS * TODX + + ! Replace base emissions with STREETS + EMX(LL) = STREETS * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + + ! Zero EDGAR emissions in the 2nd level + EMX(LL) = 0d0 + + ENDIF + ENDIF + ENDIF + + !----------------------------------------------------------- + ! Get NOx from BRAVO inventory over MEXICO + !----------------------------------------------------------- + + ! If we are using BRAVO ... + IF ( LBRAVO ) THEN + + ! If we are over the Mexican region ... + IF ( GET_BRAVO_MASK( I, J ) > 0d0 ) THEN + + IF ( LL == 1 ) THEN + + ! Get BRAVO emissions for NOx + ! (and apply time-of-day factor) + BRAVO = GET_BRAVO_ANTHRO( I, J, NN ) * TODX + + ! Replace GEIA with BRAVO emissions at surface + ! Now, if on border, add to NEI99 emissions (phs, 5/7/08) + IF ( LNEI99 ) THEN + + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + + IF ( IDTNOX .ne. 0 ) THEN + EMX(LL) = EMX(LL) + BRAVO * ( DTSRCE * + & AREA_CM2 ) / XNUMOL(IDTNOX) + ELSE + EMX(LL) = EMX(LL) + BRAVO * ( DTSRCE * + & AREA_CM2 ) / XNUMOL(IDTNO2) + ENDIF + + ENDIF + + ELSE + + IF ( IDTNOX .ne. 0 ) THEN + EMX(LL) = BRAVO * ( DTSRCE*AREA_CM2 ) / + & XNUMOL(IDTNOX) + ELSE + EMX(LL) = BRAVO * ( DTSRCE*AREA_CM2 ) / + & XNUMOL(IDTNO2) + ENDIF + + ENDIF + + ELSE + + ! Zero GEIA emissions in the 2nd level + ! where the BRAVO emissions are nonzero + EMX(LL) = 0d0 + + ENDIF + ENDIF + ENDIF + + !----------------------------------------------------------- + ! Get NOx from the CAC inventory (Canada) + !----------------------------------------------------------- + + ! If we are using CAC emissions + IF ( LCAC ) THEN + + ! If we are over the SE Asia region + IF ( GET_CANADA_MASK( I, J ) > 0d0 ) THEN + + ! Put all emissions into 1st level + IF ( LL == 1 ) THEN + + ! Get CAC emissions for NOx [molec/cm2/s] + CAC = GET_CAC_ANTHRO( I, J, NN, + & MOLEC_CM2_S=.TRUE. ) + + ! Apply time-of-day factor + CAC = CAC * TODX + + IF ( LNEI99 ) THEN + + ! If on border, add to NEI99 emissions (which has + ! no Canadian component) + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + EMX(LL) = EMX(LL) + CAC * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + ELSE + EMX(LL) = CAC * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + ENDIF + ELSE + + ! Replace base emissions with CAC + EMX(LL) = CAC * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + ENDIF + + ELSE + + ! Zero CAC emissions in the 2nd level + EMX(LL) = 0d0 + + ENDIF + ENDIF + ENDIF + +![eml + IF ( LNEI05 ) THEN +!eml] + + ! If we are over the USA and CAN/MEX + IF ( NEI05_MASK( I, J ) > 0d0 ) THEN + ! Determine if we should use weekday or weekend NEI + ! emissions at grid box (I,J,L). Since NEI is over + ! the US, then weekend is Sat/Sun. + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + + ! Get EPA emissions for NOx + NEI05 = GET_NEI2005_ANTHRO( I, J, LL, NN, WEEKDAY, + & MOLEC_CM2_s = .TRUE.) + + ! Apply time-of-day factor + NEI05 = NEI05 * TODX + + ! Replace GEIA with EPA/NEI emissions at surface + ! fp bckwd compatibility + IF ( IDTNOX .ne. 0 ) THEN + EMX(LL) = NEI05 * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(IDTNOX) + ELSE + EMX(LL) = NEI05 * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(IDTNO2) + ENDIF + + ENDIF + + ENDIF + + !----------------------------------------------------------- + ! Get NOx from the NEI2008 inventory (us only) + !----------------------------------------------------------- + + IF ( LNEI08 ) THEN + ! Flag for weekday or weekend for NEI/VISTAS emissions + !WRITE(*,*) 'NEI08 xxx ',sum(NEI08_MASK) + ! If we are over the USA and CAN/MEX + IF ( NEI08_MASK( I, J ) > 0d0 ) THEN + ! Determine if we should use weekday or weekend NEI + ! emissions at grid box (I,J,L). Since NEI is over + ! the US, then weekend is Sat/Sun. + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + ! Get EPA emissions for NOx; emissions are already + ! in MOLEC_CM2_s, so set to .FALSE. + IF ( LL .le. 3 ) THEN + NEI08 = GET_NEI2008_ANTHRO( I, J, LL, HOURNEI, NN, + & WEEKDAY ) + ! Replace GEIA with EPA/NEI emissions up to level 3 + EMX(LL) = NEI08 * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + ENDIF + ENDIF + + ENDIF + + !----------------------------------------------------------- + ! Get NOx from the HTAP V2 inventory (global) + !----------------------------------------------------------- + + ! If we are using HTAP emissions + IF ( LHTAP ) THEN + + ! Put all emissions into 1st level + IF ( LL == 1 ) THEN + + ! Get HTAP emissions for NOx [kg (NO2)/m2/s ] + HTAP = GET_HTAP( I, J, IDENOX ) + + ! Apply time-of-day factor + HTAP = HTAP * TODX + + ! Replace GEIA with HTAP emissions at surface + EMX(LL) = HTAP * ( DTSRCE * AREA_CM2 * 1d-4 ) + + ELSE + + ! Zero HTAP emissions in the 2nd level + EMX(LL) = 0d0 + + ENDIF + ENDIF + +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +! Prior to 2/24/12: +! Comment this out and leave this here, in case we have to re-install it +! in the context of the Grid-Independent model (bmy, 2/24/12) +! +! !SHIP EMISSIONS NOW DONE IN CALCRATE.F (gvinken, 07/27/10) +! +! !----------------------------------------------------------- +! ! Add ship emissions emitted as HNO3 and 10*O3, +! ! i.e., ozone production efficiency (OPE)=10. +! ! See : Chen, G., et al. (2005), An investigation of the +! ! chemistry of ship emission plumes during ITCT 2002, +! ! J. Geophys. Res., 110, D10S90, doi:10.1029/2004JD005236. +! ! (djj, phs, 3/4/08) +! ! Now also process EMEP NOx ship emissions, available +! ! from 1990 with EMEP 2005 (phs, 6/08) +! ! Correctly handle LEMEPSHIP=.TRUE. (phs 7/9/09) +! !----------------------------------------------------------- +! +! +! ! DO it only once (1st level) +! IF ( LL == 1 ) THEN +! +! ! Reset +! SHIP = 0D0 +! +! ! handle global inventory first +! IF ( LEDGARSHIP ) THEN +! +! ! Get SHIP EDGAR emissions for NOx [molec/cm2/s] +! SHIP = GET_EDGAR_NOx( I, J, +! & MOLEC_CM2_S=.TRUE., SHIP=.TRUE.) +! +! ! ICOADS ship emissions (cklee,7/09/09) +! ELSE IF ( LICOADSSHIP ) THEN +! +! ! Get ICOADS emissions for NOx [molec/cm2/s] +! SHIP = GET_ICOADS_SHIP( I, J, NN, MOLEC_CM2_S=.TRUE. ) +! +! ENDIF +! +! ! Overwrite Europe +! IF ( LEMEPSHIP ) THEN +! +! IF ( GET_EUROPE_MASK( I, J ) > 0d0 ) +! +! ! Get SHIP EMEP emissions for NOx [molec/cm2/s] +! & SHIP = GET_EMEP_ANTHRO( I, J, NN, SHIP=.TRUE.) +! +! ENDIF +! +! ! Store as HNO3 and O3 +! ! Convert molec/cm2/s to molec/box/s (cdh, 10/20/2011) +! EMISRR(I,J,IDEHNO3) = SHIP * AREA_CM2 +! EMISRR(I,J,IDEOX) = 10D0 * SHIP * AREA_CM2 +! +! ! ND36 = Anthro source diagnostic...store as [molec/cm2] +! ! and convert to [molec/cm2/s] in DIAG3.F +! IF ( ND36 > 0 ) THEN +! +! AD36(I,J,IDEHNO3) = AD36(I,J,IDEHNO3) + SHIP * DTSRCE +! +! AD36(I,J,IDEOX) = AD36(I,J,IDEOX) + 10D0 * SHIP * +! & DTSRCE +! +! ENDIF +! +! ENDIF +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + !----------------------------------------------------------- + ! Store in EMISRRN array and archive diagnostics + !----------------------------------------------------------- + + ! EMISRRN [molec/box/s] is referenced by LL + EMISRRN(I,J,LL) = EMISRRN(I,J,LL) + + & ( EMX(LL) * XNUMOL(NN) / DTSRCE ) + + ! ND32 = save anthro NOx for levels L=1,NOXEXTENT [molec/cm2/s] + IF ( ND32 > 0 ) THEN + AD32_an(I,J,LL) = AD32_an(I,J,LL) + + & ( EMX(LL) * XNUMOL(NN) / ( DTSRCE * AREA_CM2 ) ) + ENDIF + + ! ND36 = save anthro emissions in [molec/cm2] + ! and then convert to [molec/cm2/s] in DIAG3.F + IF ( ND36 > 0 ) THEN + AD36(I,J,N) = AD36(I,J,N) + +! & ( EMX(LL) * XNUMOL(NN) / AREA_CM2 ) * +! & NEI08_MASK(I,J) + & ( EMX(LL) * XNUMOL(NN) / AREA_CM2 ) + ENDIF + + IF ( DO_SAVE_DIAG49 ) THEN + + IF ( LNEI05 ) EMISS_ANTHR(I,J,N) = EMISS_ANTHR(I,J,N) + + & ( EMX(LL) * XNUMOL(NN) / (DTSRCE * AREA_CM2 )) * + & NEI05_MASK(I,J) + + IF ( LNEI08 ) EMISS_ANTHR(I,J,N) = EMISS_ANTHR(I,J,N) + + & ( EMX(LL) * XNUMOL(NN) / (DTSRCE * AREA_CM2 )) * + & NEI08_MASK(I,J) + + ENDIF + ENDDO + + !================================================================= + ! All other emitted tracers except NOx! + !================================================================= + ELSE + + ! Initialize work variables + EMX(:) = 0d0 + + ! Use appropriate scale factor for time of day + IF ( N == IDEOX ) THEN + TODX = TODN(IHOUR) + ELSE + TODX = TODH(IHOUR) + ENDIF + + EMX(1) = TODX * EMISR(IREF,JREF,N) + +!--------- Prior to 2/25/09, ccc -------------------------------- +! ! Account for CO production from anthropogenic VOC's +! ! -> For Tagged CO, enhance CO production by 18.5% +! ! -> For full-chem, enhance CO production by 2% +! ! (bnd, bmy, 4/26/01; jaf, mak, bmy, 2/14/08) +! IF ( ITS_A_TAGCO_SIM() ) THEN +! IF ( NN == IDTCO ) EMX(1) = EMX(1) * 1.185d0 +! ELSE +! IF ( NN == IDTCO ) EMX(1) = EMX(1) * 1.02d0 +! ENDIF +!---------------------------------------------------------------- + + !-------------------------------------------------------------- + ! Get CO emissions from the EDGAR inventory (global) + !-------------------------------------------------------------- + + ! If we are using EDGAR CO ... + IF ( NN == IDTCO .and. LEDGARCO ) THEN + + ! Get EDGAR CO + EDGAR = GET_EDGAR_CO( I, J, MOLEC_CM2_S=.TRUE. ) + + + ! Apply time of day factor + EDGAR = EDGAR * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = EDGAR * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + + !-------------------------------------------------------------- + ! Get hydrocarbon emissions from RETRO inventory + !-------------------------------------------------------------- + + ! If we are using RETRO emissions ... + IF ( LRETRO ) THEN + + ! Get RETRO emissions + RETRO = GET_RETRO_ANTHRO( I, J, NN ) + + ! -1 indicates tracer NN does not have RETRO emissions + IF ( .not. ( RETRO < 0d0 ) ) THEN + + ! Apply time-of-day factor + RETRO = RETRO * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = RETRO * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + ENDIF + + !-------------------------------------------------------------- + ! Get C2H6 emissions from Yaping Xiao's inventory (mpayer, 3/22/12) + !-------------------------------------------------------------- + + ! If C2H6 is a defined tracer ... + IF ( NN == IDTC2H6 ) THEN + + C2H6_ANTHRO = GET_C2H6_ANTHRO( I, J, NN ) + + ! Apply time-of-day factor + C2H6_ANTHRO = C2H6_ANTHRO * TODX + + ! Convert from molC/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = C2H6_ANTHRO * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + + !-------------------------------------------------------------- + ! Get CO & hydrocarbons emissions from RCP inventory + ! (cdh, 10/14/11) + !-------------------------------------------------------------- + + IF ( LRCP ) THEN + + ! Get RCP emissions + IF (NN==IDTCO) THEN + ! Ship CO emissions are handled separately below + RCP = GET_RCP_EMISSION( I, J, NN, + & LAND=.TRUE., SHIP=.FALSE. ) + ELSE + ! Land and ship emissions for all hydrocarbons + RCP = GET_RCP_EMISSION( I, J, NN, + & LAND=.TRUE., SHIP=.TRUE. ) + ENDIF + + ! -1 means tracer NN does not have RCP emissions + IF ( RCP >= 0d0 ) THEN + + ! Apply time-of-day factor + RCP = RCP * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = RCP * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + + ENDIF + + !-------------------------------------------------------------- + ! Get CO & Hydrocarbons from EMEP inventory over Europe + !-------------------------------------------------------------- + + ! If we are using EMEP emissions ... + IF ( LEMEP ) THEN + + ! If we are over the European region ... + IF ( GET_EUROPE_MASK( I, J ) > 0d0 ) THEN + + ! Get EMEP emissions + EMEP = GET_EMEP_ANTHRO( I, J, NN ) + + ! -1 indicates tracer NN does not have EMEP emissions + IF ( .not. ( EMEP < 0d0 ) ) THEN + + ! Apply time-of-day factor + EMEP = EMEP * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = EMEP * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + ENDIF + ENDIF + + + + + !-------------------------------------------------------------- + ! Get CO & Hydrocarbons from EPA/NEI inventory over the USA + !-------------------------------------------------------------- + + ! If we are using EPA/NEI99 emissions ... + IF ( LNEI99 ) THEN + + ! If we are over the USA ... + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + + ! Get EPA/NEI emissions (and apply time-of-day factor) + EPA_NEI = GET_EPA_ANTHRO( I, J, NN, WEEKDAY ) + + ! hotp fix for species not present (hotp 5/28/09) + IF ( .not. ( EPA_NEI < 0d0 ) ) THEN + + EPA_NEI = EPA_NEI * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = EPA_NEI * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + + ENDIF + ENDIF + + !-------------------------------------------------------------- + ! Get CO from David Streets' inventory over Europe + !-------------------------------------------------------------- + + ! If we are using David Streets' emissions ... + IF ( LSTREETS ) THEN + + ! If we are over the China region ... + IF ( GET_SE_ASIA_MASK( I, J ) > 0d0 ) THEN + + ! Get STREETS emissions + STREETS = GET_STREETS_ANTHRO( I, J, NN, + & MOLEC_CM2_S=.TRUE. ) + + ! -1 indicates tracer NN does not have BRAVO emissions + IF ( .not. ( STREETS < 0d0 ) ) THEN + + ! Apply time-of-day factor + STREETS = STREETS * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = STREETS * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + ENDIF + ENDIF + + + !-------------------------------------------------------------- + ! Get CO from BRAVO inventory over MEXICO + !-------------------------------------------------------------- + + ! If we are using BRAVO emissions ... + IF ( LBRAVO ) THEN + + ! If we are over the Mexican region ... + IF ( GET_BRAVO_MASK( I, J ) > 0d0 ) THEN + + ! Get BRAVO emissions + BRAVO = GET_BRAVO_ANTHRO( I, J, NN ) + + ! -1 indicates tracer NN does not have BRAVO emissions + !----------------------------------------------------------- + ! Prior to 11/19/08: + ! Use more robust test to only screen out -1 values + ! and not zero values (which could be valid emissions) + ! (avd, phs, bmy, 11/19/08) + !IF ( BRAVO > 0d0 ) THEN + !----------------------------------------------------------- + IF ( .not. ( BRAVO < 0d0 ) ) THEN + + ! Apply time-of-day factor + BRAVO = BRAVO * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array. + ! Now, if on border, add to NEI99 emissions (phs, 5/7/08) + + IF ( LNEI99 ) THEN + + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + + EMX(1) = EMX(1) + + & BRAVO * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + + EMX(1) = + & BRAVO * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + + ENDIF + + ENDIF + + ENDIF + ENDIF + + !-------------------------------------------------------------- + ! Get CAC other emissions over Canada + !-------------------------------------------------------------- + + ! If we are using CAC emissions ... + IF ( LCAC ) THEN + + ! If we are over the China region ... + IF ( GET_CANADA_MASK( I, J ) > 0d0 ) THEN + + ! Get CAC emissions + CAC = GET_CAC_ANTHRO( I, J, NN, MOLEC_CM2_S=.TRUE. ) + + ! -1 indicates tracer NN does not have CAC emissions + !----------------------------------------------------------- + ! Prior to 11/19/08: + ! Use more robust test to only screen out -1 values + ! and not zero values (which could be valid emissions) + ! (avd, phs, bmy, 11/19/08) + !IF ( CAC > 0d0 ) THEN + !----------------------------------------------------------- + IF ( .not. ( CAC < 0d0 ) ) THEN + + ! Apply time-of-day factor + CAC = CAC * TODX + + IF ( LNEI99 ) THEN + ! If on border, add to NEI99 emissions (which contain + ! no Canadian component) + + IF ( GET_USA_MASK( I, J ) > 0d0 ) THEN + EMX(1) = EMX(1) + CAC * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ELSE + EMX(1) = CAC * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + ELSE + + ! Else replace base emissions with CAC + EMX(1) = CAC * + & ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + ENDIF + + ENDIF + ENDIF + ENDIF + + ! If we are using EPA/NEI2005 emissions ... + IF ( LNEI05 ) THEN + + ! If we are over the USA ... + IF ( NEI05_MASK( I, J ) > 0d0 ) THEN + + NEI05 = 0D0 + + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + + ! Loop over all of the emission levels + ! For now lump levels together (phs, 10/20/09) + DO LL = 1, NOXLEVELS + + ! Get EPA/NEI emissions + EPA_NEI = GET_NEI2005_ANTHRO( I, J, LL, NN, + & WEEKDAY, MOLEC_CM2_S=.TRUE. ) + + ! -1 indicates tracer NN does not have EPA/NEI emissions + IF ( EPA_NEI < 0d0 ) EXIT + + NEI05 = NEI05 + EPA_NEI + + ENDDO + + + IF ( EPA_NEI > -1d0 ) THEN + + ! Apply time-of-day factor + NEI05 = NEI05 * TODX + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = NEI05 * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + ENDIF + ENDIF + ENDIF + + IF ( LNEI08 ) THEN + + ! If we are over the USA ... + IF ( NEI08_MASK( I, J ) > 0d0 ) THEN + ! Flag for weekday or weekend for NEI/VISTAS emissions + + ! Determine if we should use weekday or weekend NEI + ! emissions at grid box (I,J,L). Since NEI is over + ! the US, then weekend is Sat/Sun. + DOW_LT = GET_DAY_OF_WEEK_LT( I, J, 1 ) + WEEKDAY = ( DOW_LT > 0 .and. DOW_LT < 6 ) + + ! Loop over all of the emission levels + ! For now lump levels together (phs, 10/20/09) + DO LL = 1, NOXLEVELS + IF ( LL .le. 3 ) THEN !NEI08 has 3 levels + ! Get EPA/NEI emissions + NEI08 = GET_NEI2008_ANTHRO( I, J, LL,HOURNEI,NN, + & WEEKDAY ) + + ! -1 indicates tracer NN does not have EPA/NEI emissions + IF ( NEI08 < 0d0 ) EXIT + + ! Convert from molec/cm2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + IF ( EPA_NEI > -1d0 ) THEN + EMX(LL) = NEI08 * ( DTSRCE * AREA_CM2 ) + & / XNUMOL(NN) + ENDIF + ENDIF + ENDDO + ENDIF + ENDIF + + !-------------------------------------------------------------- + ! Get CO emissions from the HTAP V2 inventory (global) + !-------------------------------------------------------------- + IF ( LHTAP ) THEN + + ! If we are using HTAP CO ... + IF ( NN == IDTCO ) THEN + + ! Get HTAP CO + HTAP = GET_HTAP( I, J, IDECO ) + + ! Apply time of day factor + HTAP = HTAP * TODX + + ! Convert from kg/m2/s to kg/box/timestep in order + ! to be in the proper units for EMISRR array + EMX(1) = HTAP * ( DTSRCE * AREA_CM2 * 1d-4 ) + + ENDIF + ENDIF + + ! Account for CO production from anthropogenic VOC's + ! -> For Tagged CO, enhance CO production by 18.5% + ! -> For full-chem, enhance CO production by 2% + ! (bnd, bmy, 4/26/01; jaf, mak, bmy, 2/14/08) + ! Scaling factor is now correctly applied after + ! calculating emissions. (jaf, ccc, 2/25/09) + ! Modifications of the scaling using Rynda GRL 2008. + ! (jaf, ccc, 2/25/09) + ! Added a nested if (phs, 7/9/09) + IF ( ITS_A_TAGCO_SIM() ) THEN + IF ( LICARTT ) THEN + IF ( GET_USA_MASK(I,J) > 0.d0 ) THEN + IF ( NN == IDTCO ) EMX(:) = EMX(:) * 1.39d0 + ELSE + IF ( NN == IDTCO ) EMX(:) = EMX(:) * 1.19d0 + ENDIF + ELSE + IF ( NN == IDTCO ) EMX(:) = EMX(:) * 1.19d0 + ENDIF + ELSE + IF ( NN == IDTCO ) EMX(:) = EMX(:) * 1.02d0 + ENDIF + + !-------------------------------------------------------------- + ! Add ship emissions for CO (phs, 7/9/09) + !-------------------------------------------------------------- + SHIP = 0D0 + + IF ( NN == IDTCO ) THEN + + ! get global inventory first + IF ( LEDGARSHIP ) THEN + + SHIP = GET_EDGAR_CO( I, J, MOLEC_CM2_S=.TRUE., + $ SHIP=.TRUE.) + + ELSE IF ( LICOADSSHIP ) THEN + + SHIP = GET_ICOADS_SHIP( I, J, NN, MOLEC_CM2_S=.TRUE. ) + + ELSE IF ( LRCPSHIP ) THEN + + SHIP = GET_RCP_EMISSION( I, J, NN, + & LAND=.FALSE., SHIP=.TRUE. ) + + ENDIF + + ! overwrite Europe + IF ( LEMEPSHIP ) THEN + IF ( GET_EUROPE_MASK( I, J ) > 1d0 ) THEN + SHIP = GET_EMEP_ANTHRO( I, J, NN, SHIP=.TRUE.) + ENDIF + ENDIF + + ! Convert to same units as EMX(1), and add + SHIP = SHIP * ( DTSRCE * AREA_CM2 ) / XNUMOL(NN) + + EMX(1) = EMX(1) + SHIP + + ENDIF + + !-------------------------------------------------------------- + ! Store in EMISRR array and archive diagnostics + !-------------------------------------------------------------- +!--- Prior to (gvinken, 11/16/10). Emissions already present in EMISRR +! no longer get overwritten. +! EMISRR(I,J,N) = EMX(1) * XNUMOL(NN) / DTSRCE +! EMISRR(I,J,N) = EMISRR(I,J,N) + EMX(1) * XNUMOL(NN) / DTSRCE + + !fp + !with NEI08 we need to loop on all levels + !for now put all emissions in surface layer (should be ok since we are treated NOx, SOx separatly) + + DO LL = 1, NOXLEVELS + EMISRR(I,J,N) = EMISRR(I,J,N) + + & EMX(LL) * XNUMOL(NN) / DTSRCE + ENDDO + + !fp + ! this need to be changed to account for injections above surface layer + ! sum all emissions + + ! ND29 = CO source diagnostic... + ! store as [molec/cm2/s] in AD29(:,:,1) + IF ( ND29 > 0 .and. NN == IDTCO ) THEN + DO LL = 1, NOXLEVELS + AD29(I,J,1) = AD29(I,J,1) + + & ( EMX(LL) * XNUMOL(NN) / ( DTSRCE * AREA_CM2 ) ) + ENDDO + ENDIF + + ! ND36 = Anthro source diagnostic...store as [molec/cm2] + ! and convert to [molec/cm2/s] in DIAG3.F + IF ( ND36 > 0 ) THEN + DO LL = 1, NOXLEVELS + AD36(I,J,N) = AD36(I,J,N) + + & ( EMX(LL) * XNUMOL(NN) / AREA_CM2 ) + ENDDO + ENDIF + IF ( DO_SAVE_DIAG49 ) THEN + DO LL = 1, NOXLEVELS + EMISS_ANTHR(I,J,N) = EMISS_ANTHR(I,J,N) + + & ( EMX(LL) * XNUMOL(NN) / (DTSRCE * AREA_CM2 )) + ENDDO + ENDIF + + ENDIF + + !================================================================= + ! Restore EMISR, EMISRN to original values + !================================================================= + IF ( N == IDENOX ) THEN + EMISRN(IREF,JREF,1:NOXLEVELS) = XEMISRN(1:NOXLEVELS) + ELSE + EMISR(IREF,JREF,N) = XEMISR + ENDIF + + ! Return to calling program + END SUBROUTINE EMFOSSIL diff --git a/code/emisop.f b/code/emisop.f new file mode 100644 index 0000000..568fdd0 --- /dev/null +++ b/code/emisop.f @@ -0,0 +1,147 @@ +C $Id: emisop.f,v 1.2 2009/10/26 18:54:15 daven Exp $ + FUNCTION EMISOP( I, J, IJLOOP, SUNCOS, TMMP, XNUMOL ) +! +!****************************************************************************** +! Subroutine EMISOP_GRASS computes ISOPRENE EMISSIONS in units of +! [atoms C/box/step]. (bdf, bmy, 8/1/01, 6/16/05) +! +! Arguments as Input: +! ============================================================================ +! (1-2) I, J (INTEGER ) : 2-D grid box indices +! (3 ) IJLOOP (INTEGER ) : 1-D grid box index +! (4 ) SUNCOS (REAL*8 ) : 1-D array of cos( solar zenith angle ) +! (5 ) TMMP (REAL*8 ) : Local air temperature (K) +! (6 ) XNUMOL (REAL*8 ) : Number of atoms C / kg C +! +! Important Common Block Variables: +! ============================================================================ +! (1 ) XYLAI (CMN_VEL ) : Leaf Area Index of land type for current MONTH +! (2 ) IJREG (CMN_VEL ) : Number of Olson land types per grid box +! (3 ) IJLAND+1 (CMN_VEL ) : Olson land type index +! (4 ) IJUSE (CMN_VEL ) : Olson land type fraction per box (in mils) +! (5 ) SOPCOEFF (CMN_ISOP) : 2nd order polynomial coeffs for light correction +! (6 ) BASEISOP (CMN_ISOP) : Baseline ISOPRENE emissions [kg C/box/step] +! +! NOTES: +! (1 ) Now force double precision with DBLE and "D" exponents. Also updated +! comments, made cosmetic changes (bmy, 4/4/03) +! (2 ) Now pass I, J via the arg list. Now reference CLDFRC directly from +! "dao_mod.f" instead of referencing CFRAC from "CMN_DEP". Now +! remove reference to CMN_DEP. (bmy, 12/9/03) +! (3 ) Now scale ISOP emissions to 400 Tg C/yr for GEOS-4 (bmy, 3/5/04) +! (4 ) Now force ISOP totals to be the same for GEOS-3 and GEOS-4 met fields +! for the year 2001. This will facilitate cross-model intercomparison. +! (jal, bmy, 3/15/05) +! (5 ) Bug fix: replace #else with #elif (swu, bmy, 6/16/05) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : CLDFRC + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_VEL" ! IJREG, IJLAND, IJUSE +# include "CMN_ISOP" ! SOPCOEFF, BASEISOP + + ! Arguments + INTEGER, INTENT(IN) :: IJLOOP, I, J + REAL*8, INTENT(IN) :: SUNCOS(MAXIJ), TMMP, XNUMOL + + ! Local variables + INTEGER :: INVEG + REAL*8 :: TLAI, EMBIO, CLIGHT + + ! External functions + REAL*8, EXTERNAL :: XLTMMP, BIOFIT, TCORR + + ! Function value + REAL*8 :: EMISOP + + !================================================================= + ! EMISOP begins here! + !================================================================= + + ! Initialize + EMISOP = 0.d0 + TLAI = 0.d0 + + ! Compute total of Leaf Area Index * baseline isoprene + ! over all Olson land types that are in this grid box + DO INVEG = 1, IJREG(IJLOOP) + TLAI = TLAI + XYLAI(IJLOOP,INVEG) * BASEISOP(IJLOOP,INVEG) + ENDDO + + !================================================================= + ! Apply light & temperature corrections to baseline emissions -- + ! only if it is daytime and if there is nonzero isoprene emission + ! (e.g. XYLAI * BASEISOP > 0 ) + !================================================================= + IF ( ( SUNCOS(IJLOOP) > 0d0 ) .AND. ( TLAI > 0d0 ) ) THEN + + ! Initialize + EMBIO = 0d0 + + ! Loop over each Olson land type in this grid box + DO INVEG = 1, IJREG(IJLOOP) + + ! If the product of leaf area index and baseline ISOP > 0 ... + IF ( XYLAI(IJLOOP,INVEG) * + & BASEISOP(IJLOOP,INVEG) > 0d0 ) THEN + + ! Compute light correction -- polynomial fit + CLIGHT = BIOFIT( SOPCOEFF, XYLAI(IJLOOP,INVEG), + & SUNCOS(IJLOOP), CLDFRC(I,J) ) + + ! Apply light correction to baseline ISOPRENE emissions. + ! Also multiply by the fraction of the grid box occupied + ! by this Olson landtype. Units are [kg C/box/step]. + ! BASEISOP emission rate is set in setbase.f + + EMBIO = EMBIO + + & ( BASEISOP(IJLOOP,INVEG) * CLIGHT * + & DBLE( IJUSE(IJLOOP,INVEG) ) ) / 1000.d0 + ENDIF + ENDDO + + ! Apply the temperature correction from Gunther et al 92 to the + ! ISOPRENE emissions. Units are still [kg C/box/step]. + IF ( TMMP > 273d0 ) THEN + EMISOP = TCORR(TMMP) * EMBIO + ELSE + EMISOP = 0d0 + ENDIF + ENDIF + + !================================================================= + ! EMISOP is the amount of ISOP emitted in [kg/box/step]. + ! Convert to [atoms C/box/step] and return. + !================================================================= + EMISOP = EMISOP * XNUMOL + +#if defined( GEOS_3 ) + + ! GEOS-3 meteorology results in 579 Tg C/yr from ISOP. Scale + ! this down to 400 Tg C/yr, which is what we get from GEOS-STRAT + ! (mje, djj, bmy, 8/26/02) + ! + ! NOTE: This actually produces more like 341 Tg for 2001 GEOS-3 + ! met fields, but that is OK (jal, bmy, 3/15/05) + EMISOP = EMISOP * ( 400d0 / 579d0 ) + +#elif defined( GEOS_4 ) + + ! Original GEOS-4 scaling produced 443 Tg C/yr w/ 2003 "V3" met + ! fields. However we have since switched to GEOS-4 "V4" met fields + ! and need to rescale the ISOP total. A recent run with GEOS-4 "V4" + ! met fields for 2001 produced 443 Tg C/yr. We need to force the + ! total to be the same as for GEOS-3, for comparison purposes. + ! Therefore apply a second scale factor so that we get 341 Tg C/yr + ! of ISOP for GEOS-4 "V4" met fields for 2001. (bmy, 3/15/05) + EMISOP = EMISOP * ( 400d0 / 443d0 ) + EMISOP = EMISOP * ( 341.2376d0 / 442.7354d0 ) + +#endif + + ! Return to calling program + END FUNCTION EMISOP diff --git a/code/emisop_grass.f b/code/emisop_grass.f new file mode 100644 index 0000000..0734356 --- /dev/null +++ b/code/emisop_grass.f @@ -0,0 +1,159 @@ +! $Id: emisop_grass.f,v 1.1 2009/06/09 21:51:50 daven Exp $ + FUNCTION EMISOP_GRASS( I, J, IJLOOP, SUNCOS, TMMP, XNUMOL ) +! +!****************************************************************************** +! Subroutine EMISOP_GRASS computes the ISOPRENE EMISSIONS FROM GRASSLANDS +! in units of [atoms C/box/step]. (bdf, bmy, 8/1/01, 6/16/05) +! +! Arguments as Input: +! ============================================================================ +! (1-2) I, J (INTEGER ) : 2-D grid box indices +! (3 ) IJLOOP (INTEGER ) : 1-D grid box index +! (4 ) SUNCOS (REAL*8 ) : 1-D array of cos( solar zenith angle ) +! (5 ) TMMP (REAL*8 ) : Local air temperature (K) +! (6 ) XNUMOL (REAL*8 ) : Number of atoms C / kg C +! +! Important Common Block Variables: +! ============================================================================ +! (1 ) XYLAI (CMN_VEL ) : Leaf Area Index of land type for current MONTH +! (2 ) IJREG (CMN_VEL ) : Number of Olson land types per grid box +! (3 ) IJLAND+1 (CMN_VEL ) : Olson land type index +! (4 ) IJUSE (CMN_VEL ) : Olson land type fraction per box (in mils) +! (5 ) SOPCOEFF (CMN_ISOP) : 2nd order polynomial coeffs for light correction +! (6 ) BASEISOP (CMN_ISOP) : Baseline ISOPRENE emissions [kg C/box/step] +! (7 ) BASEGRASS (CMN_ISOP) : Baseline GRASS ISOP emissions [kg C/box/step] +! +! NOTES: +! (1 ) GEOS-3 meteorology results in 579 Tg C/yr from biogenic ISOP. Compute +! ISOP from grasslands based on 400 Tg C/yr from biogenic ISOP, which +! is what we get from GEOS-STRAT. (mje, bdf, djj, 9/10/02) +! (2 ) Now pass I, J via the arg list. Now reference CLDFRC directly from +! "dao_mod.f" instead of referencing CFRAC from "CMN_DEP". Now +! remove reference to CMN_DEP. (bmy, 12/9/03) +! (3 ) Now scale ISOP emissions to 400 Tg C/yr for GEOS-4 (bmy, 3/5/04) +! (4 ) Now force ISOP totals to be the same for GEOS-3 and GEOS-4 met fields +! for the year 2001. This will facilitate cross-model intercomparison. +! (jal, bmy, 3/15/05) +! (5 ) Bug fix: change #else to #elif (swu, bmy, 6/16/05) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : CLDFRC + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_VEL" ! IJREG, IJLAND, IJUSE +# include "CMN_ISOP" ! SOPCOEFF, BASEISOP, BASEGRASS + + ! Arguments + INTEGER, INTENT(IN) :: IJLOOP, I, J + REAL*8, INTENT(IN) :: SUNCOS(MAXIJ), TMMP, XNUMOL + + ! Local variables + INTEGER :: INVEG, GRASS_SCALE + REAL*8 :: EMBIO, TLAI, CLIGHT, EMISOP_GRASS + + ! External functions + REAL*8, EXTERNAL :: BIOFIT, TCORR + + !================================================================= + ! EMISOP_GRASS begins here! + !================================================================= + + ! Initialize + EMISOP_GRASS = 0d0 + TLAI = 0d0 + + ! Compute total of Leaf Area Index * baseline isoprene + ! over all Olson land types that are in this grid box + DO INVEG = 1, IJREG(IJLOOP) + TLAI = TLAI + XYLAI(IJLOOP,INVEG) * BASEISOP(IJLOOP,INVEG) + ENDDO + + !================================================================= + ! Apply light & temperature corrections to baseline emissions -- + ! only if it is daytime and if there is nonzero isoprene emission + ! (e.g. XYLAI * BASEISOP > 0 ) + !================================================================= + IF ( ( SUNCOS(IJLOOP) > 0d0 ) .AND. ( TLAI > 0d0 ) ) THEN + + ! Initialize + EMBIO = 0d0 + + ! Loop over each Olson land type in this grid box + DO INVEG = 1, IJREG(IJLOOP) + + ! IJLAND+1 is the Olson Land type index + ! 2: urban 42: shrub/grass 45: shrub/grass + ! 32: agriculture 43: shrub/grass 53: desert + ! 41: shrub/grass 44: shrub/grass 54: desert + SELECT CASE ( IJLAND(IJLOOP,INVEG) + 1 ) + + CASE( 2, 32, 41, 42, 43, 44, 45, 53, 54 ) + GRASS_SCALE = 6.17 !what is this scale ????? + + CASE DEFAULT + GRASS_SCALE = 0d0 + + END SELECT + + ! If the product of leaf area index and baseline ISOP > 0 ... + IF ( XYLAI(IJLOOP,INVEG) * + & BASEISOP(IJLOOP,INVEG) > 0d0 ) THEN + + ! Compute light correction -- polynomial fit + CLIGHT = BIOFIT( SOPCOEFF, XYLAI(IJLOOP,INVEG), + & SUNCOS(IJLOOP), CLDFRC(I,J) ) + + ! Apply light correction to baseline GRASS emissions. + ! Also multiply by the fraction of the grid box occupied + ! by this Olson landtype. Units are [kg C/box/step]. + ! BASEGRASS emission rate is set in setbase.f + EMBIO = EMBIO + + & ( BASEGRASS(IJLOOP) * GRASS_SCALE * CLIGHT * + & DBLE( IJUSE(IJLOOP,INVEG) ) ) / 1000d0 + ENDIF + ENDDO + + ! Apply the temperature correction from Gunther et al 92 to the + ! GRASSLAND ISOPRENE emissions. Units are still [kg C/box/step]. + IF ( TMMP > 273d0 ) THEN + EMISOP_GRASS = TCORR(TMMP) * EMBIO + ELSE + EMISOP_GRASS = 0d0 + ENDIF + ENDIF + + !================================================================= + ! EMISOP_GRASS is the amount of ISOP emitted from grasslands + ! in [kg/box/step]. Convert to [atoms C/box/step] and return. + !================================================================= + EMISOP_GRASS = EMISOP_GRASS * XNUMOL + +#if defined( GEOS_3 ) + + ! GEOS-3 meteorology results in 579 Tg C/yr from ISOP. Scale + ! this down to 400 Tg C/yr, which is what we get from GEOS-STRAT + ! (mje, djj, bmy, 8/26/02) + ! + ! NOTE: This actually produces more like 341 Tg for 2001 GEOS-3 + ! met fields, but that is OK (jal, bmy, 3/15/05) + EMISOP_GRASS = EMISOP_GRASS * ( 400d0 / 579d0 ) + +#elif defined( GEOS_4 ) + + ! Original GEOS-4 scaling produced 443 Tg C/yr w/ 2003 "V3" met + ! fields. However we have since switched to GEOS-4 "V4" met fields + ! and need to rescale the ISOP total. A recent run with GEOS-4 "V4" + ! met fields for 2001 produced 443 Tg C/yr. We need to force the + ! total to be the same as for GEOS-3, for comparison purposes. + ! Therefore apply a second scale factor so that we get 341 Tg C/yr + ! of ISOP for GEOS-4 "V4" met fields for 2001. (bmy, 3/15/05) + EMISOP_GRASS = EMISOP_GRASS * ( 400d0 / 443d0 ) + EMISOP_GRASS = EMISOP_GRASS * ( 341.2376d0 / 442.7354d0 ) + +#endif + + ! Return to calling program + END FUNCTION EMISOP_GRASS diff --git a/code/emisop_mb.f b/code/emisop_mb.f new file mode 100644 index 0000000..abb3bbf --- /dev/null +++ b/code/emisop_mb.f @@ -0,0 +1,164 @@ +! $Id: emisop_mb.f,v 1.1 2009/06/09 21:51:54 daven Exp $ + FUNCTION EMISOP_MB( I, J, IJLOOP, SUNCOS, TMMP, XNUMOL ) +! +!****************************************************************************** +! Subroutine EMISOP_MB computes METHYL BUTENOL emissions in units +! of [atoms C/box/step]. (bdf, bmy, 8/2/01, 6/16/05) +! +! Arguments as Input: +! ============================================================================ +! (1-2) I, J (INTEGER ) : 2-D grid box indices +! (1 ) IJLOOP (INTEGER) : 1-D grid box index +! (2 ) SUNCOS (REAL*8 ) : 1-D array of cos( solar zenith angle ) +! (3 ) TMMP (REAL*8 ) : Local air temperature (K) +! (4 ) XNUMOL (REAL*8 ) : Number of atoms C / kg C +! +! Important Common Block Variables: +! ============================================================================ +! (1 ) XYLAI (CMN_VEL ) : Leaf Area Index of land type for current MONTH +! (2 ) IJREG (CMN_VEL ) : Number of Olson land types per grid box +! (3 ) IJLAND+1 (CMN_VEL ) : Olson land type index +! (4 ) IJUSE (CMN_VEL ) : Olson land type fraction per box (in mils) +! (5 ) SOPCOEFF (CMN_ISOP) : 2nd order polynomial coeffs for light correction +! (6 ) BASEISOP (CMN_ISOP) : Baseline ISOPRENE emissions [kg C/box/step] +! (7 ) BASEMB (CMN_ISOP) : Baseline METHYL BUT. emissions [kg C/box/step] +! +! NOTES: +! (1 ) Now use F90 syntax. Use "D" exponents to force double precision. +! Updated comments, and mad cosmetic changes (bmy, 8/2/01) +! (2 ) Deleted obsolete, commented-out code from 8/01 (bmy, 11/27/01) +! (3 ) GEOS-3 meteorology results in 579 Tg C/yr from biogenic ISOP. Compute +! ISOP from grasslands based on 400 Tg C/yr from biogenic ISOP, which +! is what we get from GEOS-STRAT. (mje, bdf, djj, 9/10/02) +! (4 ) Now pass I, J via the arg list. Now reference CLDFRC directly from +! "dao_mod.f" instead of referencing CFRAC from "CMN_DEP". Now +! remove reference to CMN_DEP. (bmy, 12/9/03) +! (5 ) Now scale ISOP emissions to 400 Tg C/yr for GEOS-4 (bmy, 3/5/04) +! (6 ) Now force ISOP totals to be the same for GEOS-3 and GEOS-4 met fields +! for the year 2001. This will facilitate cross-model intercomparison. +! (jal, bmy, 3/15/05) +! (7 ) Bug fix: change #else to #elif (swu, bmy, 6/16/05) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : CLDFRC + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_VEL" ! IJREG, IJLAND, IJUSE +# include "CMN_ISOP" ! SOPCOEFF, BASEISOP, BASEMB + + ! Arguments + INTEGER, INTENT(IN) :: IJLOOP, I, J + REAL*8, INTENT(IN) :: SUNCOS(MAXIJ), TMMP, XNUMOL + + ! Local variables + INTEGER :: INVEG, MBO_SCALE, TEST + REAL*8 :: EMBIO, TLAI, CLIGHT, EMISOP_MB + + ! External functions + REAL*8, EXTERNAL :: BIOFIT, TCORR + + !================================================================= + ! EMISOP_MB begins here! + !================================================================= + + ! Initialize + EMISOP_MB = 0d0 + TLAI = 0d0 + + ! Compute total of Leaf Area Index * baseline isoprene + ! over all Olson land types that are in this grid box + DO INVEG = 1,IJREG(IJLOOP) + TLAI = TLAI + XYLAI(IJLOOP,INVEG) * BASEISOP(IJLOOP,INVEG) + END DO + + !================================================================= + ! Apply light & temperature corrections to baseline emissions -- + ! only if it is daytime and if there is nonzero isoprene emission + ! (e.g. XYLAI * BASEISOP > 0 ) + !================================================================= + IF ( ( SUNCOS(IJLOOP) > 0d0 ) .AND. ( TLAI > 0d0 ) ) THEN + + ! Initialize + EMBIO = 0d0 + + ! Loop over each Olson land type in this grid box + DO INVEG = 1, IJREG(IJLOOP) + + ! IJLAND+1 is the Olson land type index + ! For methyl butenol emissions the landtypes 21, 22, 23, + ! and 28 are mostly pine forests and emit MB. Landtypes + ! 24 and 25 are half pine, and emit MB at half the rate. + ! Other landtypes emit no MB. + SELECT CASE ( IJLAND(IJLOOP,INVEG) + 1 ) + CASE ( 21, 22, 23, 28 ) + MBO_SCALE = 2 + CASE ( 24, 25 ) + MBO_SCALE = 1 + CASE DEFAULT + MBO_SCALE = 0 + END SELECT + + ! If the product of leaf area index and baseline ISOP > 0 ... + IF ( XYLAI(IJLOOP,INVEG) * + & BASEISOP(IJLOOP,INVEG) > 0.0 ) THEN + + ! Compute light correction -- polynomial fit + CLIGHT = BIOFIT( SOPCOEFF, XYLAI(IJLOOP,INVEG), + & SUNCOS(IJLOOP), CLDFRC(I,J) ) + + ! Apply light correction to baseline MB emissions. + ! Also multiply by the fraction of the grid box occupied + ! by this Olson landtype. Units are [kg C/box/step]. + ! BASEMB (set in setbase.f) is computed to get Guenther's + ! North American emissions of 3.2 Tg C/yr from MB. + EMBIO = EMBIO + + & ( BASEMB(IJLOOP) * MBO_SCALE * CLIGHT * + & DBLE( IJUSE(IJLOOP,INVEG) ) / 1000d0 ) + ENDIF + ENDDO + + ! Apply the temperature correction from Gunther et al 92 to the + ! METHYL BUTENOL emissions. Units are still [kg C/box/step]. + IF ( TMMP > 273d0 ) THEN + EMISOP_MB = TCORR(TMMP) * EMBIO + ELSE + EMISOP_MB = 0d0 + ENDIF + + ENDIF + + !================================================================= + ! EMISOP_MB is the amount of METHYL BUTENOL emitted in + ! [kg/box/step]. Convert to [atoms C/box/step] and return. + !================================================================= + EMISOP_MB = EMISOP_MB * XNUMOL + +#if defined( GEOS_3 ) + + ! GEOS-3 meteorology results in 579 Tg C/yr from ISOP. Scale + ! this down to 400 Tg C/yr, which is what we get from GEOS-STRAT + ! (mje, djj, bmy, 8/26/02) + ! + ! NOTE: This actually produces more like 341 Tg for 2001 GEOS-3 + ! met fields, but that is OK (jal, bmy, 3/15/05) + EMISOP_MB = EMISOP_MB * ( 400d0 / 579d0 ) + +#elif defined( GEOS_4 ) + + ! Original GEOS-4 scaling produced 443 Tg C/yr w/ 2003 "V3" met + ! fields. However we have since switched to GEOS-4 "V4" met fields + ! and need to rescale the ISOP total. A recent run with GEOS-4 "V4" + ! met fields for 2001 produced 443 Tg C/yr. We need to force the + ! total to be the same as for GEOS-3, for comparison purposes. + ! Therefore apply a second scale factor so that we get 341 Tg C/yr + ! of ISOP for GEOS-4 "V4" met fields for 2001. (bmy, 3/15/05) + EMISOP_MB = EMISOP_MB * ( 400d0 / 443d0 ) + EMISOP_MB = EMISOP_MB * ( 341.2376d0 / 442.7354d0 ) + +#endif + + ! Return to calling program + END FUNCTION EMISOP_MB diff --git a/code/emissdr.f b/code/emissdr.f new file mode 100644 index 0000000..4119e7d --- /dev/null +++ b/code/emissdr.f @@ -0,0 +1,633 @@ +! $Id: emissdr.f,v 1.2 2009/10/26 18:54:15 daven Exp $ + SUBROUTINE EMISSDR +! +!****************************************************************************** +! Subroutine EMISSDR computes emissions for the full chemistry simulation +! Emissions are stored in various arrays, which are then passed to the +! SMVGEAR solver via routine "setemis.f". (bmy, 10/8/98, 10/3/07) +! +! NOTES: +! (1 ) Now accounts for seasonal NOx emissions, and multi-level NOx +! emissions. (bmy, 10/8/98) +! (2 ) Surface NOx and 100m NOx are now placed into the correct sigma level. +! (bmy, 10/8/98) +! (3 ) Eliminate GISS-Specific code (bmy, 3/15/99) +! (4 ) Now includes monoterpenes for ACETONE emissions (bdf, 4/8/99) +! (5 ) Now uses allocatable arrays for ND29, ND36, and ND46 diagnostics. +! Also made some cosmetic changes, and updated comments (bmy, 3/16/00) +! (6 ) Eliminate obsolete code and ND63 diagnostic (bmy, 4/12/00) +! (7 ) Add reference to BIOBURN in "biomass_mod.f" and to BIOFUEL_BURN +! in "biofuel_mod.f". Also remove references to BURNEMIS and TWOODIJ. +! (bmy, 9/12/00) +! (8 ) Remove reference to "biomass.h" -- that is replaced by F90 module +! "biomass_mod.f". (bmy, 9/25/00) +! (9 ) Remove obsolete code from 9/12/00 and 9/25/00 (bmy, 12/21/00) +! (10) Add CO source from monoterpenes (bnd, bmy, 12/21/00) +! (11) Add monoterpene source to the ND46 diagnostic. Renamed EMXX to +! EMIS (for Isoprene), and commented out Larry Horowitz's "special +! cases". Also made some cosmetic changes. (bmy, 1/2/01) +! (12) Added CO source from CH3OH oxidation (bmy, 1/3/01) +! (13) Removed obsolete code from 1/2/01 (bmy, 3/15/01) +! (14) Now initialize GEMISNOX2. Also updated comments. (bdf, bmy, 6/15/01) +! (15) Now references routines from "acetone_mod.f" for the biogenic +! emission of acetone into the SMVGEAR arrays. Now use +! EMISRR(I,J,IDEACET) to archive ND46, since the biogenic +! acetone emissions are now computed in this array. Also define +! XNUMOL_C so as not to rely on IDTISOP being defined. Also add +! LASTMONTH variable to flag when we change month. (bmy, 9/4/01) +! (16) Now reference AIREMISS from "aircraft_nox_mod.f" (bmy, 2/14/02) +! (17) Replaced all instances of IM with IIPAR and JM with JJPAR, in order +! to prevent namespace confusion for the new TPCORE. Also removed +! obsolete, commented-out code. (bmy, 6/25/02) +! (18) Now references IDTNOX, etc. from "tracerid_mod.f". Now references +! SUNCOS from "dao_mod.f". Now make FIRSTEMISS a local SAVEd variable +! instead of an argument. (bmy, 11/15/02) +! (19) Now replaced DXYP(JREF)*1d4 with GET_AREA_CM2 from "grid_mod.f". +! Now remove MONTH from call to BIOBURN. Now use functions GET_MONTH, +! GET_LOCALTIME, GET_ELAPSED_MIN, GET_TS_EMIS, GET_LOCALTIME from +! "time_mod.f". Now use functions GET_XOFFSET and GET_YOFFSET from +! "grid_mod.f". (bmy, 2/11/03) +! (20) Now pass I, J to EMISOP, EMISOP_GRASS, EMISOP_MB (bmy, 12/9/03) +! (21) Now references EMLIGHTNING from "lightning_nox_mod.f" (bmy, 4/14/04) +! (22) Now references "logical_mod.f". Now replaced LFOSSIL with LANTHRO. +! (bmy, 7/20/04) +! (23) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (24) Now can use MEGAN inventory for biogenic VOCs. Now references +! "megan_mod.f" (bmy, tmf, 10/25/05) +! (25) Now call EMLIGHTNING_NL from "lightning_nox_nl_mod.f" for GEOS-4 so +! that we can use the new near-land lightning formulation. +! (ltm, bmy, 5/11/06) +! (26) Added switch for BIOGENIC emissions. Now revert to single +! lightning_nox_mod.f. Remove reference to old GEMISNOX array; this +! has been replaced by module arrays EMIS_LI_NOx and EMIS_AC_NOx, in +! order to avoid common block errors. (ltm, bmy, phs, 10/3/07) +! (27) Add biogenic emission of MONX and C2H4. (tmf, 1/20/09) +! (28) Add a switch, LMEGANMONO, for monoterpene and MBO emission to choose +! between MEGAN and GEIA inventory indenpendantly from Isoprene. +! This is because although we did, at one time, got monoterpene +! emission factors from Alex Guenther, he never published it. +! So there is no reference for it. Use of those emission factors have +! caused much confusion among users, so we should probably not use it +! for the time being. (tmf, 1/20/09) + +!****************************************************************************** +! + ! References to F90 modules + USE ACETONE_MOD, ONLY : EMISS_BIOACET, OCEAN_SOURCE_ACET + USE ACETONE_MOD, ONLY : READ_JO1D, READ_RESP + USE AIRCRAFT_NOX_MOD, ONLY : AIREMISS + USE BIOFUEL_MOD, ONLY : BIOFUEL_BURN + USE DAO_MOD, ONLY : PARDF, PARDR, SUNCOS + USE DIAG_MOD, ONLY : AD29, AD46, AD36 + USE DIAG49_MOD, ONLY : DO_SAVE_DIAG49 + USE DIAG_MOD, ONLY : EMISS_ANTHR + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET + USE LIGHTNING_NOX_MOD, ONLY : EMLIGHTNING + USE LOGICAL_MOD, ONLY : LANTHRO, LLIGHTNOX, LSOILNOX + USE LOGICAL_MOD, ONLY : LAIRNOX, LBIONOX, LWOODCO + USE LOGICAL_MOD, ONLY : LMEGAN, LMEGANMONO, LBIOGENIC + USE LOGICAL_MOD, ONLY : LRCPAIR ! (cdh, 10/14/11) + USE MEGAN_MOD, ONLY : GET_EMISOP_MEGAN + USE MEGAN_MOD, ONLY : GET_EMMBO_MEGAN + USE MEGAN_MOD, ONLY : GET_EMMONOT_MEGAN + USE RCP_MOD, ONLY : RCP_AIREMISS! (cdh, 10/14/11) + USE TIME_MOD, ONLY : GET_MONTH, GET_TAU + USE TIME_MOD, ONLY : GET_TS_EMIS, GET_LOCALTIME + USE TRACER_MOD, ONLY : ITS_A_TAGCO_SIM + USE TRACERID_MOD, ONLY : IDEACET, IDTISOP, IDEISOP + USE TRACERID_MOD, ONLY : IDECO, IDEPRPE, NEMANTHRO + USE TRACERID_MOD, ONLY : IDEMONX, IDEC2H4 + USE TRACERID_MOD, ONLY : IDTMONX, IDTC2H4 + USE LOGICAL_MOD, ONLY : LHTAP + USE HTAP_MOD, ONLY : GET_HTAP + USE TRACERID_MOD, ONLY : IDEALK4, IDEACET, IDEMEK, IDEPRPE + USE TRACERID_MOD, ONLY : IDEC3H8, IDECH2O, IDEC2H6, IDEALD2 + USE TRACERID_MOD, ONLY : IDTCH2O + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN" ! IEBD1, IEBD2, JEBD1, JEBD2 +# include "CMN_DIAG" ! Diagnostic arrays and switches +# include "CMN_O3" ! Emissions arrays +# include "CMN_NOX" ! GEMISNOX2 +# include "CMN_MONOT" ! Monoterpenes +# include "comode.h" ! IVERT? + + ! Local variables + LOGICAL, SAVE :: FIRSTEMISS = .TRUE. + LOGICAL :: NO_TAGCO, MOLEC_CM2_S + INTEGER :: I, J, L, N, IJLOOP + INTEGER :: I0, J0, IOFF, JOFF, IREF, JREF + INTEGER :: NDAY,JSCEN,NN + INTEGER, SAVE :: LASTMONTH = -99 + REAL*8 :: DTSRCE, XLOCTM, EMIS, TMMP + REAL*8 :: BIOSCAL, AREA_CM2, EMMO, ACETSCAL + REAL*8 :: TMPVAL, EMMB, GRASS, BIO_ACET + REAL*8 :: CONVERT(NVEGTYPE), GMONOT(NVEGTYPE) + REAL*8 :: SC, PDF, PDR + ! HTAP + REAL*4 :: AD36_OLD(NEMANTHRO) + REAL*4 :: EMISS_ANTHR_OLD(NEMANTHRO) + + ! Add biogenic emission scale factor for ethene (tmf, 1/13/06) + REAL*8 :: BIOSCALEC2H4 + + ! Molecules C / kg C + REAL*8, PARAMETER :: XNUMOL_C = 6.022d+23 / 12d-3 + + ! External functions + REAL*8, EXTERNAL :: BOXVL, XLTMMP, EMISOP + REAL*8, EXTERNAL :: EMMONOT, EMISOP_MB, EMISOP_GRASS +! +!****************************************************************************** +! EMISSDR begins here! +! +! DTSRCE = emission timestep in seconds +! +! Call subroutines to set up ISOP and monoterpene emission (first time only!) +!****************************************************************************** +! + ! This is not a tagged CO simulation + NO_TAGCO = ( .not. ITS_A_TAGCO_SIM() ) + + ! Emission timestep [s] + DTSRCE = GET_TS_EMIS() * 60d0 + + ! Get nested-grid offsets + I0 = GET_XOFFSET() + J0 = GET_YOFFSET() + + IF ( FIRSTEMISS ) THEN + CALL RDLIGHT + CALL RDISOPT( CONVERT ) + CALL RDMONOT( GMONOT ) + CALL SETBASE( CONVERT, GMONOT ) + FIRSTEMISS = .FALSE. + ENDIF + +! +!****************************************************************************** +! BE CAREFUL WITH USING A WINDOW RELATIVE TO THE EMISSIONS WINDOW +! NEED SPECIFY THE OFFSET OF THE SUB-WINDOW +! +! first zero the arrays in which emissions will be stored +! +! EMISRRN(I,J,L) = Emission rate of NOx (N = IDENOX ) into box (I,J,L). +! Units are [molec NOx/box/s]. +! +! EMISRR(I,J,N) = Emission rate of tracer N into surface box (I,J,1). +! Units are [molec tracer/box/s]. +! +! GEMISNOX(I,J,L) = Array which stores NOx emissions from aircraft, +! and lightning. Units are [molec NOx/cm3/s]. +! +! GEMISNOX2(I,J) = Array which stores NOx emissions from soils. +! Units are [molec NOx/cm3/s]. +! +! NOTE: Now use F90 array initialization syntax (bmy, 3/15/99) +!****************************************************************************** +! + ! These need to be initialized on every call + EMISRRN = 0d0 + EMISRR = 0d0 + GEMISNOX2 = 0d0 + IF ( DO_SAVE_DIAG49 ) THEN + EMISS_ANTHR = 0d0 + ENDIF + + ! Loop over latitudes + IJLOOP = 0 + DO J = 1, JJPAR + JREF = J + J0 + + ! Compute surface area of grid boxes in cm^2 + AREA_CM2 = GET_AREA_CM2( J ) + + ! Loop over longitues + DO I = 1, IIPAR + IREF = I + I0 + IJLOOP = IJLOOP + 1 + + ! Zero biogenic acetone (bmy, 9/14/01) + BIO_ACET = 0d0 + + ! Use function GET_LOCALTIME to get the local time at lon I + ! Middle of time step is between 10pm-2am when IHOUR = 1 +!--prior to 4/16/09 (jlin, phs) +! IHOUR = INT( ( GET_LOCALTIME( I ) ) / 4 ) + 1 + IHOUR = NINT( ( GET_LOCALTIME( I ) ) / 4 ) + 1 + IF ( IHOUR .EQ. 7 ) IHOUR = 1 + + !================================================================= + ! attenuate emissions on the weekend --- + ! scale factors for Saturday/Sunday/Weekday must average out to 1! + ! JSCEN = 1 Saturday + ! JSCEN = 2 Sunday + ! JSCEN = 3 Weekday + ! + ! 1 Jan 1980 and 1 Jan 1985 were both Tuesdays, so NDAY mod 7 = 4 + ! is a Saturday and NDAY mod 7 = 5 is a Sunday (bmy, 3/23/98) + !================================================================= + NDAY = ( GET_TAU() / 24d0 ) + IF ( MOD( NDAY, 7 ) .eq. 4 ) THEN + JSCEN = 1 + ELSE IF ( MOD( NDAY, 7 ) .eq. 5 ) THEN + JSCEN = 2 + ELSE + JSCEN = 3 + ENDIF + + ! Fossil Fuel emissions (kg / Grid-Box / Time-Step) + ! NN = tracer number corresponding to emission species N + IF ( LANTHRO ) THEN + DO N = 1, NEMANTHRO + NN = IDEMS(N) + + + IF ( NN /= 0 ) THEN + + IF ( ND36 .GT. 0 ) AD36_OLD(N) = AD36(I,J,N) + IF ( DO_SAVE_DIAG49 ) + & EMISS_ANTHR_OLD(N) = EMISS_ANTHR(I,J,N) + CALL EMFOSSIL( I, J, N, NN, IREF, JREF, JSCEN ) + + ENDIF + + + IF ( N == IDEALK4 .or. N == IDEACET .or. + & N == IDEMEK .or. N == IDEPRPE .or. + & N == IDEC3H8 .or. N == IDECH2O .or. + & N == IDEC2H6 .or. N == IDEALD2 ) THEN + + IF ( LHTAP ) THEN + + EMISRR(I,J,N) = GET_HTAP( I, J, N ) + & * AREA_CM2 * TODH(IHOUR) + & * 1d-4 + + IF ( N == IDEALK4 ) EMISRR(I,J,N) = + & EMISRR(I,J,N) * XNUMOL_C + & * 83d-2 + + IF ( N == IDEACET ) EMISRR(I,J,N) = 0.75d0 * + & EMISRR(I,J,N) * XNUMOL_C + & * 620d-3 + + IF ( N == IDEMEK ) EMISRR(I,J,N) = 0.25d0 * + & EMISRR(I,J,N) * XNUMOL_C + & * 666d-3 + + IF ( N == IDEPRPE ) EMISRR(I,J,N) = + & EMISRR(I,J,N) * XNUMOL_C + & * 857d-3 + + IF ( N == IDEC3H8 ) EMISRR(I,J,N) = + & EMISRR(I,J,N) * XNUMOL_C + & * 818d-3 + + IF ( N == IDECH2O ) EMISRR(I,J,N) = + & EMISRR(I,J,N) * XNUMOL_C + & * 4d-1 + + IF ( N == IDEC2H6 ) EMISRR(I,J,N) = + & EMISRR(I,J,N) * XNUMOL_C + & * 8d-1 + + IF ( N == IDEALD2 ) EMISRR(I,J,N) = + & EMISRR(I,J,N) * XNUMOL_C + & * 545d-3 + + IF ( ND36 .GT. 0 ) + & AD36(I,J,N) = AD36_OLD(N) + EMISRR(I,J,N) + & * DTSRCE / AREA_CM2 + + IF ( DO_SAVE_DIAG49 ) + & EMISS_ANTHR(I,J,N) = EMISS_ANTHR_OLD(N) + + & EMISRR(I,J,N) * DTSRCE / AREA_CM2 + ENDIF + + ENDIF + + ENDDO + + ENDIF + +!----------------------------------------------------------------------------- +! LIGHTNING EMISSIONS NOX [molecules/cm3/s] +! + IF ( LLIGHTNOX ) CALL EMLIGHTNING( I, J ) +!----------------------------------------------------------------------------- +! SOIL EMISSIONS NOX [molecules/cm3/s] +! Now have to pass SUNCOS to SOILNOXEMS and SOILCRF (bmy, 10/20/99) +! + IF ( LSOILNOX .AND. I == 1 .AND. J == 1 ) + & CALL SOILNOXEMS( SUNCOS ) +!----------------------------------------------------------------------------- +! AIRCRAFT emissions NOx [molecules/cm3/s] +! + IF ( LAIRNOX .AND. I == 1 .AND. J == 1 ) THEN + + ! Choose between RCP inventory and default + ! (cdh, 6/14/12) + IF (LRCPAIR) THEN + CALL RCP_AIREMISS + ELSE + CALL AIREMISS + ENDIF + + ENDIF +!----------------------------------------------------------------------------- +! NOx AND CO from biofuel combustion [kg/box] +! + IF ( LWOODCO .AND. I == 1 .AND. J == 1 ) CALL BIOFUEL_BURN +!---------------------------------------------------------------------------- +! BIOGENIC EMISSIONS OF VARIOUS QUANTITIES [Atoms C/box/time step] +! + IF ( LBIOGENIC ) THEN + + ! Temperature + TMMP = XLTMMP(I,J,IJLOOP) + + ! Modified to choose MEGAN/GEIA inventory indenpendantly + ! for ISOP and MONX/MBO. (ccc, 1/20/09) + IF ( LMEGAN ) THEN + + !------------------ + ! MEGAN Isoprene + !------------------ + + ! Cosine of solar zenith angle + SC = SUNCOS(IJLOOP) + + ! Diffuse and direct PAR + PDR = PARDR(I,J) + PDF = PARDF(I,J) + + ! Isoprene + EMIS = GET_EMISOP_MEGAN( I, J, SC, TMMP, + & XNUMOL_C, PDR, PDF ) + + ELSE + + !------------------ + ! GEIA Isoprene + !------------------ + + ! Isoprene + EMIS = EMISOP( I, J, IJLOOP, SUNCOS, TMMP, XNUMOL_C) + + ENDIF + + + IF ( LMEGANMONO ) THEN + + !------------------ + ! MEGAN biogenics + !------------------ + + ! Monoterpenes + EMMO = GET_EMMONOT_MEGAN( I, J, TMMP, XNUMOL_C ) + + ! Methyl butenol + EMMB = GET_EMMBO_MEGAN( I, J, SC, TMMP, + & XNUMOL_C, PDR, PDF ) + + ELSE + + !------------------ + ! GEIA biogenics + !------------------ + + ! Monoterpenes + EMMO = EMMONOT( IJLOOP, + & TMMP, XNUMOL_C ) + + ! Methyl Butenol + EMMB = EMISOP_MB( I, J, IJLOOP, SUNCOS, + & TMMP, XNUMOL_C ) + + ENDIF + + + ! Isoprene emissions from grasslands (use GEIA always) + ! + ! Note from May Fu (cetmfu@polyu.edu.hk), 02 Dec 2008: + ! + ! EMISOP_GRASS calculates isoprene emission from grasslands + ! using the GEIA inventory; this is used only in EMISS_BIOACET + ! below to calculate grassland acetone emission. + ! + ! EMISOP (GEIA) and GET_EMISOP_MEGAN (MEGAN) already contains + ! the full isoprene emission, including grasslands. Therefore + ! EMISOP_GRASS should NOT be considered as an additional + ! isoprene source. + !-------------------------------------------------------------- + GRASS = EMISOP_GRASS(I, J,IJLOOP, SUNCOS, TMMP, XNUMOL_C) + +!----------------------------------------------------------------------------- +! BIOGENIC ACETONE EMISSIONS +! + IF ( IDEACET /= 0 ) THEN + + ! Read monthly mean JO1D and leaf respiration values + ! These will be stored internally in "acetone_mod.f" + IF ( I==1 .and. J==1 ) THEN + IF ( GET_MONTH() /= LASTMONTH ) THEN + CALL READ_JO1D( GET_MONTH() ) + CALL READ_RESP( GET_MONTH() ) + LASTMONTH = GET_MONTH() + ENDIF + ENDIF + + ! Compute biogenic acetone emissions [atoms C/box/s] + CALL EMISS_BIOACET( I, J, TMMP, EMMO, + & EMIS, EMMB, GRASS, BIO_ACET ) + + ! Also add ocean source of acetone [atoms C/box/s] + CALL OCEAN_SOURCE_ACET( I, J, BIO_ACET ) + + ! Add biogenic acetone to anthro source [atoms C/box/s] + ! NOTE: Don't save into EMISRR for the tagged CO + ! simulation (jaf, mak, bmy, 2/14/08) + IF ( NO_TAGCO ) THEN + EMISRR(I,J,IDEACET) = EMISRR(I,J,IDEACET) + BIO_ACET + ENDIF + ENDIF +!----------------------------------------------------------------------------- + + !============================================================== + ! save biogenic isoprene emission for later use + ! EMISRR has units [atoms C/box/s] + !============================================================== + IF ( IDTISOP /= 0 ) THEN + + ! NOTE: Don't save into EMISRR for the tagged CO + ! simulation (jaf, mak, bmy, 2/14/08) + IF ( NO_TAGCO ) THEN + EMISRR(I,J,IDEISOP) = EMISRR(I,J,IDEISOP) + + & ( EMIS / DTSRCE ) + ENDIF + ENDIF + + !================================================================= + ! save biogenic monoterpene emission for later use + ! EMISRR has units [atoms C/box/s] (tmf, 4/10/06) + !================================================================= + IF ( IDTMONX /= 0 ) THEN + EMISRR(I,J,IDEMONX) = EMISRR(I,J,IDEMONX) + + & ( EMMO / DTSRCE ) + ENDIF + +!------------------------------------------------------------------------------ +! +!****************************************************************************** +! Biogenic source of CO -- from oxidation of METHANOL and MONOTERPENES +! +! CO from METHANOL oxidation -- scaled from ISOPRENE (bnd, 1/2/01) +! +! We need to scale the Isoprene flux to get the CH3OH (methanol) flux. +! Currently, the annual isoprene flux in GEOS-CHEM is ~ 397 Tg C. +! +! Daniel Jacob recommends a flux of 100 Tg/yr CO from CH3OH oxidation +! based on Singh et al. 2000 [JGR 105, 3795-3805] who estimate a global +! methanol source of 122 Tg yr-1, of which most (75 Tg yr-1) is +! "primary biogenic". He also recommends for now that the CO flux +! from CH3OH oxidation be scaled to monthly mean isoprene flux. +! +! To get CO from METHANOL oxidation, we must therefore multiply +! the ISOPRENE flux by the following scale factor: +! ( 100 Tg CO from CH3OH Oxidation / 397 Tg C from Isoprene Flux ) * +! ( 12 g C/mole / 28 g CO/mole ) +! +! CO from MONOTERPENE oxidation (bnd, bmy, 1/2/01) +! +! Assume the production of CO from monoterpenes is instantaneous even +! though the lifetime of intermediate species may be on the order of hours +! or days. This assumption will likely cause CO from monoterpene oxidation +! to be too high in the box in which the monoterpene is emitted. +! +! The CO yield here is taken from: +! +! Hatakeyama et al. JGR, Vol. 96, p. 947-958 (1991) +! "The ultimate yield of CO from the tropospheric oxidation of terpenes +! (including both O3 and OH reactions) was estimated to be 20% on the +! carbon number basis." They studied ALPHA- & BETA-pinene. +! +! Vinckier et al. Fresenius Env. Bull., Vol. 7, p.361-368 (1998) +! "R(CO)=1.8+/-0.3" : 1.8/10 is about 20%. +!****************************************************************************** +! + !===================================================== + ! CO from MONOTERPENE oxidation [molec CO/box/s] + !==================================================== + + ! NOTE: Don't save into EMISRR for the tagged CO simulation. + ! Also for tagged CO we don't use monoterpenes ?????? + ! (jaf, mak, bmy, 2/14/08) + IF ( NO_TAGCO ) THEN + TMPVAL = ( EMMO / DTSRCE ) * 0.2d0 + EMISRR(I,J,IDECO) = EMISRR(I,J,IDECO) + TMPVAL + + ! ND29: CO-source from monoterpenes [molec/cm2/s] + IF ( ND29 > 0 ) THEN + AD29(I,J,5) = AD29(I,J,5) + ( TMPVAL / AREA_CM2 ) + ENDIF + ENDIF +! +!****************************************************************************** +! Biogenic source of PRPE -- scaled to ISOPRENE +! +! Also, add biogenic emissions of alkenes. We do this by scaling to +! isoprene emissions (probably OK for summertime conditions). The +! scaling factor is based on work by Allen Goldstein. His values +! indicate emission ratios of ethene:propene:butene=4:2:1 (on a +! per molecule basis), with total emissions approx. equal to +! 10% of isoprene emissions (again, on molecule basis). +! BIOSCAL is in units of atoms C (alkenes) / atoms C (isoprene) +!****************************************************************************** +! Change this factor to exclude ethene (bey, ljm) +! (10 molec alkenes / 100 molec isop) * (1 molec isop / 5 atoms C isop) +! *(3 molec butene + propene / 7 molec total alkenes) +! *(3.3333 atoms C but+prop mix/ 1 molec but+prop mix) +! = 0.0286 atoms C butene+propene / atom C isop +! Note that 3.3333 atoms C/molecule is the weighted average for this mix. +!****************************************************************************** +! + BIOSCAL = 0.0286d0 ! new factor, (ljm, bey, 9/28/98) + + IF ( IDEPRPE /= 0 ) THEN + + ! NOTE: Don't save into EMISRR for the tagged + ! CO simulation. (jaf, mak, bmy, 2/14/08) + IF ( NO_TAGCO ) THEN + EMISRR(I,J,IDEPRPE) = EMISRR(I,J,IDEPRPE) + + & ( EMIS / DTSRCE ) * BIOSCAL + ENDIF + ENDIF + +!======================================================================= +! Add biogenic emission of ethene (C2H4) --> scaled to isoprene +! +! Scale factor BIOSCALEC2H4 = +! ( 10 molec alkenes / 100 molec isop ) * ( 1 molec isop / 5 atoms C ) +! * ( 4 molec ethene / 7 molec alkenes ) +! * ( 2 atoms C / 1 molec ethene ) +! = 0.022857d0 [atoms C / atoms C isop] +! (tmf, 1/13/06) + + BIOSCALEC2H4 = 0.022857d0 + + IF ( IDEC2H4 /= 0 ) THEN + EMISRR(I,J,IDEC2H4) = EMISRR(I,J,IDEC2H4) + + & ( EMIS / DTSRCE ) * BIOSCALEC2H4 + ENDIF +!======================================================================= + +! +!****************************************************************************** +! ND46 diagnostic: Biogenic emissions +! +! AD46(:,:,1) = Total biogenic ISOP emissions [atoms C/cm2/s] +! AD46(:,:,2) = Total biogenic ACET emissions [atoms C/cm2/s] +! AD46(:,:,3) = Total biogenic PRPE emissions [atoms C/cm2/s] +! AD46(:,:,4) = Total biogenic MONOT emissions [atoms C/cm2/s] +! AD46(:,:,5) = Total biogenic MBO emissions [atoms C/cm2/s] +! +! NOTES: +! (1 ) Now make ACET tracer #2 and PRPE tracer #3 (bmy, 9/13/01) +! (2 ) Now archive ND46 as [atoms C/cm2/s] here (bmy, 9/13/01) +! (3 ) Added MBO emission diagnostics [atoms C/cm2/s] (bmy, tmf, 10/20/05) +!****************************************************************************** +! + IF ( ND46 > 0 ) THEN + + ! ISOP emissions [atoms C/cm2/s] -- tracer #1 + AD46(I,J,1) = AD46(I,J,1) + ( EMIS / AREA_CM2 /DTSRCE) + + ! ACET emissions [atoms C/cm2/s] -- tracer #2 + AD46(I,J,2) = AD46(I,J,2) + ( BIO_ACET / AREA_CM2 ) + + ! PRPE emissions [atoms C/cm2/s] -- tracer #3 + AD46(I,J,3) = AD46(I,J,3) + + & ( EMIS * BIOSCAL / AREA_CM2 / DTSRCE ) + + ! Monoterpene emissions [atoms C/cm2/s] -- tracer #4 + AD46(I,J,4) = AD46(I,J,4) + ( EMMO / AREA_CM2 /DTSRCE) + + ! MBO emissions [atoms C/cm2/s] -- tracer #5 + AD46(I,J,5) = AD46(I,J,5) + ( EMMB / AREA_CM2 /DTSRCE) + + ! C2H4 emissions [atoms C/cm2/s] -- tracer #6 (tmf, 1/13/06) + AD46(I,J,6) = AD46(I,J,6) + + & ( EMIS * BIOSCALEC2H4 / AREA_CM2 / DTSRCE ) + + ENDIF + ENDIF + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE EMISSDR + diff --git a/code/emissions_mod.f b/code/emissions_mod.f new file mode 100644 index 0000000..42a32de --- /dev/null +++ b/code/emissions_mod.f @@ -0,0 +1,653 @@ +! $Id: emissions_mod.f,v 1.3 2012/03/01 22:00:26 daven Exp $ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: EMISSIONS_MOD +! +! !DESCRIPTION: Module EMISSIONS\_MOD is used to call the proper emissions +! subroutines for the various GEOS-CHEM simulations. (bmy, 2/11/03, 2/14/08) +!\\ +!\\ +! !INTERFACE: +! + MODULE EMISSIONS_MOD +! +! !USES: +! + IMPLICIT NONE + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: DO_EMISSIONS + !FP_ISOP (6/2009) + PUBLIC :: ISOP_SCALING,NOx_SCALING +! +! !REVISION HISTORY: +! (1 ) Now references DEBUG_MSG from "error_mod.f" +! (2 ) Now references "Kr85_mod.f" (jsw, bmy, 8/20/03) +! (3 ) Now references "carbon_mod.f" and "dust_mod.f" (rjp, tdf, bmy, 4/2/04) +! (4 ) Now references "seasalt_mod.f" (rjp, bmy, bec, 4/20/04) +! (5 ) Now references "logical_mod" & "tracer_mod.f" (bmy, 7/20/04) +! (6 ) Now references "epa_nei_mod.f" and "time_mod.f" (bmy, 11/5/04) +! (7 ) Now references "emissions_mod.f" (bmy, 12/7/04) +! (8 ) Now calls EMISSSULFATE if LCRYST=T. Also read EPA/NEI emissions for +! the offline aerosol simulation. (bmy, 1/11/05) +! (9 ) Remove code for the obsolete CO-OH param simulation (bmy, 6/24/05) +! (10) Now references "co2_mod.f" (pns, bmy, 7/25/05) +! (11) Now references "emep_mod.f" (bdf, bmy, 10/1/05) +! (12) Now references "gfed2_biomass_mod.f" (bmy, 3/30/06) +! (13) Now references "bravo_mod.f" (rjp, kfb, bmy, 6/26/06) +! (14) Now references "edgar_mod.f" (avd, bmy, 7/6/06) +! (15) Now references "streets_anthro_mod.f" (yxw, bmy, 8/18/06) +! (16) Now references "h2_hd_mod.f" (lyj, phs, 9/18/07) +! (17) Now calls EMISSDR for tagged CO simulation (jaf, mak, bmy, 2/14/08) +! (18) Now references "cac_anthro_mod.f" (amv, phs, 03/11/08) +! (19) Now references "vistas_anthro_mod.f" (amv, 12/02/08) +! (20) Bug fixe : add specific calls for Streets for the grid 0.5x0.666. +! (dan, ccc, 3/11/09) +!EOP +!------------------------------------------------------------------------------ + + !FP_ISOP. For scaling Isoprene and NOx emissions. + REAL*8 :: ISOP_SCALING,NOx_SCALING = 1d0 + + CONTAINS + +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: DO_EMISSIONS +! +! !DESCRIPTION: Subroutine DO\_EMISSIONS is the driver routine which calls +! the appropriate emissions subroutine for the various GEOS-CHEM simulations. +! (bmy, 2/11/03, 2/14/08) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE DO_EMISSIONS +! +! !USES: +! + USE BIOMASS_MOD, ONLY : NBIOMAX + USE BIOMASS_MOD, ONLY : COMPUTE_BIOMASS_EMISSIONS + USE ARCTAS_SHIP_EMISS_MOD, ONLY : EMISS_ARCTAS_SHIP + USE BRAVO_MOD, ONLY : EMISS_BRAVO + USE C2H6_MOD, ONLY : EMISSC2H6 + USE CAC_ANTHRO_MOD, ONLY : EMISS_CAC_ANTHRO + USE CAC_ANTHRO_MOD, ONLY : EMISS_CAC_ANTHRO_05x0666 + USE CARBON_MOD, ONLY : EMISSCARBON + USE CH3I_MOD, ONLY : EMISSCH3I + USE CO2_MOD, ONLY : EMISSCO2 + USE DUST_MOD, ONLY : EMISSDUST + USE EDGAR_MOD, ONLY : EMISS_EDGAR + USE EMEP_MOD, ONLY : EMISS_EMEP + USE EMEP_MOD, ONLY : EMISS_EMEP_05x0666 + USE EPA_NEI_MOD, ONLY : EMISS_EPA_NEI + USE ERROR_MOD, ONLY : DEBUG_MSG + USE GLOBAL_CH4_MOD, ONLY : EMISSCH4 + USE H2_HD_MOD, ONLY : EMISS_H2_HD + USE HCN_CH3CN_MOD, ONLY : EMISS_HCN_CH3CN + USE Kr85_MOD, ONLY : EMISSKr85 + USE LOGICAL_MOD + USE MERCURY_MOD, ONLY : EMISSMERCURY + USE NEI2005_ANTHRO_MOD, ONLY : EMISS_NEI2005_ANTHRO + USE NEI2005_ANTHRO_MOD, ONLY : EMISS_NEI2005_ANTHRO_05x0666 + USE RETRO_MOD, ONLY : EMISS_RETRO + USE NEI2008_ANTHRO_MOD, ONLY : EMISS_NEI2008_ANTHRO !(krt, 5/13/13) + USE NEI2008_ANTHRO_MOD, ONLY : EMISS_NEI2008_ANTHRO_NATIVE !krt + USE RnPbBe_MOD, ONLY : EMISSRnPbBe + USE SEASALT_MOD, ONLY : EMISSSEASALT + USE STREETS_ANTHRO_MOD, ONLY : EMISS_STREETS_ANTHRO + USE STREETS_ANTHRO_MOD, ONLY : EMISS_STREETS_ANTHRO_05x0666 + USE STREETS_ANTHRO_MOD, ONLY : EMISS_STREETS_ANTHRO_025x03125 !(lzh,02/01/2015) + USE SULFATE_MOD, ONLY : EMISSSULFATE + USE TIME_MOD, ONLY : GET_MONTH, GET_YEAR + USE TIME_MOD, ONLY : ITS_A_NEW_MONTH, ITS_A_NEW_YEAR + USE TIME_MOD, ONLY : ITS_A_NEW_DAY, ITS_A_NEW_HOUR + USE TRACER_MOD + USE TAGGED_CO_MOD, ONLY : EMISS_TAGGED_CO + USE VISTAS_ANTHRO_MOD, ONLY : EMISS_VISTAS_ANTHRO + USE ICOADS_SHIP_MOD, ONLY : EMISS_ICOADS_SHIP !(cklee,7/09/09) + USE RCP_MOD, ONLY : LOAD_RCP_EMISSIONS !cdh + USE PARANOX_MOD, ONLY : READ_PARANOX_LUT + USE HTAP_MOD, ONLY : EMISS_HTAP + +# include "CMN_SIZE" ! Size parameters +# include "CMN_O3" ! FSCLYR +! +! !REVISION HISTORY: +! (1 ) Now references DEBUG_MSG from "error_mod.f" (bmy, 8/7/03) +! (2 ) Now calls Kr85 emissions if NSRCX == 12 (jsw, bmy, 8/20/03) +! (3 ) Now calls EMISSCARBON and EMISSDUST for carbon aerosol and dust +! aerosol chemistry (rjp, tdf, bmy, 4/2/04) +! (4 ) Now calls EMISSSEASALT for seasalt emissions (rjp, bec, bmy, 4/20/04) +! (5 ) Now use inquiry functions from "tracer_mod.f". Now references +! "logical_mod.f" (bmy, 7/20/04) +! (6 ) Now references ITS_A_NEW_MONTH from "time_mod.f". Now references +! EMISS_EPA_NEI from "epa_nei_mod.f" (bmy, 11/5/04) +! (7 ) Now calls EMISSMERCURY from "mercury_mod.f" (eck, bmy, 12/7/04) +! (8 ) Now calls EMISSSULFATE if LCRYST=T. Also read EPA/NEI emissions for +! the offline sulfate simulation. Also call EMISS_EPA_NEI for the +! tagged CO simulation. (cas, bmy, stu, 1/10/05). +! (9 ) Now call EMISSSEASALT before EMISSSULFATE (bec, bmy, 4/13/05) +! (10) Now call EMISS_HCN_CH3CN from "hcn_ch3cn_mod.f". Also remove all +! references to the obsolete CO-OH param simulation. (xyp, bmy, 6/23/05) +! (11) Now call EMISSCO2 from "co2_mod.f" (pns, bmy, 7/25/05) +! (12) Now references EMISS_EMEP from "emep_mod.f" (bdf, bmy, 11/1/05) +! (13) Now call GFED2_COMPUTE_BIOMASS to read 1x1 biomass emissions and +! regrid to the model resolution once per month. (bmy, 3/30/06) +! (14) Now references EMISS_BRAVO from "bravo_mod.f" (rjp, kfb, bmy, 6/26/06) +! (15) Now references EMISS_EDGAR from "edgar_mod.f" (avd, bmy, 7/6/06) +! (16) Now references EMISS_STREETS_ANTHRO from "streets_anthro_mod.f" +! (yxw, bmy, 8/17/06) +! (17) Now calls EMISSDR for tagged CO simulation (jaf, mak, bmy, 2/18/08) +! (18) Now references EMISS_CAC_ANTHRO from "cac_anthro_mod.f" +! (amv, phs, 3/11/08) +! (19) Now references EMISS_ARCTAS_SHIP from "arctas_ship_emiss_mod.f" +! (phs, 5/12/08) +! (20) Now references EMISS_VISTAS_ANTHR from "vistas_anthro_mod.f". Call +! EMEP, and Streets every month (amv, 12/2/08) +! (21) Now references EMISS_NEI2005_ANTHRO from "nei2005_anthro_mod.f" +! (amv, 10/19/09) +! 07 Feb 2011 - R. Yantosca - Use NEI99 biofuels when useing NEI05 anthro +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: MONTH, YEAR + REAL*8 :: BIOMASS(IIPAR,JJPAR,NBIOMAX) + + !================================================================= + ! DO_EMISSIONS begins here! + !================================================================= + + ! Get year and month + MONTH = GET_MONTH() + + ! check if emissions year differs from met field year + IF ( FSCALYR < 0 ) THEN + YEAR = GET_YEAR() + ELSE + YEAR = FSCALYR + ENDIF + + + ! Get biomass burning emissions for use below + IF ( LBIOMASS ) THEN + CALL COMPUTE_BIOMASS_EMISSIONS( GET_YEAR(), MONTH ) + ENDIF + + ! Test by simulation type + IF ( ITS_A_FULLCHEM_SIM() ) THEN + + !-------------------- + ! NOx-Ox-HC-aerosol + !-------------------- + + ! Read David Streets' emisisons over China / SE ASia + IF ( LSTREETS .and. ITS_A_NEW_MONTH() ) THEN +#if defined(GRID05x0666) + CALL EMISS_STREETS_ANTHRO_05x0666 !(dan) +#elif defined( GRID025x03125 ) + CALL EMISS_STREETS_ANTHRO_025x03125 ! (lzh, 02/01/2015) +#else + CALL EMISS_STREETS_ANTHRO +#endif + ENDIF + + ! Read EDGAR emissions once per month to get, at least + ! the NOx diurnal scale factors, and the EDGAR emissions + ! if necessary (amv, phs, 3/11/08) +!---------------- +! prior to 3/11/08 +! IF ( LEDGAR .and. ITS_A_NEW_MONTH() ) THEN +!---------------- + IF ( ITS_A_NEW_MONTH() ) THEN + CALL EMISS_EDGAR( YEAR, MONTH ) + ENDIF + + ! Read RETRO emissions once per month (wfr, 3/8/11) + IF ( LRETRO .and. ITS_A_NEW_MONTH() ) CALL EMISS_RETRO + + ! Read RCP emissions once per month (cdh, 10/14/11) + ! We read all emissions (for land, ship, air) even if only + ! one is needed + IF ( (LRCP .OR. LRCPSHIP .OR. LRCPAIR) .and. + & ITS_A_NEW_MONTH() ) CALL LOAD_RCP_EMISSIONS + + ! Read EPA/NEI99 (USA) emissions once per month + IF ( LNEI99 .and. ITS_A_NEW_MONTH() ) CALL EMISS_EPA_NEI + + ! Read VISTAS (USA) emissions once per month + IF ( LVISTAS .and. ITS_A_NEW_MONTH() ) + & CALL EMISS_VISTAS_ANTHRO + + ! Read BRAVO (Mexico) emissions once per year + IF ( LBRAVO .and. ITS_A_NEW_YEAR() ) CALL EMISS_BRAVO + + ! Read EMEP (Europe) emissions once per year (adj32_015) + IF ( LEMEP .and. ITS_A_NEW_MONTH() ) THEN +#if defined(GRID05x0666) + CALL EMISS_EMEP_05x0666 +#else + CALL EMISS_EMEP +#endif + ENDIF + + ! Read CAC emissions (adj32_015) + IF ( LCAC .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_CAC_ANTHRO_05x0666 +#else + CALL EMISS_CAC_ANTHRO +#endif + ENDIF + + ! Read NEI2005 (USA) emissions (adj32_015) + IF ( LNEI05 .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO_05x0666 ! Use NEI05 anthro, global +#else + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO ! Use NEI05 anthro, global +#endif + ENDIF + + ! Calculate NEI2008 (USA) emissions every day + IF ( LNEI08 .AND. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_EPA_NEI + CALL EMISS_NEI2008_ANTHRO_NATIVE ! Use NEI08 anthro, nested +#else + CALL EMISS_EPA_NEI + CALL EMISS_NEI2008_ANTHRO ! Use NEI08 anthro, global +#endif + ENDIF + + IF (LHTAP .and. ITS_A_NEW_MONTH() ) CALL EMISS_HTAP + + ! Read SO2 ARCTAS emissions + IF ( LARCSHIP .AND. ITS_A_NEW_YEAR() ) + $ CALL EMISS_ARCTAS_SHIP( YEAR ) + + ! Read NEI2008 (USA) emissions every month + IF ( LNEI08 .AND. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_NEI2008_ANTHRO_NATIVE +#else + CALL EMISS_NEI2008_ANTHRO +#endif + ENDIF + + ! Read ICOADS ship emissions once per month (cklee, 7/09/09) + IF ( LICOADSSHIP .and. ITS_A_NEW_MONTH() ) + & CALL EMISS_ICOADS_SHIP + + ! Read look up tables for PARANOX ship plume model (mpayer, 2/7/12) + IF ( ( LICOADSSHIP .or. LEDGARSHIP .or. LEMEPSHIP ) + & .and. ITS_A_NEW_MONTH() ) THEN + CALL READ_PARANOX_LUT + ENDIF + + ! C2H6 emissions using RETRO are too low, use Yaping Xiao's + ! offline C2H6 emissions instead (mpayer, 3/22/12) + CALL EMISSC2H6 + + ! NOx-Ox-HC (w/ or w/o aerosols) + CALL EMISSDR + + ! Emissions for various aerosol types + IF ( LSSALT ) CALL EMISSSEASALT + IF ( LSULF .or. LCRYST ) CALL EMISSSULFATE + IF ( LCARB ) CALL EMISSCARBON + IF ( LDUST ) CALL EMISSDUST + + ELSE IF ( ITS_AN_AEROSOL_SIM() ) THEN + + !-------------------- + ! Offline aerosol + !-------------------- + + ! Read David Streets' emisisons over China / SE ASia +!---------------- +! prior to 12/9/08 +! IF ( LSTREETS .and. ITS_A_NEW_YEAR() ) THEN + IF ( LSTREETS .and. ITS_A_NEW_MONTH() ) THEN +#if defined(GRID05x0666) + CALL EMISS_STREETS_ANTHRO_05x0666 !(dan) +#elif defined( GRID025x03125 ) + CALL EMISS_STREETS_ANTHRO_025x03125 ! (lzh,02/01/2015) +#else + CALL EMISS_STREETS_ANTHRO +#endif + ENDIF + + ! Read CAC emissions (adj32_015) + IF ( LCAC .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_CAC_ANTHRO_05x0666 +#else + CALL EMISS_CAC_ANTHRO +#endif + ENDIF + + ! Read EDGAR emissions once per month +!---------------- +! prior to 3/11/08 +! IF ( LEDGAR .and. ITS_A_NEW_MONTH() ) THEN +!---------------- + IF ( ITS_A_NEW_MONTH() ) THEN + CALL EMISS_EDGAR( YEAR, MONTH ) + ENDIF + + ! Read EPA/NEI99 emissions once per month + IF ( LNEI99 .and. ITS_A_NEW_MONTH() ) CALL EMISS_EPA_NEI + + ! Read NEI2005 emissions once per month (adj32_015) + IF ( LNEI05 .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO_05x0666 ! Use NEI05 anthro, global +#else + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO ! Use NEI05 anthro, global +#endif + ENDIF + + + ! Calculate NEI2008 emissions once per day + IF ( LNEI08 .AND. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) .or. defined( GRID025x03125 ) + CALL EMISS_NEI2008_ANTHRO_NATIVE +#else + CALL EMISS_NEI2008_ANTHRO +#endif + ENDIF + + IF (LHTAP .and. ITS_A_NEW_MONTH() ) CALL EMISS_HTAP + + ! Read BRAVO (Mexico) emissions once per year + IF ( LBRAVO .and. ITS_A_NEW_YEAR() ) CALL EMISS_BRAVO + + ! Read EMEP (Europe) emissions once per year (adj32_015) + IF ( LEMEP .and. ITS_A_NEW_YEAR() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_EMEP_05x0666 +#else + CALL EMISS_EMEP +#endif + ENDIF + + ! Read SO2 ARCTAS emissions + IF ( LARCSHIP .AND. ITS_A_NEW_YEAR() ) + $ CALL EMISS_ARCTAS_SHIP( YEAR ) + + ! Read ICOADS ship emissions once per month !(cklee, 7/09/09) + IF ( LICOADSSHIP .and. ITS_A_NEW_MONTH() ) THEN + CALL EMISS_ICOADS_SHIP + ENDIF + + ! Emissions for various aerosol types + IF ( LSSALT ) CALL EMISSSEASALT + IF ( LSULF .or. LCRYST ) CALL EMISSSULFATE + IF ( LCARB ) CALL EMISSCARBON + IF ( LDUST ) CALL EMISSDUST + + ELSE IF ( ITS_A_RnPbBe_SIM() ) THEN + + !-------------------- + ! Rn-Pb-Be + !-------------------- + CALL EMISSRnPbBe + + ELSE IF ( ITS_A_CH3I_SIM() ) THEN + + !-------------------- + ! CH3I + !-------------------- + + ! Emit CH3I + CALL EMISSCH3I + + ELSE IF ( ITS_A_HCN_SIM() ) THEN + + !-------------------- + ! HCN - CH3CN + !-------------------- + CALL EMISS_HCN_CH3CN( N_TRACERS, STT ) + + ELSE IF ( ITS_A_TAGCO_SIM() ) THEN + + !-------------------- + ! Tagged CO + !-------------------- + + ! Read David Streets' emisisons over China / SE ASia + ! Bug fix: call every month now (pdk, phs, 3/17/09) + IF ( LSTREETS .and. ITS_A_NEW_MONTH() ) THEN +#if defined(GRID05x0666) + CALL EMISS_STREETS_ANTHRO_05x0666 !(dan) +#elif defined( GRID025x03125 ) + CALL EMISS_STREETS_ANTHRO_025x03125 ! (lzh,02/01/2015) +#else + CALL EMISS_STREETS_ANTHRO +#endif + ENDIF + + ! Read CAC emissions (adj32_015) + IF ( LCAC .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_CAC_ANTHRO_05x0666 +#else + CALL EMISS_CAC_ANTHRO +#endif + ENDIF + + ! Read EDGAR emissions once per month +!---------------- +! prior to 3/11/08 +! IF ( LEDGAR .and. ITS_A_NEW_MONTH() ) THEN +!---------------- + IF ( ITS_A_NEW_MONTH() ) THEN + CALL EMISS_EDGAR( YEAR, MONTH ) + ENDIF + + ! Read EPA (USA) emissions once per month + IF ( LNEI99 .and. ITS_A_NEW_MONTH() ) CALL EMISS_EPA_NEI + + ! Read NEI2005 (USA) emissions once per year (adj32_015) + IF ( LNEI05 .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO_05x0666 ! Use NEI05 anthro, global +#else + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO ! Use NEI05 anthro, global +#endif + ENDIF + + + ! Read NEI2008 (USA) emissions once per month + IF ( LNEI08 .AND. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) .or. defined ( GRID025x03125 ) + CALL EMISS_NEI2008_ANTHRO_NATIVE ! Use NEI08 anthro, nested +#else + CALL EMISS_NEI2008_ANTHRO ! Use NEI08 anthro, global +#endif + ENDIF + + IF (LHTAP .and. ITS_A_NEW_MONTH() ) CALL EMISS_HTAP + + ! Read BRAVO (Mexico) emissions once per year + IF ( LBRAVO .and. ITS_A_NEW_YEAR() ) CALL EMISS_BRAVO + + ! Read EPA (Europe) emissions once per year (adj32_015) + IF ( LEMEP .and. ITS_A_NEW_YEAR() ) THEN +#if defined(GRID05x0666) + CALL EMISS_EMEP_05x0666 +#else + CALL EMISS_EMEP +#endif + ENDIF + + ! Read ICOADS ship emissions once per month (cklee, 7/09/09) + IF ( LICOADSSHIP .and. ITS_A_NEW_MONTH() ) THEN + CALL EMISS_ICOADS_SHIP + ENDIF + + ! Now call EMISSDR for Tagged CO fossil fuel emissions, + ! so that we get the same emissions for Tagged CO as + ! we do for the full-chemistry (jaf, mak, bmy, 2/14/08) + CALL EMISSDR + + ! Emit tagged CO + CALL EMISS_TAGGED_CO + + ELSE IF ( ITS_A_C2H6_SIM() ) THEN + + !-------------------- + ! C2H6 + !-------------------- + + ! Emit C2H6 + CALL EMISSC2H6 + + ELSE IF ( ITS_A_CH4_SIM() ) THEN + + !-------------------- + ! CH4 + !-------------------- + + ! Read David Streets' emisisons over China / SE ASia + ! Bug fix: call every month now (phs, 3/17/09) + IF ( LSTREETS .and. ITS_A_NEW_MONTH() ) THEN +#if defined(GRID05x0666) + CALL EMISS_STREETS_ANTHRO_05x0666 !(dan) +#else + CALL EMISS_STREETS_ANTHRO +#endif + ENDIF + + ! Emit CH4 + CALL EMISSCH4 + + ELSE IF ( ITS_A_MERCURY_SIM() ) THEN + + !-------------------- + ! Mercury + !-------------------- + CALL EMISSMERCURY + + ELSE IF ( ITS_A_CO2_SIM() ) THEN + + !-------------------- + ! CO2 + !-------------------- + + ! Read David Streets' emisisons over China / SE ASia + ! Bug fix: call every month now (phs, 3/17/09) + IF ( LSTREETS .and. ITS_A_NEW_MONTH() ) THEN +#if defined(GRID05x0666) + CALL EMISS_STREETS_ANTHRO_05x0666 !(dan) +#else + CALL EMISS_STREETS_ANTHRO +#endif + ENDIF + + ! Read CO2 ARCTAS SHIP emissions + IF ( LARCSHIP .and. ITS_A_NEW_YEAR() ) + $ CALL EMISS_ARCTAS_SHIP( YEAR ) + + ! Emit CO2 + CALL EMISSCO2 + + ELSE IF ( ITS_A_H2HD_SIM() ) THEN + + !-------------------- + ! Offline H2/HD + !-------------------- + + ! Read David Streets' emisisons over China / SE ASia + ! Bug fix: call every month now (phs, 3/17/09) + IF ( LSTREETS .and. ITS_A_NEW_MONTH() ) THEN +#if defined(GRID05x0666) + CALL EMISS_STREETS_ANTHRO_05x0666 !(dan) +#else + CALL EMISS_STREETS_ANTHRO +#endif + ENDIF + + ! Read EDGAR emissions once per month +!---------------- +! prior to 3/11/08 +! IF ( LEDGAR .and. ITS_A_NEW_MONTH() ) THEN +!---------------- + IF ( ITS_A_NEW_MONTH() ) THEN + CALL EMISS_EDGAR( YEAR, MONTH ) + ENDIF + + ! Read CAC emissions (adj32_015) + IF ( LCAC .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_CAC_ANTHRO_05x0666 +#else + CALL EMISS_CAC_ANTHRO +#endif + ENDIF + + ! Read EPA (USA) emissions once per month + IF ( LNEI99 .and. ITS_A_NEW_MONTH() ) CALL EMISS_EPA_NEI + + ! Read NEI2005 (USA) emissions (adj32_015) + IF ( LNEI05 .and. ITS_A_NEW_MONTH() ) THEN +#if defined( GRID05x0666 ) + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO_05x0666 ! Use NEI05 anthro, global +#else + CALL EMISS_EPA_NEI ! Use NEI99 biofuel, nested + CALL EMISS_NEI2005_ANTHRO ! Use NEI05 anthro, global +#endif + ENDIF + + ! Read BRAVO (Mexico) emissions once per year + IF ( LBRAVO .and. ITS_A_NEW_YEAR() ) CALL EMISS_BRAVO + + ! Read EPA (Europe) emissions once per year (adj32_015) + IF ( LEMEP .and. ITS_A_NEW_YEAR() ) THEN +#if defined(GRID05x0666) + CALL EMISS_EMEP_05x0666 +#else + CALL EMISS_EMEP +#endif + ENDIF + + ! Read ICOADS ship emissions once per month !(cklee, 7/09/09) + IF ( LICOADSSHIP .and. ITS_A_NEW_MONTH() ) THEN + CALL EMISS_ICOADS_SHIP + ENDIF + + ! Emit H2/HD + CALL EMISS_H2_HD + + ENDIF + + !### Debug + IF ( LPRT ) CALL DEBUG_MSG ( '### DO_EMISSIONS: a EMISSIONS' ) + + ! Return to calling program + END SUBROUTINE DO_EMISSIONS + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE EMISSIONS_MOD +!EOC diff --git a/code/emmonot.f b/code/emmonot.f new file mode 100644 index 0000000..931de47 --- /dev/null +++ b/code/emmonot.f @@ -0,0 +1,77 @@ +C $Id: emmonot.f,v 1.1 2009/06/09 21:51:51 daven Exp $ + FUNCTION EMMONOT( IJLOOP, TMMP, XNUMOL ) +! +!****************************************************************************** +! Subroutine EMMONOT computes the BIOGENIC MONOTERPENE EMISSIONS for each +! grid box in units of [atoms C/box/step]. (yhw, bdf, bmy, 9/4/01, 11/26/01) +! +! Arguments as Input: +! ============================================================================ +! (1 ) IJLOOP (INTEGER ) : 1-D grid box index +! (2 ) TMMP (REAL*8 ) : Local air temperature (K) +! (3 ) XNUMOL (REAL*8 ) : Number of atoms C / kg C +! +! Important Common Block Variables: +! ============================================================================ +! (1 ) XYLAI (CMN_VEL ) : Leaf Area Index of land type for current MONTH +! (2 ) IJREG (CMN_VEL ) : Number of Olson land types per grid box +! (3 ) IJLAND+1 (CMN_VEL ) : Olson land type index +! (4 ) IJUSE (CMN_VEL ) : Olson land type fraction per box (in mils) +! (5 ) BASEMONOT (CMN_ISOP) : Baseline MONOTERPENE emissions [kg C/box/step] +! +! NOTES: +! (1 ) Now use F90 syntax. Use "D" exponents to force double precision. +! Updated comments, and mad cosmetic changes (bmy, 9/4/01) +! (2 ) Removed obsolete, commented-out code from 8/01 (bmy, 11/26/01) +!****************************************************************************** +! + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_VEL" ! XYLAI, IJREG, IJLAND, IJUSE +# include "CMN_MONOT" ! BASEMONOT + + ! Arguments + INTEGER, INTENT(IN) :: IJLOOP + REAL*8, INTENT(IN) :: TMMP, XNUMOL + + ! Local variables + INTEGER :: INVEG + REAL*8 :: EMMONOT + REAL*8, PARAMETER :: TS=303d0, BETA=0.09d0 + + !================================================================= + ! EMMONOT begins here! + !================================================================= + + ! Initialize + EMMONOT = 0d0 + + ! Loop over all Olson land types in this grid box + DO INVEG = 1, IJREG(IJLOOP) + + ! Compute monoterpene emissions at box IJLOOP in [kg C/box/step]. + ! Monoterpenes are now scaled to leaf area index XYLAI. Also + ! multiply by the fraction of grid box IJLOOP occupied + ! by this Olson land type. (bdf, bmy, 8/2/01) + EMMONOT = EMMONOT + + & ( BASEMONOT(IJLOOP,INVEG) * XYLAI(IJLOOP,INVEG) * + & DBLE( IJUSE(IJLOOP,INVEG) ) / 1000d0 ) + + ENDDO + + !================================================================= + ! Temperature correction from Guenther et al. (1995) + ! BETA is an empirical coefficient given by Guenther. (.09 K-1) + ! TS is leaf temperature at standard conditions, (303 K) + ! foliar density is accounted for in monotemis.table. + !================================================================= + + ! Temp-corrected MONOTERPENE emissions in [kg C/box/step] + EMMONOT = EMMONOT * EXP( BETA * ( TMMP - TS ) ) + + ! Convert MONOTERPENE emissions to [atoms C/box/step] + EMMONOT = EMMONOT * XNUMOL + + ! Return to calling program + END FUNCTION EMMONOT diff --git a/code/epa_nei_mod.f b/code/epa_nei_mod.f new file mode 100644 index 0000000..181fefa --- /dev/null +++ b/code/epa_nei_mod.f @@ -0,0 +1,2679 @@ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: epa_nei_mod +! +! !DESCRIPTION: ! Module EPA_NEI_MOD contains variables and routines to read +! the weekday/weekend emissions from the EPA/NEI99 emissions inventory. +!\\ +!\\ +! !INTERFACE: +! + MODULE EPA_NEI_MOD +! +! !USES: +! + IMPLICIT NONE + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: CLEANUP_EPA_NEI + PUBLIC :: EMISS_EPA_NEI + PUBLIC :: GET_USA_MASK + PUBLIC :: GET_EPA_ANTHRO + PUBLIC :: GET_EPA_BIOFUEL +! +! !PRIVATE MEMBER FUNCTIONS: +! + PRIVATE :: EMISS_EPA_NEI_AN + PRIVATE :: EMISS_EPA_NEI_BF + PRIVATE :: INIT_EPA_NEI + PRIVATE :: READ_USA_MASK + PRIVATE :: READ_USA_MASK_05x0666 + PRIVATE :: READ_EPA + PRIVATE :: READ_EPA_05x0666 + PRIVATE :: TOTAL_ANTHRO_Tg + PRIVATE :: TOTAL_BIOFUEL_Tg +! +! !REMARKS: +! When you use EPA/NEI99 emissions (LNEI99=T), then the routines in this +! module will read and process in the anthropogenic and biofuel emissions +! from the EPA/NEI99 inventory. +! . +! When you use the EPA/NEI05 emissions (LNEI99=F and LNEI05=T), then the +! routines in this module will read and process only the biofuel emissions +! from the EPA/NEI99 inventory. The EPA/NEI05 inventory only contains +! anthropogenic emissions, so we are constrained to use the EPA/NEI99 +! biofuel data. +! +! !REVISION HISTORY: +! (1 ) Prevent out of bounds errors in routines TOTAL_ANTHRO_TG and +! TOTAL_BIOFUEL_TG (bmy, 1/26/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 replace FMOL with TRACER_MW_KG (bmy, 10/25/05) +! (5 ) Now modified for IPCC future emissions (swu, bmy, 5/30/06) +! (6 ) Now use int'annual scalars (amv, 08/24/07) +! (7 ) Now can use ICARTT-based modifications from Hudman (phs, 1/26/09) +! (a) Hudman et al., 2007, J. Geophys. Res., 112, D12S05, +! doi:10.1029/2006JD007912 +! (b) Hudman et al., 2008, Geophys. Res. Lett., 35, L04801, +! doi:10.1029/2007GL032393 +! (8 ) Now can read 0.5 x 0.667 nested grid emissions (amv, bmy, 12/18/09) +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !PRIVATE TYPES: +! + ! USA Mask + REAL*8, ALLOCATABLE :: USA_MASK(:,:) + + ! Fossil fuel arrays -- weekday + REAL*4, ALLOCATABLE :: EPA_WD_AN_NOX(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_CO(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_ALK4(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_ACET(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_MEK(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_PRPE(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_C2H6(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_C3H8(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_CH2O(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_NH3(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_SO2(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_AN_SO4(:,:) + + ! Fossil fuel arrays -- weekend + REAL*4, ALLOCATABLE :: EPA_WE_AN_NOX(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_CO(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_ALK4(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_ACET(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_MEK(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_PRPE(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_C2H6(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_C3H8(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_CH2O(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_NH3(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_SO2(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_AN_SO4(:,:) + + ! Biofuel arrays -- weekday + REAL*4, ALLOCATABLE :: EPA_WD_BF_NOX(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_CO(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_ALK4(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_ACET(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_MEK(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_PRPE(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_C2H6(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_C3H8(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_CH2O(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_NH3(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_SO2(:,:) + REAL*4, ALLOCATABLE :: EPA_WD_BF_SO4(:,:) + + ! Biofuel arrays -- weekend + REAL*4, ALLOCATABLE :: EPA_WE_BF_NOX(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_CO(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_ALK4(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_ACET(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_MEK(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_PRPE(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_C2H6(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_C3H8(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_CH2O(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_NH3(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_SO2(:,:) + REAL*4, ALLOCATABLE :: EPA_WE_BF_SO4(:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS +!EOC +!------------------------------------------------------------------------------ +! Prior to 2/7/11: +! Preserve original code here (bmy, 2/7/11) +! +! SUBROUTINE EMISS_EPA_NEI +!! +!!****************************************************************************** +!! Subroutine EMISS_EPA_NEI reads all EPA emissions from disk at the start +!! of a new month. (rch, bmy, 11/10/04, 12/18/09) +!! +!! NOTES: +!! (1 ) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +!! (2 ) Modified for IPCC future emissions (swu, bmy, 5/30/06) +!! (3 ) Now can read 0.5 x 0.667 nested grid emissions (amv, bmy, 12/18/09) +!!****************************************************************************** +!! +! ! References to F90 modules +! USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D, GET_RES_EXT +! USE DIRECTORY_MOD, ONLY : DATA_DIR +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_ALK4ff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_C2H6ff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_C3H8ff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_CObf +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_COff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NH3an +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NH3bf +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxbf +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_PRPEff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2bf +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2ff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_TONEff +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_VOCbf +! USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_VOCff +! USE LOGICAL_MOD, ONLY : LFUTURE, LICARTT +! USE TIME_MOD, ONLY : EXPAND_DATE, GET_MONTH +! +!# include "CMN_SIZE" ! Size parameters +! +! ! Local variables +! LOGICAL, SAVE :: FIRST = .TRUE. +! INTEGER :: I, J, THISMONTH, YYYYMMDD +! REAL*8 :: ALK4ff, C2H6ff, C3H8ff, COff +! REAL*8 :: NH3an, NOxff, PRPEff, SO2ff +! REAL*8 :: TONEff, VOCff, CObf, NH3bf +! REAL*8 :: NOxbf, SO2bf, VOCbf +! CHARACTER(LEN=255) :: FILENAME +! +! !================================================================= +! ! EMISS_EPA_NEI begins here! +! !================================================================= +! +! ! First-time initialization +! IF ( FIRST ) THEN +! +! ! Allocate arrays +! CALL INIT_EPA_NEI +! +! ! Read mask over the USA +!#if defined(GRID05_0666) +! CALL READ_USA_MASK_05x0666 +!#else +! CALL READ_USA_MASK +!#endif +! +! ! Reset first-time flag +! FIRST = .FALSE. +! ENDIF +! +! ! Get the current month +! THISMONTH = GET_MONTH() +! +! ! Get date for 1999 emissions +! YYYYMMDD = 19990000 + ( THISMONTH * 100 ) + 01 +! +! ! Echo info +! WRITE( 6, '(a)' ) REPEAT( '=', 79 ) +! WRITE( 6, 100 ) +! 100 FORMAT( 'E P A / N E I E M I S S I O N S', +! & ' -- Baseline Year: 1999', / ) +! +! !================================================================= +! ! Read EPA weekday average anthropogenic emissions +! !================================================================= +! +! ! Weekday anthro file name +! IF ( LICARTT ) THEN +! +! FILENAME = TRIM( DATA_DIR ) // +! & 'EPA_NEI_200806/wkday_avg_an.YYYYMM.' // +! & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() +! ELSE +! FILENAME = TRIM( DATA_DIR ) // +! & 'EPA_NEI_200708/wkday_avg_an.YYYYMM.' // +! & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() +! ENDIF +! +! ! Replace date in filename +! CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) +! +! ! Read weekday data +!#if defined(GRID05x0666) +! CALL READ_EPA_05x0666( FILENAME, +! & EPA_WD_AN_NOX, EPA_WD_AN_CO, EPA_WD_AN_ALK4, +! & EPA_WD_AN_ACET, EPA_WD_AN_MEK, EPA_WD_AN_PRPE, +! & EPA_WD_AN_C3H8, EPA_WD_AN_CH2O, EPA_WD_AN_C2H6, +! & EPA_WD_AN_SO2, EPA_WD_AN_SO4, EPA_WD_AN_NH3, 0) +!#else +! CALL READ_EPA( FILENAME, +! & EPA_WD_AN_NOX, EPA_WD_AN_CO, EPA_WD_AN_ALK4, +! & EPA_WD_AN_ACET, EPA_WD_AN_MEK, EPA_WD_AN_PRPE, +! & EPA_WD_AN_C3H8, EPA_WD_AN_CH2O, EPA_WD_AN_C2H6, +! & EPA_WD_AN_SO2, EPA_WD_AN_SO4, EPA_WD_AN_NH3 ) +!#endif +! +! !================================================================= +! ! Read EPA weekend average anthropogenic emissions +! !================================================================= +! +! ! Weekday anthro file name +! IF ( LICARTT ) THEN +! +! FILENAME = TRIM( DATA_DIR ) // +! & 'EPA_NEI_200806/wkend_avg_an.YYYYMM.' // +! & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() +! ELSE +! FILENAME = TRIM( DATA_DIR ) // +! & 'EPA_NEI_200708/wkend_avg_an.YYYYMM.' // +! & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() +! ENDIF +! +! ! Replace date in filename +! CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) +! +! ! Read weekend data +!#if defined(GRID05x0666) +! CALL READ_EPA_05x0666( FILENAME, +! & EPA_WE_AN_NOX, EPA_WE_AN_CO, EPA_WE_AN_ALK4, +! & EPA_WE_AN_ACET, EPA_WE_AN_MEK, EPA_WE_AN_PRPE, +! & EPA_WE_AN_C3H8, EPA_WE_AN_CH2O, EPA_WE_AN_C2H6, +! & EPA_WE_AN_SO2, EPA_WE_AN_SO4, EPA_WE_AN_NH3, 0) +!#else +! CALL READ_EPA( FILENAME, +! & EPA_WE_AN_NOX, EPA_WE_AN_CO, EPA_WE_AN_ALK4, +! & EPA_WE_AN_ACET, EPA_WE_AN_MEK, EPA_WE_AN_PRPE, +! & EPA_WE_AN_C3H8, EPA_WE_AN_CH2O, EPA_WE_AN_C2H6, +! & EPA_WE_AN_SO2, EPA_WE_AN_SO4, EPA_WE_AN_NH3 ) +!#endif +! +! !================================================================= +! ! Read EPA weekday average biofuel emissions +! !================================================================= +! +! ! Weekday biofuel file name +! FILENAME = TRIM( DATA_DIR ) // +! & 'EPA_NEI_200411/wkday_avg_bf.YYYYMM.' // +! & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() +! +! ! Replace date in filename +! CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) +! +! ! Read weekday data +!#if defined(GRID05x0666) +! CALL READ_EPA_05x0666( FILENAME, +! & EPA_WD_BF_NOX, EPA_WD_BF_CO, EPA_WD_BF_ALK4, +! & EPA_WD_BF_ACET, EPA_WD_BF_MEK, EPA_WD_BF_PRPE, +! & EPA_WD_BF_C3H8, EPA_WD_BF_CH2O, EPA_WD_BF_C2H6, +! & EPA_WD_BF_SO2, EPA_WD_BF_SO4, EPA_WD_BF_NH3, 1) +!#else +! CALL READ_EPA( FILENAME, +! & EPA_WD_BF_NOX, EPA_WD_BF_CO, EPA_WD_BF_ALK4, +! & EPA_WD_BF_ACET, EPA_WD_BF_MEK, EPA_WD_BF_PRPE, +! & EPA_WD_BF_C3H8, EPA_WD_BF_CH2O, EPA_WD_BF_C2H6, +! & EPA_WD_BF_SO2, EPA_WD_BF_SO4, EPA_WD_BF_NH3 ) +!#endif +! +! !================================================================= +! ! Read EPA weekend average biofuel emissions +! !================================================================= +! +! ! Weekend biofuel file name +! FILENAME = TRIM( DATA_DIR ) // +! & 'EPA_NEI_200411/wkend_avg_bf.YYYYMM.' // +! & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() +! +! ! Replace date in filename +! CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) +! +! ! Read weekend data +!#if defined(GRID05x0666) +! CALL READ_EPA_05x0666( FILENAME, +! & EPA_WE_BF_NOX, EPA_WE_BF_CO, EPA_WE_BF_ALK4, +! & EPA_WE_BF_ACET, EPA_WE_BF_MEK, EPA_WE_BF_PRPE, +! & EPA_WE_BF_C3H8, EPA_WE_BF_CH2O, EPA_WE_BF_C2H6, +! & EPA_WE_BF_SO2, EPA_WE_BF_SO4, EPA_WE_BF_NH3, 1) +!#else +! CALL READ_EPA( FILENAME, +! & EPA_WE_BF_NOX, EPA_WE_BF_CO, EPA_WE_BF_ALK4, +! & EPA_WE_BF_ACET, EPA_WE_BF_MEK, EPA_WE_BF_PRPE, +! & EPA_WE_BF_C3H8, EPA_WE_BF_CH2O, EPA_WE_BF_C2H6, +! & EPA_WE_BF_SO2, EPA_WE_BF_SO4, EPA_WE_BF_NH3 ) +!#endif +! +! !================================================================= +! ! Apply USA Mask (keep emissions over US, zero elsewhere) +! !================================================================= +! +!!$OMP PARALLEL DO +!!$OMP+DEFAULT( SHARED ) +!!$OMP+PRIVATE( I, J, ALK4ff, C2H6ff, C3H8ff, COff ) +!!$OMP+PRIVATE( NH3an, NOxff, PRPEff, SO2ff, TONEff, VOCff ) +!!$OMP+PRIVATE( CObf, NH3bf, NOxbf, SO2bf, VOCbf ) +!!$OMP+SCHEDULE( DYNAMIC ) +! DO J = 1, JJPAR +! DO I = 1, IIPAR +! +! ! Weekday avg anthro +! EPA_WD_AN_NOX (I,J) = EPA_WD_AN_NOX (I,J) * USA_MASK(I,J) +! EPA_WD_AN_CO (I,J) = EPA_WD_AN_CO (I,J) * USA_MASK(I,J) +! EPA_WD_AN_ALK4(I,J) = EPA_WD_AN_ALK4(I,J) * USA_MASK(I,J) +! EPA_WD_AN_ACET(I,J) = EPA_WD_AN_ACET(I,J) * USA_MASK(I,J) +! EPA_WD_AN_MEK (I,J) = EPA_WD_AN_MEK (I,J) * USA_MASK(I,J) +! EPA_WD_AN_PRPE(I,J) = EPA_WD_AN_PRPE(I,J) * USA_MASK(I,J) +! EPA_WD_AN_C3H8(I,J) = EPA_WD_AN_C3H8(I,J) * USA_MASK(I,J) +! EPA_WD_AN_CH2O(I,J) = EPA_WD_AN_CH2O(I,J) * USA_MASK(I,J) +! EPA_WD_AN_C2H6(I,J) = EPA_WD_AN_C2H6(I,J) * USA_MASK(I,J) +! EPA_WD_AN_SO2 (I,J) = EPA_WD_AN_SO2 (I,J) * USA_MASK(I,J) +! EPA_WD_AN_SO4 (I,J) = EPA_WD_AN_SO4 (I,J) * USA_MASK(I,J) +! EPA_WD_AN_NH3 (I,J) = EPA_WD_AN_NH3 (I,J) * USA_MASK(I,J) +! +! ! Weekend avg anthro +! EPA_WE_AN_NOX (I,J) = EPA_WE_AN_NOX (I,J) * USA_MASK(I,J) +! EPA_WE_AN_CO (I,J) = EPA_WE_AN_CO (I,J) * USA_MASK(I,J) +! EPA_WE_AN_ALK4(I,J) = EPA_WE_AN_ALK4(I,J) * USA_MASK(I,J) +! EPA_WE_AN_ACET(I,J) = EPA_WE_AN_ACET(I,J) * USA_MASK(I,J) +! EPA_WE_AN_MEK (I,J) = EPA_WE_AN_MEK (I,J) * USA_MASK(I,J) +! EPA_WE_AN_PRPE(I,J) = EPA_WE_AN_PRPE(I,J) * USA_MASK(I,J) +! EPA_WE_AN_C3H8(I,J) = EPA_WE_AN_C3H8(I,J) * USA_MASK(I,J) +! EPA_WE_AN_CH2O(I,J) = EPA_WE_AN_CH2O(I,J) * USA_MASK(I,J) +! EPA_WE_AN_C2H6(I,J) = EPA_WE_AN_C2H6(I,J) * USA_MASK(I,J) +! EPA_WE_AN_SO2 (I,J) = EPA_WE_AN_SO2 (I,J) * USA_MASK(I,J) +! EPA_WE_AN_SO4 (I,J) = EPA_WE_AN_SO4 (I,J) * USA_MASK(I,J) +! EPA_WE_AN_NH3 (I,J) = EPA_WE_AN_NH3 (I,J) * USA_MASK(I,J) +! +! ! Weekday avg biofuel +! EPA_WD_BF_NOX (I,J) = EPA_WD_BF_NOX (I,J) * USA_MASK(I,J) +! EPA_WD_BF_CO (I,J) = EPA_WD_BF_CO (I,J) * USA_MASK(I,J) +! EPA_WD_BF_ALK4(I,J) = EPA_WD_BF_ALK4(I,J) * USA_MASK(I,J) +! EPA_WD_BF_ACET(I,J) = EPA_WD_BF_ACET(I,J) * USA_MASK(I,J) +! EPA_WD_BF_MEK (I,J) = EPA_WD_BF_MEK (I,J) * USA_MASK(I,J) +! EPA_WD_BF_PRPE(I,J) = EPA_WD_BF_PRPE(I,J) * USA_MASK(I,J) +! EPA_WD_BF_C3H8(I,J) = EPA_WD_BF_C3H8(I,J) * USA_MASK(I,J) +! EPA_WD_BF_CH2O(I,J) = EPA_WD_BF_CH2O(I,J) * USA_MASK(I,J) +! EPA_WD_BF_C2H6(I,J) = EPA_WD_BF_C2H6(I,J) * USA_MASK(I,J) +! EPA_WD_BF_SO2 (I,J) = EPA_WD_BF_SO2 (I,J) * USA_MASK(I,J) +! EPA_WD_BF_SO4 (I,J) = EPA_WD_BF_SO4 (I,J) * USA_MASK(I,J) +! EPA_WD_BF_NH3 (I,J) = EPA_WD_BF_NH3 (I,J) * USA_MASK(I,J) +! +! ! Weekend avg biofuel +! EPA_WE_BF_NOX (I,J) = EPA_WE_BF_NOX (I,J) * USA_MASK(I,J) +! EPA_WE_BF_CO (I,J) = EPA_WE_BF_CO (I,J) * USA_MASK(I,J) +! EPA_WE_BF_ALK4(I,J) = EPA_WE_BF_ALK4(I,J) * USA_MASK(I,J) +! EPA_WE_BF_ACET(I,J) = EPA_WE_BF_ACET(I,J) * USA_MASK(I,J) +! EPA_WE_BF_MEK (I,J) = EPA_WE_BF_MEK (I,J) * USA_MASK(I,J) +! EPA_WE_BF_PRPE(I,J) = EPA_WE_BF_PRPE(I,J) * USA_MASK(I,J) +! EPA_WE_BF_C3H8(I,J) = EPA_WE_BF_C3H8(I,J) * USA_MASK(I,J) +! EPA_WE_BF_CH2O(I,J) = EPA_WE_BF_CH2O(I,J) * USA_MASK(I,J) +! EPA_WE_BF_C2H6(I,J) = EPA_WE_BF_C2H6(I,J) * USA_MASK(I,J) +! EPA_WE_BF_SO2 (I,J) = EPA_WE_BF_SO2 (I,J) * USA_MASK(I,J) +! EPA_WE_BF_SO4 (I,J) = EPA_WE_BF_SO4 (I,J) * USA_MASK(I,J) +! EPA_WE_BF_NH3 (I,J) = EPA_WE_BF_NH3 (I,J) * USA_MASK(I,J) +! +! !---------------------------------------------- +! ! Compute IPCC future emissions (if necessary) +! !---------------------------------------------- +! IF ( LFUTURE .and. USA_MASK(I,J) > 0d0 ) THEN +! +! ! Future anthro scale factors +! ALK4ff = GET_FUTURE_SCALE_ALK4ff( I, J ) +! C2H6ff = GET_FUTURE_SCALE_C2H6ff( I, J ) +! C3H8ff = GET_FUTURE_SCALE_C3H8ff( I, J ) +! COff = GET_FUTURE_SCALE_COff( I, J ) +! NH3an = GET_FUTURE_SCALE_NH3an( I, J ) +! NOxff = GET_FUTURE_SCALE_NOxff( I, J ) +! PRPEff = GET_FUTURE_SCALE_PRPEff( I, J ) +! TONEff = GET_FUTURE_SCALE_TONEff( I, J ) +! SO2ff = GET_FUTURE_SCALE_SO2ff( I, J ) +! VOCff = GET_FUTURE_SCALE_VOCff( I, J ) +! +! ! Future biofuel scale factors +! CObf = GET_FUTURE_SCALE_CObf( I, J ) +! NH3bf = GET_FUTURE_SCALE_NH3bf( I, J ) +! NOxbf = GET_FUTURE_SCALE_NOXbf( I, J ) +! SO2bf = GET_FUTURE_SCALE_SO2bf( I, J ) +! VOCbf = GET_FUTURE_SCALE_VOCbf( I, J ) +! +! ! Future weekday avg anthro +! EPA_WD_AN_NOX (I,J) = EPA_WD_AN_NOX (I,J) * NOxff +! EPA_WD_AN_CO (I,J) = EPA_WD_AN_CO (I,J) * COff +! EPA_WD_AN_ALK4(I,J) = EPA_WD_AN_ALK4(I,J) * ALK4ff +! EPA_WD_AN_ACET(I,J) = EPA_WD_AN_ACET(I,J) * TONEff +! EPA_WD_AN_MEK (I,J) = EPA_WD_AN_MEK (I,J) * TONEff +! EPA_WD_AN_PRPE(I,J) = EPA_WD_AN_PRPE(I,J) * PRPEff +! EPA_WD_AN_C3H8(I,J) = EPA_WD_AN_C3H8(I,J) * C3H8ff +! EPA_WD_AN_CH2O(I,J) = EPA_WD_AN_CH2O(I,J) * VOCff +! EPA_WD_AN_C2H6(I,J) = EPA_WD_AN_C2H6(I,J) * C2H6ff +! EPA_WD_AN_SO2 (I,J) = EPA_WD_AN_SO2 (I,J) * SO2ff +! EPA_WD_AN_SO4 (I,J) = EPA_WD_AN_SO4 (I,J) * SO2ff +! EPA_WD_AN_NH3 (I,J) = EPA_WD_AN_NH3 (I,J) * NH3an +! +! ! Weekend avg anthro +! EPA_WE_AN_NOX (I,J) = EPA_WE_AN_NOX (I,J) * NOxff +! EPA_WE_AN_CO (I,J) = EPA_WE_AN_CO (I,J) * COff +! EPA_WE_AN_ALK4(I,J) = EPA_WE_AN_ALK4(I,J) * ALK4ff +! EPA_WE_AN_ACET(I,J) = EPA_WE_AN_ACET(I,J) * TONEff +! EPA_WE_AN_MEK (I,J) = EPA_WE_AN_MEK (I,J) * TONEff +! EPA_WE_AN_PRPE(I,J) = EPA_WE_AN_PRPE(I,J) * PRPEff +! EPA_WE_AN_C3H8(I,J) = EPA_WE_AN_C3H8(I,J) * C3H8ff +! EPA_WE_AN_CH2O(I,J) = EPA_WE_AN_CH2O(I,J) * VOCff +! EPA_WE_AN_C2H6(I,J) = EPA_WE_AN_C2H6(I,J) * C2H6ff +! EPA_WE_AN_SO2 (I,J) = EPA_WE_AN_SO2 (I,J) * SO2ff +! EPA_WE_AN_SO4 (I,J) = EPA_WE_AN_SO4 (I,J) * SO2ff +! EPA_WE_AN_NH3 (I,J) = EPA_WE_AN_NH3 (I,J) * NH3an +! +! ! Weekday avg biofuel +! EPA_WD_BF_NOX (I,J) = EPA_WD_BF_NOX (I,J) * NOxbf +! EPA_WD_BF_CO (I,J) = EPA_WD_BF_CO (I,J) * CObf +! EPA_WD_BF_ALK4(I,J) = EPA_WD_BF_ALK4(I,J) * VOCbf +! EPA_WD_BF_ACET(I,J) = EPA_WD_BF_ACET(I,J) * VOCbf +! EPA_WD_BF_MEK (I,J) = EPA_WD_BF_MEK (I,J) * VOCbf +! EPA_WD_BF_PRPE(I,J) = EPA_WD_BF_PRPE(I,J) * VOCbf +! EPA_WD_BF_C3H8(I,J) = EPA_WD_BF_C3H8(I,J) * VOCbf +! EPA_WD_BF_CH2O(I,J) = EPA_WD_BF_CH2O(I,J) * VOCbf +! EPA_WD_BF_C2H6(I,J) = EPA_WD_BF_C2H6(I,J) * VOCbf +! EPA_WD_BF_SO2 (I,J) = EPA_WD_BF_SO2 (I,J) * SO2bf +! EPA_WD_BF_SO4 (I,J) = EPA_WD_BF_SO4 (I,J) * SO2bf +! EPA_WD_BF_NH3 (I,J) = EPA_WD_BF_NH3 (I,J) * NH3bf +! +! ! Weekend avg biofuel +! EPA_WE_BF_NOX (I,J) = EPA_WE_BF_NOX (I,J) * NOxbf +! EPA_WE_BF_CO (I,J) = EPA_WE_BF_CO (I,J) * CObf +! EPA_WE_BF_ALK4(I,J) = EPA_WE_BF_ALK4(I,J) * VOCbf +! EPA_WE_BF_ACET(I,J) = EPA_WE_BF_ACET(I,J) * VOCbf +! EPA_WE_BF_MEK (I,J) = EPA_WE_BF_MEK (I,J) * VOCbf +! EPA_WE_BF_PRPE(I,J) = EPA_WE_BF_PRPE(I,J) * VOCbf +! EPA_WE_BF_C3H8(I,J) = EPA_WE_BF_C3H8(I,J) * VOCbf +! EPA_WE_BF_CH2O(I,J) = EPA_WE_BF_CH2O(I,J) * VOCbf +! EPA_WE_BF_C2H6(I,J) = EPA_WE_BF_C2H6(I,J) * VOCbf +! EPA_WE_BF_SO2 (I,J) = EPA_WE_BF_SO2 (I,J) * SO2bf +! EPA_WE_BF_SO4 (I,J) = EPA_WE_BF_SO4 (I,J) * SO2bf +! EPA_WE_BF_NH3 (I,J) = EPA_WE_BF_NH3 (I,J) * NH3bf +! ENDIF +! ENDDO +! ENDDO +!!$OMP END PARALLEL DO +! +! ! Print totals to the log file +! CALL TOTAL_ANTHRO_TG( THISMONTH ) +! CALL TOTAL_BIOFUEL_TG( THISMONTH ) +! +! ! Fancy output +! WRITE( 6, '(a)' ) REPEAT( '=', 79 ) +! +! ! Return to calling program +! END SUBROUTINE EMISS_EPA_NEI +! +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emiss_epa_nei +! +! !DESCRIPTION: Subroutine EMISS\_EPA\_NEI reads all EPA emissions from disk +! at the start of a new month. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_EPA_NEI +! +! !USES: +! + USE LOGICAL_MOD, ONLY : LNEI05 + USE LOGICAL_MOD, ONLY : LNEI99 +! +! !REMARKS: +! Read EPA/NEI99 anthro + EPA/NEI99 biofuel if LNEI99=T, or +! Read EPA/NEI05 anthro + EPA/NEI99 biofuel if LNEI99=F but LNEI05=T +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! 07 Feb 2011 - R. Yantosca - Now reads anthro & biofuel emissions separately +! 7 Feb 2011 - R. Yantosca - Now reads biofuel only when LNEI05=T +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + LOGICAL, SAVE :: FIRST = .TRUE. + + !================================================================= + ! First-time initialization + !================================================================= + IF ( FIRST ) THEN + + ! Allocate arrays + CALL INIT_EPA_NEI + +#if defined( GRID05_0666 ) + ! Read mask over the USA, nested-grid resolution + CALL READ_USA_MASK_05x0666 +#else + ! Read mask over the USA, global resolution + CALL READ_USA_MASK +#endif + + ! Reset first-time flag + FIRST = .FALSE. + ENDIF + + !================================================================= + ! Read data + !================================================================= + + ! Echo info + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 100 ) + 100 FORMAT( 'E P A / N E I 9 9 E M I S S I O N S', / ) + + IF ( LNEI99 ) THEN + + ! If we are using EPA/NEI99, then we will read both the anthro + ! and biofuel emissions data from disk for each month. + WRITE( 6, 120 ) + CALL EMISS_EPA_NEI_AN + CALL EMISS_EPA_NEI_BF + + ELSE + + ! If we are not using EPA/NEI99, then check if we are using + ! EPA/NEI05. The EPA/NEI05 inventory only has anthro emissions. + ! In this case, we must read the EPA/NEI99 biofuel emissions, since + ! these data are better defined over the USA than the "default" + ! biomass data from Yevich & Logan 2003. + IF ( LNEI05 ) THEN + WRITE( 6, 130 ) + CALL EMISS_EPA_NEI_BF + ENDIF + + ENDIF + + ! Echo info + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! FORMATs + 120 FORMAT( '%%% Using EPA/NEI99 anthro + EPA/NEI99 biofuel %%%', / ) + 130 FORMAT( '%%% Using EPA/NEI05 anthro + EPA/NEI99 biofuel %%%', / ) + + END SUBROUTINE EMISS_EPA_NEI +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emiss_epa_nei_an +! +! !DESCRIPTION: Subroutine EMISS\_EPA\_NEI\_AN reads only the EPA/NEI99 +! anthropogenic emissions from disk at the start of a new month. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_EPA_NEI_AN +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_ALK4ff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_C2H6ff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_C3H8ff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_COff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NH3an + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_PRPEff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2ff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_TONEff + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_VOCff + USE LOGICAL_MOD, ONLY : LFUTURE + USE LOGICAL_MOD, ONLY : LICARTT + USE TIME_MOD, ONLY : EXPAND_DATE + USE TIME_MOD, ONLY : GET_MONTH + +# include "CMN_SIZE" ! Size parameters +! +! !REMARKS: +! Split off from EMISS_EPA_NEI. +! +! !REVISION HISTORY: +! (1 ) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +! (2 ) Modified for IPCC future emissions (swu, bmy, 5/30/06) +! (3 ) Now can read 0.5 x 0.667 nested grid emissions (amv, bmy, 12/18/09) +! 07 Feb 2011 - R. Yantosca - Now only read anthro emissions. +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J, THISMONTH, YYYYMMDD + REAL*8 :: ALK4ff, C2H6ff, C3H8ff, COff + REAL*8 :: NH3an, NOxff, PRPEff, SO2ff + REAL*8 :: TONEff, VOCff + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! EMISS_EPA_NEI_AN begins here! + !================================================================= + + ! Get the current month + THISMONTH = GET_MONTH() + + ! Get date for 1999 emissions + YYYYMMDD = 19990000 + ( THISMONTH * 100 ) + 01 + + !================================================================= + ! Read EPA weekday average anthropogenic emissions + !================================================================= + + ! Weekday anthro file name + IF ( LICARTT ) THEN + FILENAME = TRIM( DATA_DIR ) // + & 'EPA_NEI_200806/wkday_avg_an.YYYYMM.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + ELSE + FILENAME = TRIM( DATA_DIR ) // + & 'EPA_NEI_200708/wkday_avg_an.YYYYMM.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + ENDIF + + ! Replace date in filename + CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) + +#if defined( GRID05x0666 ) + + ! Read weekday data, nested grids + CALL READ_EPA_05x0666( FILENAME, + & EPA_WD_AN_NOX, EPA_WD_AN_CO, EPA_WD_AN_ALK4, + & EPA_WD_AN_ACET, EPA_WD_AN_MEK, EPA_WD_AN_PRPE, + & EPA_WD_AN_C3H8, EPA_WD_AN_CH2O, EPA_WD_AN_C2H6, + & EPA_WD_AN_SO2, EPA_WD_AN_SO4, EPA_WD_AN_NH3, 0) + +#else + + ! Read weekday data, global grids + CALL READ_EPA( FILENAME, + & EPA_WD_AN_NOX, EPA_WD_AN_CO, EPA_WD_AN_ALK4, + & EPA_WD_AN_ACET, EPA_WD_AN_MEK, EPA_WD_AN_PRPE, + & EPA_WD_AN_C3H8, EPA_WD_AN_CH2O, EPA_WD_AN_C2H6, + & EPA_WD_AN_SO2, EPA_WD_AN_SO4, EPA_WD_AN_NH3 ) + +#endif + + !================================================================= + ! Read EPA weekend average anthropogenic emissions + !================================================================= + + ! Weekday anthro file name + IF ( LICARTT ) THEN + FILENAME = TRIM( DATA_DIR ) // + & 'EPA_NEI_200806/wkend_avg_an.YYYYMM.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + ELSE + FILENAME = TRIM( DATA_DIR ) // + & 'EPA_NEI_200708/wkend_avg_an.YYYYMM.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + ENDIF + + ! Replace date in filename + CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) + +#if defined( GRID05x0666 ) + + ! Read weekend data, nested grid + CALL READ_EPA_05x0666( FILENAME, + & EPA_WE_AN_NOX, EPA_WE_AN_CO, EPA_WE_AN_ALK4, + & EPA_WE_AN_ACET, EPA_WE_AN_MEK, EPA_WE_AN_PRPE, + & EPA_WE_AN_C3H8, EPA_WE_AN_CH2O, EPA_WE_AN_C2H6, + & EPA_WE_AN_SO2, EPA_WE_AN_SO4, EPA_WE_AN_NH3, 0) + +#else + + ! Read weekend data, global grids + CALL READ_EPA( FILENAME, + & EPA_WE_AN_NOX, EPA_WE_AN_CO, EPA_WE_AN_ALK4, + & EPA_WE_AN_ACET, EPA_WE_AN_MEK, EPA_WE_AN_PRPE, + & EPA_WE_AN_C3H8, EPA_WE_AN_CH2O, EPA_WE_AN_C2H6, + & EPA_WE_AN_SO2, EPA_WE_AN_SO4, EPA_WE_AN_NH3 ) + +#endif + + !================================================================= + ! Apply USA Mask (keep emissions over US, zero elsewhere) + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, ALK4ff, C2H6ff, C3H8ff, COff ) +!$OMP+PRIVATE( NH3an, NOxff, PRPEff, SO2ff, TONEff, VOCff ) +!$OMP+SCHEDULE( DYNAMIC ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Weekday avg anthro + EPA_WD_AN_NOX (I,J) = EPA_WD_AN_NOX (I,J) * USA_MASK(I,J) + EPA_WD_AN_CO (I,J) = EPA_WD_AN_CO (I,J) * USA_MASK(I,J) + EPA_WD_AN_ALK4(I,J) = EPA_WD_AN_ALK4(I,J) * USA_MASK(I,J) + EPA_WD_AN_ACET(I,J) = EPA_WD_AN_ACET(I,J) * USA_MASK(I,J) + EPA_WD_AN_MEK (I,J) = EPA_WD_AN_MEK (I,J) * USA_MASK(I,J) + EPA_WD_AN_PRPE(I,J) = EPA_WD_AN_PRPE(I,J) * USA_MASK(I,J) + EPA_WD_AN_C3H8(I,J) = EPA_WD_AN_C3H8(I,J) * USA_MASK(I,J) + EPA_WD_AN_CH2O(I,J) = EPA_WD_AN_CH2O(I,J) * USA_MASK(I,J) + EPA_WD_AN_C2H6(I,J) = EPA_WD_AN_C2H6(I,J) * USA_MASK(I,J) + EPA_WD_AN_SO2 (I,J) = EPA_WD_AN_SO2 (I,J) * USA_MASK(I,J) + EPA_WD_AN_SO4 (I,J) = EPA_WD_AN_SO4 (I,J) * USA_MASK(I,J) + EPA_WD_AN_NH3 (I,J) = EPA_WD_AN_NH3 (I,J) * USA_MASK(I,J) + + ! Weekend avg anthro + EPA_WE_AN_NOX (I,J) = EPA_WE_AN_NOX (I,J) * USA_MASK(I,J) + EPA_WE_AN_CO (I,J) = EPA_WE_AN_CO (I,J) * USA_MASK(I,J) + EPA_WE_AN_ALK4(I,J) = EPA_WE_AN_ALK4(I,J) * USA_MASK(I,J) + EPA_WE_AN_ACET(I,J) = EPA_WE_AN_ACET(I,J) * USA_MASK(I,J) + EPA_WE_AN_MEK (I,J) = EPA_WE_AN_MEK (I,J) * USA_MASK(I,J) + EPA_WE_AN_PRPE(I,J) = EPA_WE_AN_PRPE(I,J) * USA_MASK(I,J) + EPA_WE_AN_C3H8(I,J) = EPA_WE_AN_C3H8(I,J) * USA_MASK(I,J) + EPA_WE_AN_CH2O(I,J) = EPA_WE_AN_CH2O(I,J) * USA_MASK(I,J) + EPA_WE_AN_C2H6(I,J) = EPA_WE_AN_C2H6(I,J) * USA_MASK(I,J) + EPA_WE_AN_SO2 (I,J) = EPA_WE_AN_SO2 (I,J) * USA_MASK(I,J) + EPA_WE_AN_SO4 (I,J) = EPA_WE_AN_SO4 (I,J) * USA_MASK(I,J) + EPA_WE_AN_NH3 (I,J) = EPA_WE_AN_NH3 (I,J) * USA_MASK(I,J) + + !---------------------------------------------- + ! Compute IPCC future emissions (if necessary) + !---------------------------------------------- + IF ( LFUTURE .and. USA_MASK(I,J) > 0d0 ) THEN + + ! Future anthro scale factors + ALK4ff = GET_FUTURE_SCALE_ALK4ff( I, J ) + C2H6ff = GET_FUTURE_SCALE_C2H6ff( I, J ) + C3H8ff = GET_FUTURE_SCALE_C3H8ff( I, J ) + COff = GET_FUTURE_SCALE_COff( I, J ) + NH3an = GET_FUTURE_SCALE_NH3an( I, J ) + NOxff = GET_FUTURE_SCALE_NOxff( I, J ) + PRPEff = GET_FUTURE_SCALE_PRPEff( I, J ) + TONEff = GET_FUTURE_SCALE_TONEff( I, J ) + SO2ff = GET_FUTURE_SCALE_SO2ff( I, J ) + VOCff = GET_FUTURE_SCALE_VOCff( I, J ) + + ! Future weekday avg anthro + EPA_WD_AN_NOX (I,J) = EPA_WD_AN_NOX (I,J) * NOxff + EPA_WD_AN_CO (I,J) = EPA_WD_AN_CO (I,J) * COff + EPA_WD_AN_ALK4(I,J) = EPA_WD_AN_ALK4(I,J) * ALK4ff + EPA_WD_AN_ACET(I,J) = EPA_WD_AN_ACET(I,J) * TONEff + EPA_WD_AN_MEK (I,J) = EPA_WD_AN_MEK (I,J) * TONEff + EPA_WD_AN_PRPE(I,J) = EPA_WD_AN_PRPE(I,J) * PRPEff + EPA_WD_AN_C3H8(I,J) = EPA_WD_AN_C3H8(I,J) * C3H8ff + EPA_WD_AN_CH2O(I,J) = EPA_WD_AN_CH2O(I,J) * VOCff + EPA_WD_AN_C2H6(I,J) = EPA_WD_AN_C2H6(I,J) * C2H6ff + EPA_WD_AN_SO2 (I,J) = EPA_WD_AN_SO2 (I,J) * SO2ff + EPA_WD_AN_SO4 (I,J) = EPA_WD_AN_SO4 (I,J) * SO2ff + EPA_WD_AN_NH3 (I,J) = EPA_WD_AN_NH3 (I,J) * NH3an + + ! Weekend avg anthro + EPA_WE_AN_NOX (I,J) = EPA_WE_AN_NOX (I,J) * NOxff + EPA_WE_AN_CO (I,J) = EPA_WE_AN_CO (I,J) * COff + EPA_WE_AN_ALK4(I,J) = EPA_WE_AN_ALK4(I,J) * ALK4ff + EPA_WE_AN_ACET(I,J) = EPA_WE_AN_ACET(I,J) * TONEff + EPA_WE_AN_MEK (I,J) = EPA_WE_AN_MEK (I,J) * TONEff + EPA_WE_AN_PRPE(I,J) = EPA_WE_AN_PRPE(I,J) * PRPEff + EPA_WE_AN_C3H8(I,J) = EPA_WE_AN_C3H8(I,J) * C3H8ff + EPA_WE_AN_CH2O(I,J) = EPA_WE_AN_CH2O(I,J) * VOCff + EPA_WE_AN_C2H6(I,J) = EPA_WE_AN_C2H6(I,J) * C2H6ff + EPA_WE_AN_SO2 (I,J) = EPA_WE_AN_SO2 (I,J) * SO2ff + EPA_WE_AN_SO4 (I,J) = EPA_WE_AN_SO4 (I,J) * SO2ff + EPA_WE_AN_NH3 (I,J) = EPA_WE_AN_NH3 (I,J) * NH3an + + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Print totals to the log file + CALL TOTAL_ANTHRO_TG( THISMONTH ) + + END SUBROUTINE EMISS_EPA_NEI_AN +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: emiss_epa_nei_bf +! +! !DESCRIPTION: Subroutine EMISS\_EPA\_NEI\_BF reads only the EPA/NEI99 +! biofuel emissions from disk at the start of a new month. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE EMISS_EPA_NEI_BF +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_CObf + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NH3bf + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxbf + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2bf + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_VOCbf + USE LOGICAL_MOD, ONLY : LFUTURE + USE LOGICAL_MOD, ONLY : LICARTT + USE TIME_MOD, ONLY : EXPAND_DATE + USE TIME_MOD, ONLY : GET_MONTH + +# include "CMN_SIZE" ! Size parameters + +! +! !REMARKS: +! Split off from EMISS_EPA_NEI. +! +! !REVISION HISTORY: +! (1 ) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +! (2 ) Modified for IPCC future emissions (swu, bmy, 5/30/06) +! (3 ) Now can read 0.5 x 0.667 nested grid emissions (amv, bmy, 12/18/09) +! 07 Feb 2011 - R. Yantosca - Now only read biofuel emissions +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J, THISMONTH, YYYYMMDD + REAL*8 :: CObf, NH3bf, NOxbf, SO2bf, VOCbf + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! EMISS_EPA_NEI_BF begins here! + !================================================================= + + ! Get the current month + THISMONTH = GET_MONTH() + + ! Get date for 1999 emissions + YYYYMMDD = 19990000 + ( THISMONTH * 100 ) + 01 + + !================================================================= + ! Read EPA weekday average biofuel emissions + !================================================================= + + ! Weekday biofuel file name + FILENAME = TRIM( DATA_DIR ) // + & 'EPA_NEI_200411/wkday_avg_bf.YYYYMM.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! Replace date in filename + CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) + +#if defined( GRID05x0666 ) + + ! Read weekday data, nested grids + CALL READ_EPA_05x0666( FILENAME, + & EPA_WD_BF_NOX, EPA_WD_BF_CO, EPA_WD_BF_ALK4, + & EPA_WD_BF_ACET, EPA_WD_BF_MEK, EPA_WD_BF_PRPE, + & EPA_WD_BF_C3H8, EPA_WD_BF_CH2O, EPA_WD_BF_C2H6, + & EPA_WD_BF_SO2, EPA_WD_BF_SO4, EPA_WD_BF_NH3, 1) + +#else + + ! Read weekday data, global grids + CALL READ_EPA( FILENAME, + & EPA_WD_BF_NOX, EPA_WD_BF_CO, EPA_WD_BF_ALK4, + & EPA_WD_BF_ACET, EPA_WD_BF_MEK, EPA_WD_BF_PRPE, + & EPA_WD_BF_C3H8, EPA_WD_BF_CH2O, EPA_WD_BF_C2H6, + & EPA_WD_BF_SO2, EPA_WD_BF_SO4, EPA_WD_BF_NH3 ) + +#endif + + !================================================================= + ! Read EPA weekend average biofuel emissions + !================================================================= + + ! Weekend biofuel file name + FILENAME = TRIM( DATA_DIR ) // + & 'EPA_NEI_200411/wkend_avg_bf.YYYYMM.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! Replace date in filename + CALL EXPAND_DATE( FILENAME, YYYYMMDD, 000000 ) + +#if defined( GRID05x0666 ) + + ! Read weekend data, nested-grids + CALL READ_EPA_05x0666( FILENAME, + & EPA_WE_BF_NOX, EPA_WE_BF_CO, EPA_WE_BF_ALK4, + & EPA_WE_BF_ACET, EPA_WE_BF_MEK, EPA_WE_BF_PRPE, + & EPA_WE_BF_C3H8, EPA_WE_BF_CH2O, EPA_WE_BF_C2H6, + & EPA_WE_BF_SO2, EPA_WE_BF_SO4, EPA_WE_BF_NH3, 1 ) + +#else + + ! Read weekend data, global grids + CALL READ_EPA( FILENAME, + & EPA_WE_BF_NOX, EPA_WE_BF_CO, EPA_WE_BF_ALK4, + & EPA_WE_BF_ACET, EPA_WE_BF_MEK, EPA_WE_BF_PRPE, + & EPA_WE_BF_C3H8, EPA_WE_BF_CH2O, EPA_WE_BF_C2H6, + & EPA_WE_BF_SO2, EPA_WE_BF_SO4, EPA_WE_BF_NH3 ) + +#endif + + !================================================================= + ! Apply USA Mask (keep emissions over US, zero elsewhere) + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, CObf, NH3bf, NOxbf, SO2bf, VOCbf ) +!$OMP+SCHEDULE( DYNAMIC ) + DO J = 1, JJPAR + DO I = 1, IIPAR + + ! Weekday avg biofuel + EPA_WD_BF_NOX (I,J) = EPA_WD_BF_NOX (I,J) * USA_MASK(I,J) + EPA_WD_BF_CO (I,J) = EPA_WD_BF_CO (I,J) * USA_MASK(I,J) + EPA_WD_BF_ALK4(I,J) = EPA_WD_BF_ALK4(I,J) * USA_MASK(I,J) + EPA_WD_BF_ACET(I,J) = EPA_WD_BF_ACET(I,J) * USA_MASK(I,J) + EPA_WD_BF_MEK (I,J) = EPA_WD_BF_MEK (I,J) * USA_MASK(I,J) + EPA_WD_BF_PRPE(I,J) = EPA_WD_BF_PRPE(I,J) * USA_MASK(I,J) + EPA_WD_BF_C3H8(I,J) = EPA_WD_BF_C3H8(I,J) * USA_MASK(I,J) + EPA_WD_BF_CH2O(I,J) = EPA_WD_BF_CH2O(I,J) * USA_MASK(I,J) + EPA_WD_BF_C2H6(I,J) = EPA_WD_BF_C2H6(I,J) * USA_MASK(I,J) + EPA_WD_BF_SO2 (I,J) = EPA_WD_BF_SO2 (I,J) * USA_MASK(I,J) + EPA_WD_BF_SO4 (I,J) = EPA_WD_BF_SO4 (I,J) * USA_MASK(I,J) + EPA_WD_BF_NH3 (I,J) = EPA_WD_BF_NH3 (I,J) * USA_MASK(I,J) + + ! Weekend avg biofuel + EPA_WE_BF_NOX (I,J) = EPA_WE_BF_NOX (I,J) * USA_MASK(I,J) + EPA_WE_BF_CO (I,J) = EPA_WE_BF_CO (I,J) * USA_MASK(I,J) + EPA_WE_BF_ALK4(I,J) = EPA_WE_BF_ALK4(I,J) * USA_MASK(I,J) + EPA_WE_BF_ACET(I,J) = EPA_WE_BF_ACET(I,J) * USA_MASK(I,J) + EPA_WE_BF_MEK (I,J) = EPA_WE_BF_MEK (I,J) * USA_MASK(I,J) + EPA_WE_BF_PRPE(I,J) = EPA_WE_BF_PRPE(I,J) * USA_MASK(I,J) + EPA_WE_BF_C3H8(I,J) = EPA_WE_BF_C3H8(I,J) * USA_MASK(I,J) + EPA_WE_BF_CH2O(I,J) = EPA_WE_BF_CH2O(I,J) * USA_MASK(I,J) + EPA_WE_BF_C2H6(I,J) = EPA_WE_BF_C2H6(I,J) * USA_MASK(I,J) + EPA_WE_BF_SO2 (I,J) = EPA_WE_BF_SO2 (I,J) * USA_MASK(I,J) + EPA_WE_BF_SO4 (I,J) = EPA_WE_BF_SO4 (I,J) * USA_MASK(I,J) + EPA_WE_BF_NH3 (I,J) = EPA_WE_BF_NH3 (I,J) * USA_MASK(I,J) + + !---------------------------------------------- + ! Compute IPCC future emissions (if necessary) + !---------------------------------------------- + IF ( LFUTURE .and. USA_MASK(I,J) > 0d0 ) THEN + + ! Future biofuel scale factors + CObf = GET_FUTURE_SCALE_CObf( I, J ) + NH3bf = GET_FUTURE_SCALE_NH3bf( I, J ) + NOxbf = GET_FUTURE_SCALE_NOXbf( I, J ) + SO2bf = GET_FUTURE_SCALE_SO2bf( I, J ) + VOCbf = GET_FUTURE_SCALE_VOCbf( I, J ) + + ! Weekday avg biofuel + EPA_WD_BF_NOX (I,J) = EPA_WD_BF_NOX (I,J) * NOxbf + EPA_WD_BF_CO (I,J) = EPA_WD_BF_CO (I,J) * CObf + EPA_WD_BF_ALK4(I,J) = EPA_WD_BF_ALK4(I,J) * VOCbf + EPA_WD_BF_ACET(I,J) = EPA_WD_BF_ACET(I,J) * VOCbf + EPA_WD_BF_MEK (I,J) = EPA_WD_BF_MEK (I,J) * VOCbf + EPA_WD_BF_PRPE(I,J) = EPA_WD_BF_PRPE(I,J) * VOCbf + EPA_WD_BF_C3H8(I,J) = EPA_WD_BF_C3H8(I,J) * VOCbf + EPA_WD_BF_CH2O(I,J) = EPA_WD_BF_CH2O(I,J) * VOCbf + EPA_WD_BF_C2H6(I,J) = EPA_WD_BF_C2H6(I,J) * VOCbf + EPA_WD_BF_SO2 (I,J) = EPA_WD_BF_SO2 (I,J) * SO2bf + EPA_WD_BF_SO4 (I,J) = EPA_WD_BF_SO4 (I,J) * SO2bf + EPA_WD_BF_NH3 (I,J) = EPA_WD_BF_NH3 (I,J) * NH3bf + + ! Weekend avg biofuel + EPA_WE_BF_NOX (I,J) = EPA_WE_BF_NOX (I,J) * NOxbf + EPA_WE_BF_CO (I,J) = EPA_WE_BF_CO (I,J) * CObf + EPA_WE_BF_ALK4(I,J) = EPA_WE_BF_ALK4(I,J) * VOCbf + EPA_WE_BF_ACET(I,J) = EPA_WE_BF_ACET(I,J) * VOCbf + EPA_WE_BF_MEK (I,J) = EPA_WE_BF_MEK (I,J) * VOCbf + EPA_WE_BF_PRPE(I,J) = EPA_WE_BF_PRPE(I,J) * VOCbf + EPA_WE_BF_C3H8(I,J) = EPA_WE_BF_C3H8(I,J) * VOCbf + EPA_WE_BF_CH2O(I,J) = EPA_WE_BF_CH2O(I,J) * VOCbf + EPA_WE_BF_C2H6(I,J) = EPA_WE_BF_C2H6(I,J) * VOCbf + EPA_WE_BF_SO2 (I,J) = EPA_WE_BF_SO2 (I,J) * SO2bf + EPA_WE_BF_SO4 (I,J) = EPA_WE_BF_SO4 (I,J) * SO2bf + EPA_WE_BF_NH3 (I,J) = EPA_WE_BF_NH3 (I,J) * NH3bf + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Print totals to the log file + CALL TOTAL_BIOFUEL_TG( THISMONTH ) + + END SUBROUTINE EMISS_EPA_NEI_BF +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_epa +! +! !DESCRIPTION: Subroutine READ\_EPA reads an EPA data file (biomass or anthro) +! from disk. The entire file is read through on one pass for better I/O +! optimization. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_EPA( FILENAME, NOX, CO, ALK4, ACET, MEK, + & PRPE, C3H8, CH2O, C2H6, SO2, SO4, NH3 ) +! +! !USES: +! + USE BPCH2_MOD, ONLY : OPEN_BPCH2_FOR_READ + USE FILE_MOD, ONLY : IU_FILE, IOERROR + USE LOGICAL_MOD, ONLY : LICARTT + USE TRANSFER_MOD, ONLY : TRANSFER_2D + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR + USE TIME_MOD, ONLY : GET_YEAR + +# include "CMN_SIZE" ! Size parameters +# include "CMN_O3" ! FSCLYR +! +! !INPUT PARAMETERS: +! + CHARACTER(LEN=*), INTENT(IN) :: FILENAME ! File to read +! +! !INPUT/OUTPUT PARAMETERS: +! + REAL*4, INTENT(INOUT) :: NOX(IIPAR,JJPAR) ! NOx data + REAL*4, INTENT(INOUT) :: CO(IIPAR,JJPAR) ! CO data + REAL*4, INTENT(INOUT) :: ALK4(IIPAR,JJPAR) ! ALK4 data + REAL*4, INTENT(INOUT) :: ACET(IIPAR,JJPAR) ! ACET data + REAL*4, INTENT(INOUT) :: MEK(IIPAR,JJPAR) ! MEK data + REAL*4, INTENT(INOUT) :: PRPE(IIPAR,JJPAR) ! PRPE data + REAL*4, INTENT(INOUT) :: C3H8(IIPAR,JJPAR) ! C3H8 data + REAL*4, INTENT(INOUT) :: CH2O(IIPAR,JJPAR) ! CH2O data + REAL*4, INTENT(INOUT) :: C2H6(IIPAR,JJPAR) ! C2H6 data + REAL*4, INTENT(INOUT) :: SO2(IIPAR,JJPAR) ! SO2 data + REAL*4, INTENT(INOUT) :: SO4(IIPAR,JJPAR) ! SO4 data + REAL*4, INTENT(INOUT) :: NH3(IIPAR,JJPAR) ! NH3 data +! +! !REVISION HISTORY: +! 01 Jul 2004 - R. Hudman - Initial version +! (1 ) now apply yearly scale factor (amv, phs, 3/10/08) +! (2 ) Now accounts for FSCLYR (phs, 3/17/08) +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J, L, N, IOS + INTEGER :: NTRACER, NSKIP + INTEGER :: HALFPOLAR, CENTER180 + INTEGER :: NI, NJ, NL + INTEGER :: IFIRST, JFIRST, LFIRST + INTEGER :: SCALEYEAR, BASEYEAR + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*4 :: LONRES, LATRES + REAL*8 :: ZTAU0, ZTAU1 + REAL*4 :: SC(IIPAR,JJPAR) + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=40) :: RESERVED + + !================================================================= + ! READ_EPA begins here! + !================================================================= + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_EPA: Reading ', a ) + + ! Open file + CALL OPEN_BPCH2_FOR_READ( IU_FILE, FILENAME ) + + ! Read the entire file in one pass (for I/O optimization) + DO + + ! Read 1st data block header line + READ( IU_FILE, IOSTAT=IOS ) + & MODELNAME, LONRES, LATRES, HALFPOLAR, CENTER180 + + ! Check for EOF or errors + IF ( IOS < 0 ) EXIT + IF ( IOS > 0 ) CALL IOERROR( IOS, IU_FILE, 'read_data:2' ) + + ! Read 2nd data block header line + READ( IU_FILE, IOSTAT=IOS ) + & CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED, + & NI, NJ, NL, IFIRST, JFIRST, LFIRST, + & NSKIP + + ! Error check + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'read_data:3' ) + + ! Read data + READ( IU_FILE, IOSTAT=IOS ) ARRAY(1:NI,1:NJ,1:NL) + + ! Error check + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_FILE, 'read_data:4' ) + + !============================================================== + ! Save into tracer arrays + !============================================================== + SELECT CASE ( NTRACER ) + CASE( 1 ) + CALL TRANSFER_2D( ARRAY(:,:,1), NOx ) + CASE( 4 ) + CALL TRANSFER_2D( ARRAY(:,:,1), CO ) + CASE( 5 ) + CALL TRANSFER_2D( ARRAY(:,:,1), ALK4 ) + CASE( 9 ) + CALL TRANSFER_2D( ARRAY(:,:,1), ACET ) + CASE( 10 ) + CALL TRANSFER_2D( ARRAY(:,:,1), MEK ) + CASE( 18 ) + CALL TRANSFER_2D( ARRAY(:,:,1), PRPE ) + CASE( 19 ) + CALL TRANSFER_2D( ARRAY(:,:,1), C3H8 ) + CASE( 20 ) + CALL TRANSFER_2D( ARRAY(:,:,1), CH2O ) + CASE( 21 ) + CALL TRANSFER_2D( ARRAY(:,:,1), C2H6 ) + CASE( 26 ) + CALL TRANSFER_2D( ARRAY(:,:,1), SO2 ) + CASE( 27 ) + CALL TRANSFER_2D( ARRAY(:,:,1), SO4 ) + CASE( 29 ) + CALL TRANSFER_2D( ARRAY(:,:,1), NH3 ) + CASE DEFAULT + ! Nothing + END SELECT + + ENDDO + + ! Close file + CLOSE( IU_FILE ) + + + ! Get/Apply annual scalar factor (amv, 08/24/07) + IF ( FSCALYR < 0 ) THEN + SCALEYEAR = GET_YEAR() + ELSE + SCALEYEAR = FSCALYR + ENDIF + + BASEYEAR = 1999 + IF ( LICARTT ) BASEYEAR = 2004 + + CALL GET_ANNUAL_SCALAR( 71, BASEYEAR, SCALEYEAR, SC) + NOx(:,:) = NOx(:,:) * SC(:,:) + + CALL GET_ANNUAL_SCALAR( 72, BASEYEAR, SCALEYEAR, SC) + CO(:,:) = CO(:,:) * SC(:,:) + + CALL GET_ANNUAL_SCALAR( 73, 1999, SCALEYEAR, SC) + SO2(:,:) = SO2(:,:) * SC(:,:) + + CALL GET_ANNUAL_SCALAR( 73, 1999, SCALEYEAR, SC) + SO4(:,:) = SO4(:,:) * SC(:,:) + + END SUBROUTINE READ_EPA +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_epa_05x0666 +! +! !DESCRIPTION: Subroutine READ\_EPA reads an EPA data file (biomass or anthro, +! 0.5 x 0.666 resolution) from disk. The entire file is read through on one +! pass for better I/O optimization. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_EPA_05x0666( FILENAME, NOX, CO, ALK4, ACET, + & MEK, PRPE, C3H8, CH2O, C2H6, + & SO2, SO4, NH3, BF ) + +! +! !USES: +! + USE BPCH2_MOD, ONLY : READ_BPCH2, GET_TAU0 + USE LOGICAL_MOD, ONLY : LICARTT + USE TRANSFER_MOD, ONLY : TRANSFER_2D + USE SCALE_ANTHRO_MOD, ONLY : GET_ANNUAL_SCALAR + USE TIME_MOD, ONLY : GET_YEAR, GET_MONTH + +# include "CMN_SIZE" ! Size parameters +# include "CMN_O3" ! FSCLYR +! +! !INPUT PARAMETERS: +! + CHARACTER(LEN=*), INTENT(IN) :: FILENAME ! File to read + INTEGER, INTENT(IN) :: BF ! Read biofuels +! +! !INPUT/OUTPUT PARAMETERS: +! + REAL*4, INTENT(INOUT) :: NOX(IIPAR,JJPAR) ! NOx data + REAL*4, INTENT(INOUT) :: CO(IIPAR,JJPAR) ! CO data + REAL*4, INTENT(INOUT) :: ALK4(IIPAR,JJPAR) ! ALK4 data + REAL*4, INTENT(INOUT) :: ACET(IIPAR,JJPAR) ! ACET data + REAL*4, INTENT(INOUT) :: MEK(IIPAR,JJPAR) ! MEK data + REAL*4, INTENT(INOUT) :: PRPE(IIPAR,JJPAR) ! PRPE data + REAL*4, INTENT(INOUT) :: C3H8(IIPAR,JJPAR) ! C3H8 data + REAL*4, INTENT(INOUT) :: CH2O(IIPAR,JJPAR) ! CH2O data + REAL*4, INTENT(INOUT) :: C2H6(IIPAR,JJPAR) ! C2H6 data + REAL*4, INTENT(INOUT) :: SO2(IIPAR,JJPAR) ! SO2 data + REAL*4, INTENT(INOUT) :: SO4(IIPAR,JJPAR) ! SO4 data + REAL*4, INTENT(INOUT) :: NH3(IIPAR,JJPAR) ! NH3 data +! +! !REMARKS: +! Modified for nested grids (A. van Donkelaar) +! +! !REVISION HISTORY: +! (1 ) now apply yearly scale factor (amv, phs, 3/10/08) +! (2 ) Now accounts for FSCLYR (phs, 3/17/08) +! 07 Feb 2011 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J, L, N, IOS + INTEGER :: NTRACER, NSKIP + INTEGER :: HALFPOLAR, CENTER180 + INTEGER :: SCALEYEAR, BASEYEAR + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*4 :: LONRES, LATRES + REAL*8 :: ZTAU0, ZTAU1, XTAU + REAL*4 :: SC(IIPAR,JJPAR) + CHARACTER(LEN=20) :: MODELNAME + CHARACTER(LEN=40) :: CATEGORY + CHARACTER(LEN=40) :: UNIT + CHARACTER(LEN=40) :: RESERVED + CHARACTER(LEN=8) :: CAT + + !================================================================= + ! READ_EPA begins here! + !================================================================= + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_EPA: Reading ', a ) + + XTAU = GET_TAU0(GET_MONTH(), 1, 1999) + + CAT = 'ANTHSRCE' + IF (BF .EQ. 1) CAT = 'BIOFSRCE' + + CALL READ_BPCH2( FILENAME, CAT, 1, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + NOx(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT, 4, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + CO(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT, 5, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + ALK4(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT, 9, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + ACET(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT,10, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + MEK(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT,18, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + PRPE(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT,19, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + C3H8(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT,21, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + C2H6(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT,26, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + SO2(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT,27, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + SO4(:,:) = ARRAY(:,:,1) + + CALL READ_BPCH2( FILENAME, CAT,29, XTAU, + & IIPAR, JJPAR, 1, ARRAY, QUIET=.TRUE.) + NH3(:,:) = ARRAY(:,:,1) + + ! Get/Apply annual scalar factor (amv, 08/24/07) + IF ( FSCALYR < 0 ) THEN + SCALEYEAR = GET_YEAR() + ELSE + SCALEYEAR = FSCALYR + ENDIF + + BASEYEAR = 1999 + IF ( LICARTT ) BASEYEAR = 2004 + + CALL GET_ANNUAL_SCALAR( 71, BASEYEAR, SCALEYEAR, SC) + NOx(:,:) = NOx(:,:) * SC(:,:) + + CALL GET_ANNUAL_SCALAR( 72, BASEYEAR, SCALEYEAR, SC) + CO(:,:) = CO(:,:) * SC(:,:) + + CALL GET_ANNUAL_SCALAR( 73, 1999, SCALEYEAR, SC) + SO2(:,:) = SO2(:,:) * SC(:,:) + + CALL GET_ANNUAL_SCALAR( 73, 1999, SCALEYEAR, SC) + SO4(:,:) = SO4(:,:) * SC(:,:) + + END SUBROUTINE READ_EPA_05x0666 +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_usa_mask +! +! !DESCRIPTION: Subroutine READ\_USA\_MASK reads the USA mask from disk. The USA mask is +! the fraction of the grid box (I,J) which lies w/in the continental USA. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_USA_MASK + +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D, GET_RES_EXT + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE LOGICAL_MOD, ONLY : LCAC, LBRAVO + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters +! +! !REMARKS: +! From README file: +! "The mask files have been updated to deal correctly with the boxes on +! the border. They are simply set to include boxes where EPA emissions +! are non-zero. We assume that BRAVO and CAC are also used when EPA is +! used. If you use neither BRAVO nor CAC, you should use the older masks +! to avoid missing emissions along the borders. Masks for the +! case that either BRAVO or CAC (but not both) is used w/ EPA have not +! been produced" (phs, 12/23/08) +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! (1 ) Now can read data for GEOS and GCAP grids (bmy, 8/16/05) +! (2 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (3 ) Read larger mask for correct overlap with BRAVO and CAC, if these +! regional inventories are used. +! (4 ) Temporary fix (until larger masks at 1x1 and 0.5x0.667, and cut to +! the NA window, are available) nested NA runs. +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*8 :: XTAU + CHARACTER(LEN=255) :: FILENAME + CHARACTER(LEN=14 ) :: MASK_DIR + + !================================================================= + ! READ_USA_MASK begins here! + !================================================================= + + ! File name + IF ( LCAC .AND. LBRAVO ) THEN + MASK_DIR = 'EPA_NEI_200806' + ELSE IF ( LCAC .OR. LBRAVO ) THEN + WRITE( 6, * ) '!! WARNING !! : WITH EPA, EITHER NONE OR ' // + $ ' BOTH BRAVO AND CAC INVENTORIES SHOULD BE USED !!!' + MASK_DIR = 'EPA_NEI_200806' + ELSE + MASK_DIR = 'EPA_NEI_200411' + ENDIF + +#if defined( NESTED_NA ) + MASK_DIR = 'EPA_NEI_200411' +#endif + + ! Create filename + FILENAME = TRIM( DATA_DIR ) // + & MASK_DIR // '/usa_mask.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_USA_MASK: Reading ', a ) + + ! Get TAU0 for Jan 1985 + XTAU = GET_TAU0( 1, 1, 1985 ) + + ! USA mask is stored in the bpch file as #2 + CALL READ_BPCH2( FILENAME, 'LANDMAP', 2, + & XTAU, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 + CALL TRANSFER_2D( ARRAY(:,:,1), USA_MASK ) + + END SUBROUTINE READ_USA_MASK +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: read_usa_mask_05x0666 +! +! !DESCRIPTION: Subroutine READ\_USA\_MASK\_05x0666 reads the USA mask from +! disk, at 0.5 x 0.666 resolution. The USA mask is the fraction of the grid +! box (I,J) which lies w/in the continental USA. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE READ_USA_MASK_05x0666 +! +! !USES: +! + USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D, GET_RES_EXT + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE LOGICAL_MOD, ONLY : LCAC, LBRAVO + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters +! +! !REMARKS: +! From README file: +! "The mask files have been updated to deal correctly with the boxes on +! the border. They are simply set to include boxes where EPA emissions +! are non-zero. We assume that BRAVO and CAC are also used when EPA is +! used. If you use neither BRAVO nor CAC, you should use the older masks +! to avoid missing emissions along the borders. Masks for the +! case that either BRAVO or CAC (but not both) is used w/ EPA have not +! been produced" (phs, 12/23/08) +! +! !REVISION HISTORY: +! (1 ) Now can read data for GEOS and GCAP grids (bmy, 8/16/05) +! (2 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (3 ) Read larger mask for correct overlap with BRAVO and CAC, if these +! regional inventories are used. +! (4 ) Temporary fix (until larger masks at 1x1 and 0.5x0.667, and cut to +! the NA window, are available) nested NA runs. +! 07 Feb 2011 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*4 :: ARRAY(IIPAR,JJPAR,1) + REAL*8 :: XTAU + CHARACTER(LEN=255) :: FILENAME + CHARACTER(LEN=14 ) :: MASK_DIR + + !================================================================= + ! READ_USA_MASK begins here! + !================================================================= + + ! File name + IF ( LCAC .AND. LBRAVO ) THEN + MASK_DIR = 'EPA_NEI_200806' + ELSE IF ( LCAC .OR. LBRAVO ) THEN + WRITE( 6, * ) '!! WARNING !! : WITH EPA, EITHER NONE OR ' // + $ ' BOTH BRAVO AND CAC INVENTORIES SHOULD BE USED !!!' + MASK_DIR = 'EPA_NEI_200806' + ELSE + MASK_DIR = 'EPA_NEI_200411' + ENDIF + +#if defined( NESTED_NA ) + MASK_DIR = 'EPA_NEI_200411' +#endif + + ! Create filename + FILENAME = TRIM( DATA_DIR ) // + & MASK_DIR // '/usa_mask.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_USA_MASK: Reading ', a ) + + ! Get TAU0 for Jan 1985 + XTAU = GET_TAU0( 1, 1, 1985 ) + + ! USA mask is stored in the bpch file as #2 + CALL READ_BPCH2( FILENAME, 'LANDMAP', 2, + & XTAU, IIPAR, JJPAR, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 + CALL TRANSFER_2D( ARRAY(:,:,1), USA_MASK ) + + END SUBROUTINE READ_USA_MASK_05x0666 +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: total_anthro_Tg +! +! !DESCRIPTION: Subroutine TOTAL\_ANTHRO\_TG prints the amount of EPA/NEI99 +! anthropogenic emissions that are emitted each month in Tg or Tg C. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE TOTAL_ANTHRO_Tg( THISMONTH ) +! +! !USES: +! + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE TRACER_MOD, ONLY : TRACER_MW_KG + USE TRACERID_MOD, ONLY : IDTACET, IDTALK4, IDTC2H6, IDTC3H8 + USE TRACERID_MOD, ONLY : IDTCH2O, IDTCO, IDTMEK, IDTNOX + USE TRACERID_MOD, ONLY : IDTNH3, IDTPRPE, IDTSO2, IDTSO4 + +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: THISMONTH ! Current month (1-12) +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! (1) Scale factors were determined by Jennifer Logan (jal@io.harvard.edu), +! Bryan Duncan (bnd@io.harvard.edu), and Daniel Jacob (djj@io.harvard.edu) +! (2) Now replace DXYP(J)*1d4 with routine GET_AREA_CM2 from "grid_mod.f". +! (bmy, 2/4/03) +! (3) Prevent out of bounds error when tracers are undefined (bmy, 1/25/05) +! (4) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (5) Now replace FMOL with TRACER_MW_KG (bmy, 10/25/05) + +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + REAL*8 :: WD_NOX, WD_CO, WD_ALK4, WD_ACET + REAL*8 :: WD_MEK, WD_PRPE, WD_C2H6, WD_C3H8 + REAL*8 :: WD_CH2O, WD_NH3, WD_SO2, WD_SO4, A + REAL*8 :: WE_NOX, WE_CO, WE_ALK4, WE_ACET + REAL*8 :: WE_MEK, WE_PRPE, WE_C2H6, WE_C3H8 + REAL*8 :: WE_CH2O, WE_NH3, WE_SO2, WE_SO4 + REAL*8 :: F_NOX, F_CO, F_ALK4, F_ACET + REAL*8 :: F_MEK, F_PRPE, F_C2H6, F_C3H8 + REAL*8 :: F_CH2O, F_SO2, F_SO4, F_NH3 + CHARACTER(LEN=6) :: UNIT + + ! Days per month + INTEGER :: D(12) = (/ 31, 28, 31, 30, 31, 30, + & 31, 31, 30, 31, 30, 31 /) + + !================================================================= + ! TOTAL_ANTHRO_TG begins here! + !================================================================= + + ! Summing variables for weekday avg anthro + WD_NOX = 0d0 + WD_CO = 0d0 + WD_ALK4 = 0d0 + WD_ACET = 0d0 + WD_MEK = 0d0 + WD_PRPE = 0d0 + WD_C2H6 = 0d0 + WD_C3H8 = 0d0 + WD_CH2O = 0d0 + WD_NH3 = 0d0 + WD_SO2 = 0d0 + WD_SO4 = 0d0 + + ! Summing variables for weekend avg anthro + WE_NOX = 0d0 + WE_CO = 0d0 + WE_ALK4 = 0d0 + WE_ACET = 0d0 + WE_MEK = 0d0 + WE_PRPE = 0d0 + WE_C2H6 = 0d0 + WE_C3H8 = 0d0 + WE_CH2O = 0d0 + WE_NH3 = 0d0 + WE_SO2 = 0d0 + WE_SO4 = 0d0 + + ! Molecular weights + F_NOX = 0d0 + F_CO = 0d0 + F_ALK4 = 0d0 + F_ACET = 0d0 + F_MEK = 0d0 + F_PRPE = 0d0 + F_C2H6 = 0d0 + F_C3H8 = 0d0 + F_CH2O = 0d0 + F_SO2 = 0d0 + F_SO4 = 0d0 + F_NH3 = 0d0 + + ! Prevent array out of bounds error for undefined tracers + IF ( IDTNOX > 0 ) F_NOX = TRACER_MW_KG(IDTNOX ) + IF ( IDTCO > 0 ) F_CO = TRACER_MW_KG(IDTCO ) + IF ( IDTALK4 > 0 ) F_ALK4 = TRACER_MW_KG(IDTALK4) + IF ( IDTACET > 0 ) F_ACET = TRACER_MW_KG(IDTACET) + IF ( IDTMEK > 0 ) F_MEK = TRACER_MW_KG(IDTMEK ) + IF ( IDTPRPE > 0 ) F_PRPE = TRACER_MW_KG(IDTPRPE) + IF ( IDTC2H6 > 0 ) F_C2H6 = TRACER_MW_KG(IDTC2H6) + IF ( IDTC3H8 > 0 ) F_C3H8 = TRACER_MW_KG(IDTC3H8) + IF ( IDTCH2O > 0 ) F_CH2O = TRACER_MW_KG(IDTCH2O) + IF ( IDTSO2 > 0 ) F_SO2 = TRACER_MW_KG(IDTSO2 ) + IF ( IDTSO4 > 0 ) F_SO4 = TRACER_MW_KG(IDTSO4 ) + IF ( IDTNH3 > 0 ) F_NH3 = TRACER_MW_KG(IDTNH3 ) + + !================================================================= + ! Sum anthropogenic emissions + !================================================================= + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Surface area [cm2] * seconds in this month / AVOGADRO's number + ! Also multiply by the factor 1d-9 to convert kg to Tg + A = GET_AREA_CM2( J ) * ( D(THISMONTH) * 86400d-9 ) / 6.0225d23 + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Weekday avg emissions + WD_NOX = WD_NOX + EPA_WD_AN_NOX (I,J) * A * F_NOX + WD_CO = WD_CO + EPA_WD_AN_CO (I,J) * A * F_CO + WD_ALK4 = WD_ALK4 + EPA_WD_AN_ALK4(I,J) * A * F_ALK4 + WD_ACET = WD_ACET + EPA_WD_AN_ACET(I,J) * A * F_ACET + WD_MEK = WD_MEK + EPA_WD_AN_MEK (I,J) * A * F_MEK + WD_PRPE = WD_PRPE + EPA_WD_AN_PRPE(I,J) * A * F_PRPE + WD_C2H6 = WD_C2H6 + EPA_WD_AN_C2H6(I,J) * A * F_C2H6 + WD_C3H8 = WD_C3H8 + EPA_WD_AN_C3H8(I,J) * A * F_C3H8 + WD_CH2O = WD_CH2O + EPA_WD_AN_CH2O(I,J) * A * F_CH2O + WD_SO2 = WD_SO2 + EPA_WD_AN_SO2 (I,J) * A * F_SO2 + WD_SO4 = WD_SO4 + EPA_WD_AN_SO4 (I,J) * A * F_SO4 + WD_NH3 = WD_NH3 + EPA_WD_AN_NH3 (I,J) * A * F_NH3 + + ! Weekend avg emissions + WE_NOX = WE_NOX + EPA_WE_AN_NOX (I,J) * A * F_NOX + WE_CO = WE_CO + EPA_WE_AN_CO (I,J) * A * F_CO + WE_ALK4 = WE_ALK4 + EPA_WE_AN_ALK4(I,J) * A * F_ALK4 + WE_ACET = WE_ACET + EPA_WE_AN_ACET(I,J) * A * F_ACET + WE_MEK = WE_MEK + EPA_WE_AN_MEK (I,J) * A * F_MEK + WE_PRPE = WE_PRPE + EPA_WE_AN_PRPE(I,J) * A * F_PRPE + WE_C2H6 = WE_C2H6 + EPA_WE_AN_C2H6(I,J) * A * F_C2H6 + WE_C3H8 = WE_C3H8 + EPA_WE_AN_C3H8(I,J) * A * F_C3H8 + WE_CH2O = WE_CH2O + EPA_WE_AN_CH2O(I,J) * A * F_CH2O + WE_SO2 = WE_SO2 + EPA_WE_AN_SO2 (I,J) * A * F_SO2 + WE_SO4 = WE_SO4 + EPA_WE_AN_SO4 (I,J) * A * F_SO4 + WE_NH3 = WE_NH3 + EPA_WE_AN_NH3 (I,J) * A * F_NH3 + + ENDDO + ENDDO + + !================================================================= + ! Print info + !================================================================= + + ! Weekday avg anthro + WRITE( 6, '(a)' ) + WRITE( 6, 100 ) 'NOx ', THISMONTH, WD_NOX, ' ' + WRITE( 6, 100 ) 'CO ', THISMONTH, WD_CO, ' ' + WRITE( 6, 100 ) 'ALK4', THISMONTH, WD_ALK4, ' C' + WRITE( 6, 100 ) 'ACET', THISMONTH, WD_ACET, ' C' + WRITE( 6, 100 ) 'MEK ', THISMONTH, WD_MEK, ' C' + WRITE( 6, 100 ) 'PRPE', THISMONTH, WD_PRPE, ' C' + WRITE( 6, 100 ) 'C3H8', THISMONTH, WD_C3H8, ' C' + WRITE( 6, 100 ) 'CH2O', THISMONTH, WD_CH2O, ' ' + WRITE( 6, 100 ) 'C2H6', THISMONTH, WD_C2H6, ' C' + WRITE( 6, 100 ) 'SO2 ', THISMONTH, WD_SO2, ' ' + WRITE( 6, 100 ) 'SO4 ', THISMONTH, WD_SO4, ' ' + WRITE( 6, 100 ) 'NH3 ', THISMONTH, WD_NH3, ' ' + 100 FORMAT( 'Total weekday avg anthro ', a4, ' for 1999/', + & i2.2, ': ', f13.6, ' Tg', a2 ) + + ! Weekend avg anthro + WRITE( 6, '(a)' ) + WRITE( 6, 110 ) 'NOx ', THISMONTH, WE_NOX, ' ' + WRITE( 6, 110 ) 'CO ', THISMONTH, WE_CO, ' ' + WRITE( 6, 110 ) 'ALK4', THISMONTH, WE_ALK4, ' C' + WRITE( 6, 110 ) 'ACET', THISMONTH, WE_ACET, ' C' + WRITE( 6, 110 ) 'MEK ', THISMONTH, WE_MEK, ' C' + WRITE( 6, 110 ) 'PRPE', THISMONTH, WE_PRPE, ' C' + WRITE( 6, 110 ) 'C3H8', THISMONTH, WE_C3H8, ' C' + WRITE( 6, 110 ) 'CH2O', THISMONTH, WE_CH2O, ' ' + WRITE( 6, 110 ) 'C2H6', THISMONTH, WE_C2H6, ' C' + WRITE( 6, 110 ) 'SO2 ', THISMONTH, WE_SO2, ' ' + WRITE( 6, 110 ) 'SO4 ', THISMONTH, WE_SO4, ' ' + WRITE( 6, 110 ) 'NH3 ', THISMONTH, WE_NH3, ' ' + 110 FORMAT( 'Total weekend avg anthro ', a4, ' for 1999/', + & i2.2, ': ', f13.6, ' Tg', a2 ) + + END SUBROUTINE TOTAL_ANTHRO_TG +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: total_biofuel_Tg +! +! !DESCRIPTION: Subroutine TOTAL\_BIOFUEL\_Tg prints the amount of EPA/NEI99 +! biofuel emissions that are emitted each month in Tg or Tg C. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE TOTAL_BIOFUEL_Tg( THISMONTH ) +! +! !USES: +! + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE TRACER_MOD, ONLY : TRACER_MW_KG + USE TRACERID_MOD, ONLY : IDTACET, IDTALK4, IDTC2H6, IDTC3H8 + USE TRACERID_MOD, ONLY : IDTCH2O, IDTCO, IDTMEK, IDTNOX + USE TRACERID_MOD, ONLY : IDTNH3, IDTPRPE, IDTSO2, IDTSO4 + +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: THISMONTH ! Current month (1-12) +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! (1 ) Prevent out of bounds error when tracers are undefined (bmy, 1/25/05) +! (2 ) Now replace FMOL with TRACER_MW_KG +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: I, J + REAL*8 :: WD_NOX, WD_CO, WD_ALK4, WD_ACET + REAL*8 :: WD_MEK, WD_PRPE, WD_C2H6, WD_C3H8 + REAL*8 :: WD_CH2O, WD_NH3, WD_SO2, WD_SO4, A + REAL*8 :: WE_NOX, WE_CO, WE_ALK4, WE_ACET + REAL*8 :: WE_MEK, WE_PRPE, WE_C2H6, WE_C3H8 + REAL*8 :: WE_CH2O, WE_NH3, WE_SO2, WE_SO4 + REAL*8 :: F_NOX, F_CO, F_ALK4, F_ACET + REAL*8 :: F_MEK, F_PRPE, F_C2H6, F_C3H8 + REAL*8 :: F_CH2O, F_SO2, F_SO4, F_NH3 + CHARACTER(LEN=6) :: UNIT + + ! Days per month + INTEGER :: D(12) = (/ 31, 28, 31, 30, 31, 30, + & 31, 31, 30, 31, 30, 31 /) + + !================================================================= + ! TOTAL_BIOFUEL_TG begins here! + !================================================================= + + ! Summing variables for weekday avg anthro + WD_NOX = 0d0 + WD_CO = 0d0 + WD_ALK4 = 0d0 + WD_ACET = 0d0 + WD_MEK = 0d0 + WD_PRPE = 0d0 + WD_C2H6 = 0d0 + WD_C3H8 = 0d0 + WD_CH2O = 0d0 + WD_NH3 = 0d0 + WD_SO2 = 0d0 + WD_SO4 = 0d0 + + ! Summing variables for weekend avg anthro + WE_NOX = 0d0 + WE_CO = 0d0 + WE_ALK4 = 0d0 + WE_ACET = 0d0 + WE_MEK = 0d0 + WE_PRPE = 0d0 + WE_C2H6 = 0d0 + WE_C3H8 = 0d0 + WE_CH2O = 0d0 + WE_NH3 = 0d0 + WE_SO2 = 0d0 + WE_SO4 = 0d0 + + ! Molecular weights + F_NOX = 0d0 + F_CO = 0d0 + F_ALK4 = 0d0 + F_ACET = 0d0 + F_MEK = 0d0 + F_PRPE = 0d0 + F_C2H6 = 0d0 + F_C3H8 = 0d0 + F_CH2O = 0d0 + F_SO2 = 0d0 + F_SO4 = 0d0 + F_NH3 = 0d0 + + ! Prevent array out of bounds error for undefined tracers + IF ( IDTNOX > 0 ) F_NOX = TRACER_MW_KG(IDTNOX ) + IF ( IDTCO > 0 ) F_CO = TRACER_MW_KG(IDTCO ) + IF ( IDTALK4 > 0 ) F_ALK4 = TRACER_MW_KG(IDTALK4) + IF ( IDTACET > 0 ) F_ACET = TRACER_MW_KG(IDTACET) + IF ( IDTMEK > 0 ) F_MEK = TRACER_MW_KG(IDTMEK ) + IF ( IDTPRPE > 0 ) F_PRPE = TRACER_MW_KG(IDTPRPE) + IF ( IDTC2H6 > 0 ) F_C2H6 = TRACER_MW_KG(IDTC2H6) + IF ( IDTC3H8 > 0 ) F_C3H8 = TRACER_MW_KG(IDTC3H8) + IF ( IDTCH2O > 0 ) F_CH2O = TRACER_MW_KG(IDTCH2O) + IF ( IDTSO2 > 0 ) F_SO2 = TRACER_MW_KG(IDTSO2 ) + IF ( IDTSO4 > 0 ) F_SO4 = TRACER_MW_KG(IDTSO4 ) + IF ( IDTNH3 > 0 ) F_NH3 = TRACER_MW_KG(IDTNH3 ) + + !================================================================= + ! Sum biofuel emissions + !================================================================= + + ! Loop over surface boxes + DO J = 1, JJPAR + + ! Surface area [cm2] * seconds in this month / AVOGADRO's number + ! Also multiply by the factor 1d-9 to convert kg to Tg + A = GET_AREA_CM2( J ) * ( D(THISMONTH) * 86400d-9 ) / 6.0225d23 + + DO I = 1, IIPAR + + ! Weekday avg emissions + WD_NOX = WD_NOX + EPA_WD_BF_NOX (I,J) * A * F_NOX + WD_CO = WD_CO + EPA_WD_BF_CO (I,J) * A * F_CO + WD_ALK4 = WD_ALK4 + EPA_WD_BF_ALK4(I,J) * A * F_ALK4 + WD_ACET = WD_ACET + EPA_WD_BF_ACET(I,J) * A * F_ACET + WD_MEK = WD_MEK + EPA_WD_BF_MEK (I,J) * A * F_MEK + WD_PRPE = WD_PRPE + EPA_WD_BF_PRPE(I,J) * A * F_PRPE + WD_C2H6 = WD_C2H6 + EPA_WD_BF_C2H6(I,J) * A * F_C2H6 + WD_C3H8 = WD_C3H8 + EPA_WD_BF_C3H8(I,J) * A * F_C3H8 + WD_CH2O = WD_CH2O + EPA_WD_BF_CH2O(I,J) * A * F_CH2O + WD_SO2 = WD_SO2 + EPA_WD_BF_SO2 (I,J) * A * F_SO2 + WD_SO4 = WD_SO4 + EPA_WD_BF_SO4 (I,J) * A * F_SO4 + WD_NH3 = WD_NH3 + EPA_WD_BF_NH3 (I,J) * A * F_NH3 + + ! Weekend avg emissions + WE_NOX = WE_NOX + EPA_WE_BF_NOX (I,J) * A * F_NOX + WE_CO = WE_CO + EPA_WE_BF_CO (I,J) * A * F_CO + WE_ALK4 = WE_ALK4 + EPA_WE_BF_ALK4(I,J) * A * F_ALK4 + WE_ACET = WE_ACET + EPA_WE_BF_ACET(I,J) * A * F_ACET + WE_MEK = WE_MEK + EPA_WE_BF_MEK (I,J) * A * F_MEK + WE_PRPE = WE_PRPE + EPA_WE_BF_PRPE(I,J) * A * F_PRPE + WE_C2H6 = WE_C2H6 + EPA_WE_BF_C2H6(I,J) * A * F_C2H6 + WE_C3H8 = WE_C3H8 + EPA_WE_BF_C3H8(I,J) * A * F_C3H8 + WE_CH2O = WE_CH2O + EPA_WE_BF_CH2O(I,J) * A * F_CH2O + WE_SO2 = WE_SO2 + EPA_WE_BF_SO2 (I,J) * A * F_SO2 + WE_SO4 = WE_SO4 + EPA_WE_BF_SO4 (I,J) * A * F_SO4 + WE_NH3 = WE_NH3 + EPA_WE_BF_NH3 (I,J) * A * F_NH3 + + ENDDO + ENDDO + + !================================================================= + ! Print info + !================================================================= + + ! Weekday avg biofuel + WRITE( 6, '(a)' ) + WRITE( 6, 100 ) 'NOx ', THISMONTH, WD_NOX, ' ' + WRITE( 6, 100 ) 'CO ', THISMONTH, WD_CO, ' ' + WRITE( 6, 100 ) 'ALK4', THISMONTH, WD_ALK4, ' C' + WRITE( 6, 100 ) 'ACET', THISMONTH, WD_ACET, ' C' + WRITE( 6, 100 ) 'MEK ', THISMONTH, WD_MEK, ' C' + WRITE( 6, 100 ) 'PRPE', THISMONTH, WD_PRPE, ' C' + WRITE( 6, 100 ) 'C3H8', THISMONTH, WD_C3H8, ' C' + WRITE( 6, 100 ) 'CH2O', THISMONTH, WD_CH2O, ' ' + WRITE( 6, 100 ) 'C2H6', THISMONTH, WD_C2H6, ' C' + WRITE( 6, 100 ) 'SO2 ', THISMONTH, WD_SO2, ' ' + WRITE( 6, 100 ) 'SO4 ', THISMONTH, WD_SO4, ' ' + WRITE( 6, 100 ) 'NH3 ', THISMONTH, WD_NH3, ' ' + 100 FORMAT( 'Total weekday avg biofuel ', a4, ' for 1999/', + & i2.2, ': ', f13.6, ' Tg', a2 ) + + ! Weekend avg biofuel + WRITE( 6, '(a)' ) + WRITE( 6, 110 ) 'NOx ', THISMONTH, WE_NOX, ' ' + WRITE( 6, 110 ) 'CO ', THISMONTH, WE_CO, ' ' + WRITE( 6, 110 ) 'ALK4', THISMONTH, WE_ALK4, ' C' + WRITE( 6, 110 ) 'ACET', THISMONTH, WE_ACET, ' C' + WRITE( 6, 110 ) 'MEK ', THISMONTH, WE_MEK, ' C' + WRITE( 6, 110 ) 'PRPE', THISMONTH, WE_PRPE, ' C' + WRITE( 6, 110 ) 'C3H8', THISMONTH, WE_C3H8, ' C' + WRITE( 6, 110 ) 'CH2O', THISMONTH, WE_CH2O, ' ' + WRITE( 6, 110 ) 'C2H6', THISMONTH, WE_C2H6, ' C' + WRITE( 6, 110 ) 'SO2 ', THISMONTH, WE_SO2, ' ' + WRITE( 6, 110 ) 'SO4 ', THISMONTH, WE_SO4, ' ' + WRITE( 6, 110 ) 'NH3 ', THISMONTH, WE_NH3, ' ' + 110 FORMAT( 'Total weekend avg biofuel ', a4, ' for 1999/', + & i2.2, ': ', f13.6, ' Tg', a2 ) + + END SUBROUTINE TOTAL_BIOFUEL_TG +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_usa_mask +! +! !DESCRIPTION: Function GET\_USA\_MASK returns the value of the USA mask +! (i.e. the fraction of a grid box which lies w/in the continental USA) +! at a given (I,J) location. (rch, bmy, 11/10/04) + +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_USA_MASK( I, J ) RESULT( USA ) +! +! !INPUT PARAMETERS: +! + INTEGER, INTENT(IN) :: I ! GEOS-Chem longitude index + INTEGER, INTENT(IN) :: J ! GEOS-Chem latitude index +! +! !RETURN VALUE: +! + REAL*8 :: USA ! Fraction of box in continental USA +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! GET_USA_MASK begins here! + !================================================================= + USA = USA_MASK(I,J) + + END FUNCTION GET_USA_MASK +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_epa_anthro +! +! !DESCRIPTION: Function GET\_EPA\_ANTHRO returns the EPA/NEI99 weekday avg or +! weekend avg anthropogenic emissions at a (I,J) location. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_EPA_ANTHRO( I, J, N, WEEKDAY ) RESULT( EPA_NEI ) +! +! !USES: +! + USE TRACERID_MOD, ONLY : IDTACET, IDTALK4, IDTC2H6, IDTC3H8 + USE TRACERID_MOD, ONLY : IDTCH2O, IDTCO, IDTMEK, IDTNOX + USE TRACERID_MOD, ONLY : IDTNH3, IDTPRPE, IDTSO2, IDTSO4 + +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + LOGICAL, INTENT(IN) :: WEEKDAY ! =T if it's a weekday, =F if weekend + INTEGER, INTENT(IN) :: I ! GEOS-Chem longitude index + INTEGER, INTENT(IN) :: J ! GEOS-Chem latitude index + INTEGER, INTENT(IN) :: N ! GEOS-Chem tracer number +! +! !RETURN VALUE: +! + REAL*8 :: EPA_NEI ! Anthropogenic Emissions [molec/cm2/s] + ! or [atoms C/cm2/s] for some HC's +! +! !REVISION HISTORY: +! 07 Feb 2011 - R. Yantosca - Initial version +! 10 Nov 2004 - R. Hudman - Initial version +! (1 ) Now make sure all USE statements are USE, ONLY. Also remove reference +! to BPCH2_MOD and TRACERID_MOD, they're not needed. (bmy, 10/3/05) +! (2 ) Default value changed to -1 to identify tracers without EPA/NEI +! emissions. (hotp, ccc, 5/29/09) + +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! GET_EPA_ANTHRO begins here! + !================================================================= + + ! Return either weekday or weekend avg emissions + IF ( WEEKDAY ) THEN + + !-------------------- + ! Weekday avg anthro + !-------------------- + IF ( N == IDTNOX ) THEN + EPA_NEI = EPA_WD_AN_NOX(I,J) + + ELSE IF ( N == IDTCO ) THEN + EPA_NEI = EPA_WD_AN_CO(I,J) + + ELSE IF ( N == IDTALK4 ) THEN + EPA_NEI = EPA_WD_AN_ALK4(I,J) + + ELSE IF ( N == IDTACET ) THEN + EPA_NEI = EPA_WD_AN_ACET(I,J) + + ELSE IF ( N == IDTMEK ) THEN + EPA_NEI = EPA_WD_AN_MEK(I,J) + + ELSE IF ( N == IDTPRPE ) THEN + EPA_NEI = EPA_WD_AN_PRPE(I,J) + + ELSE IF ( N == IDTC3H8 ) THEN + EPA_NEI = EPA_WD_AN_C3H8(I,J) + + ELSE IF ( N == IDTCH2O ) THEN + EPA_NEI = EPA_WD_AN_CH2O(I,J) + + ELSE IF ( N == IDTC2H6 ) THEN + EPA_NEI = EPA_WD_AN_C2H6(I,J) + + ELSE IF ( N == IDTSO2 ) THEN + EPA_NEI = EPA_WD_AN_SO2(I,J) + + ELSE IF ( N == IDTSO4 ) THEN + EPA_NEI = EPA_WD_AN_SO4(I,J) + + ELSE IF ( N == IDTNH3 ) THEN + EPA_NEI = EPA_WD_AN_NH3(I,J) + + ELSE + ! Some anthropogenic species don't have EPA/NEI emissions. + ! We need to keep background emissions. (hotp, ccc, 5/29/09) + EPA_NEI = -1d0 + + ENDIF + + ELSE + + !-------------------- + ! Weekend avg anthro + !-------------------- + IF ( N == IDTNOX ) THEN + EPA_NEI = EPA_WE_AN_NOX(I,J) + + ELSE IF ( N == IDTCO ) THEN + EPA_NEI = EPA_WE_AN_CO(I,J) + + ELSE IF ( N == IDTALK4 ) THEN + EPA_NEI = EPA_WE_AN_ALK4(I,J) + + ELSE IF ( N == IDTACET ) THEN + EPA_NEI = EPA_WE_AN_ACET(I,J) + + ELSE IF ( N == IDTMEK ) THEN + EPA_NEI = EPA_WE_AN_MEK(I,J) + + ELSE IF ( N == IDTPRPE ) THEN + EPA_NEI = EPA_WE_AN_PRPE(I,J) + + ELSE IF ( N == IDTC3H8 ) THEN + EPA_NEI = EPA_WE_AN_C3H8(I,J) + + ELSE IF ( N == IDTCH2O ) THEN + EPA_NEI = EPA_WE_AN_CH2O(I,J) + + ELSE IF ( N == IDTC2H6 ) THEN + EPA_NEI = EPA_WE_AN_C2H6(I,J) + + ELSE IF ( N == IDTSO2 ) THEN + EPA_NEI = EPA_WE_AN_SO2(I,J) + + ELSE IF ( N == IDTSO4 ) THEN + EPA_NEI = EPA_WE_AN_SO4(I,J) + + ELSE IF ( N == IDTNH3 ) THEN + EPA_NEI = EPA_WE_AN_NH3(I,J) + + ELSE + ! Some anthropogenic species don't have EPA/NEI emissions. + ! We need to keep background emissions. (hotp, ccc, 5/29/09) + EPA_NEI = -1d0 + + ENDIF + + ENDIF + + END FUNCTION GET_EPA_ANTHRO +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: get_epa_biofuel +! +! !DESCRIPTION: Function GET\_EPA\_BIOFUEL returns the EPA/NEI99 weekday avg +! or weekend avg biofuel emissions at a (I,J) location. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION GET_EPA_BIOFUEL( I, J, N, WEEKDAY ) RESULT( EPA_NEI ) +! +! !USES: +! + USE TRACERID_MOD, ONLY : IDTACET, IDTALK4, IDTC2H6, IDTC3H8 + USE TRACERID_MOD, ONLY : IDTCH2O, IDTCO, IDTMEK, IDTNOX + USE TRACERID_MOD, ONLY : IDTNH3, IDTPRPE, IDTSO2, IDTSO4 + +# include "CMN_SIZE" ! Size parameters +! +! !INPUT PARAMETERS: +! + LOGICAL, INTENT(IN) :: WEEKDAY ! =T if it's a weekday, =F if weekend + INTEGER, INTENT(IN) :: I ! GEOS-Chem longitude index + INTEGER, INTENT(IN) :: J ! GEOS-Chem latitude index + INTEGER, INTENT(IN) :: N ! GEOS-Chem tracer number +! +! !RETURN VALUE: +! + REAL*8 :: EPA_NEI +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! (1 ) Now make sure all USE statements are USE, ONLY. Also remove reference +! to BPCH2_MOD and TRACERID_MOD, they're not needed. (bmy, 10/3/05) +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! GET_EPA_BIOFUEL begins here! + !================================================================= + + ! Return either weekday or weekend avg emissions + IF ( WEEKDAY ) THEN + + !--------------------- + ! Weekday avg biofuel + !--------------------- + IF ( N == IDTNOX ) THEN + EPA_NEI = EPA_WD_BF_NOX(I,J) + + ELSE IF ( N == IDTCO ) THEN + EPA_NEI = EPA_WD_BF_CO(I,J) + + ELSE IF ( N == IDTALK4 ) THEN + EPA_NEI = EPA_WD_BF_ALK4(I,J) + + ELSE IF ( N == IDTACET ) THEN + EPA_NEI = EPA_WD_BF_ACET(I,J) + + ELSE IF ( N == IDTMEK ) THEN + EPA_NEI = EPA_WD_BF_MEK(I,J) + + ELSE IF ( N == IDTPRPE ) THEN + EPA_NEI = EPA_WD_BF_PRPE(I,J) + + ELSE IF ( N == IDTC3H8 ) THEN + EPA_NEI = EPA_WD_BF_C3H8(I,J) + + ELSE IF ( N == IDTCH2O ) THEN + EPA_NEI = EPA_WD_BF_CH2O(I,J) + + ELSE IF ( N == IDTC2H6 ) THEN + EPA_NEI = EPA_WD_BF_C2H6(I,J) + + ELSE IF ( N == IDTSO2 ) THEN + EPA_NEI = EPA_WD_BF_SO2(I,J) + + ELSE IF ( N == IDTSO4 ) THEN + EPA_NEI = EPA_WD_BF_SO4(I,J) + + ELSE IF ( N == IDTNH3 ) THEN + EPA_NEI = EPA_WD_BF_NH3(I,J) + + ELSE + EPA_NEI = 0d0 + + ENDIF + + ELSE + + !--------------------- + ! Weekend avg biofuel + !--------------------- + IF ( N == IDTNOX ) THEN + EPA_NEI = EPA_WE_BF_NOX(I,J) + + ELSE IF ( N == IDTCO ) THEN + EPA_NEI = EPA_WE_BF_CO(I,J) + + ELSE IF ( N == IDTALK4 ) THEN + EPA_NEI = EPA_WE_BF_ALK4(I,J) + + ELSE IF ( N == IDTACET ) THEN + EPA_NEI = EPA_WE_BF_ACET(I,J) + + ELSE IF ( N == IDTMEK ) THEN + EPA_NEI = EPA_WE_BF_MEK(I,J) + + ELSE IF ( N == IDTPRPE ) THEN + EPA_NEI = EPA_WE_BF_PRPE(I,J) + + ELSE IF ( N == IDTC3H8 ) THEN + EPA_NEI = EPA_WE_BF_C3H8(I,J) + + ELSE IF ( N == IDTCH2O ) THEN + EPA_NEI = EPA_WE_BF_CH2O(I,J) + + ELSE IF ( N == IDTC2H6 ) THEN + EPA_NEI = EPA_WE_BF_C2H6(I,J) + + ELSE IF ( N == IDTSO2 ) THEN + EPA_NEI = EPA_WE_BF_SO2(I,J) + + ELSE IF ( N == IDTSO4 ) THEN + EPA_NEI = EPA_WE_BF_SO4(I,J) + + ELSE IF ( N == IDTNH3 ) THEN + EPA_NEI = EPA_WE_BF_NH3(I,J) + + ELSE + EPA_NEI = 0d0 + + ENDIF + + ENDIF + + END FUNCTION GET_EPA_BIOFUEL +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: init_epa_nei +! +! !DESCRIPTION: Subroutine INIT\_EPA\_NEI allocates and zeroes all module +! arrays. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE INIT_EPA_NEI +! +! !USES: +! + USE ERROR_MOD, ONLY : ALLOC_ERR + USE LOGICAL_MOD, ONLY : LNEI99 + USE LOGICAL_MOD, ONLY : LNEI05, LNEI08 + +# include "CMN_SIZE" ! Size parameters +! +! !REMARKS: +! Read EPA/NEI99 anthro + EPA/NEI99 biofuel if LNEI99=T, or +! Read EPA/NEI05 anthro + EPA/NEI99 biofuel if LNEI99=F but LNEI05=T +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER :: AS + + !================================================================= + ! INIT_EPA_NEI begins here! + !================================================================= + + !------------------------------------ + ! Prior to 2/7/11: + ! Return if we LNEI99 = .FALSE. + !IF ( .not. LNEI99 ) RETURN + !------------------------------------ + + ! Return if we have not selected LNEI99 (or LNEI05, since we + ! must read the EPA/NEI99 biofuels when using EPA/NEI05 anthro) + ! (bmy, 2/7/11) + IF ( .not. LNEI99 ) THEN + IF ( .not. LNEI05 ) THEN + IF ( .not. LNEI08 ) RETURN + ENDIF + ENDIF + + ! USA Mask + ALLOCATE( USA_MASK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'USA_MASK' ) + USA_MASK = 0d0 + + !----------------------- + ! Anthro - weekday avg + !----------------------- + IF ( .not. LNEI05 ) THEN + + ALLOCATE( EPA_WD_AN_NOX( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_NOX' ) + EPA_WD_AN_NOX = 0e0 + + ALLOCATE( EPA_WD_AN_CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_CO' ) + EPA_WD_AN_CO = 0e0 + + ALLOCATE( EPA_WD_AN_ALK4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_ALK4' ) + EPA_WD_AN_ALK4 = 0e0 + + ALLOCATE( EPA_WD_AN_ACET( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_ACET' ) + EPA_WD_AN_ACET = 0e0 + + ALLOCATE( EPA_WD_AN_MEK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_MEK' ) + EPA_WD_AN_MEK = 0e0 + + ALLOCATE( EPA_WD_AN_PRPE( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_PRPE' ) + EPA_WD_AN_PRPE = 0e0 + + ALLOCATE( EPA_WD_AN_C2H6( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_C2H6' ) + EPA_WD_AN_C2H6 = 0e0 + + ALLOCATE( EPA_WD_AN_C3H8( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_C3H8' ) + EPA_WD_AN_C3H8 = 0e0 + + ALLOCATE( EPA_WD_AN_CH2O( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_CH2O' ) + EPA_WD_AN_CH2O = 0e0 + + ALLOCATE( EPA_WD_AN_NH3( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_NH3' ) + EPA_WD_AN_NH3 = 0e0 + + ALLOCATE( EPA_WD_AN_SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_SO2' ) + EPA_WD_AN_SO2 = 0e0 + + ALLOCATE( EPA_WD_AN_SO4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_AN_SO4' ) + EPA_WD_AN_SO4 = 0e0 + + ENDIF + + !----------------------- + ! Anthro - weekend avg + !----------------------- + IF ( .not. LNEI05 ) THEN + + ALLOCATE( EPA_WE_AN_NOX( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_NOX' ) + EPA_WE_AN_NOX = 0e0 + + ALLOCATE( EPA_WE_AN_CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_CO' ) + EPA_WE_AN_CO = 0e0 + + ALLOCATE( EPA_WE_AN_ALK4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_ALK4' ) + EPA_WE_AN_ALK4 = 0e0 + + ALLOCATE( EPA_WE_AN_ACET( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_ACET' ) + EPA_WE_AN_ACET = 0e0 + + ALLOCATE( EPA_WE_AN_MEK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_MEK' ) + EPA_WE_AN_MEK = 0e0 + + ALLOCATE( EPA_WE_AN_PRPE( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_PRPE' ) + EPA_WE_AN_PRPE = 0e0 + + ALLOCATE( EPA_WE_AN_C2H6( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_C2H6' ) + EPA_WE_AN_C2H6 = 0e0 + + ALLOCATE( EPA_WE_AN_C3H8( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_C3H8' ) + EPA_WE_AN_C3H8 = 0e0 + + ALLOCATE( EPA_WE_AN_CH2O( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_CH2O' ) + EPA_WE_AN_CH2O = 0e0 + + ALLOCATE( EPA_WE_AN_NH3( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_NH3' ) + EPA_WE_AN_NH3 = 0e0 + + ALLOCATE( EPA_WE_AN_SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_SO2' ) + EPA_WE_AN_SO2 = 0e0 + + ALLOCATE( EPA_WE_AN_SO4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_AN_SO4' ) + EPA_WE_AN_SO4 = 0e0 + + ENDIF + + !----------------------- + ! Biofuel - weekday avg + !----------------------- + ALLOCATE( EPA_WD_BF_NOX( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_NOX' ) + EPA_WD_BF_NOX = 0e0 + + ALLOCATE( EPA_WD_BF_CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_CO' ) + EPA_WD_BF_CO = 0e0 + + ALLOCATE( EPA_WD_BF_ALK4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_ALK4' ) + EPA_WD_BF_ALK4 = 0e0 + + ALLOCATE( EPA_WD_BF_ACET( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_ACET' ) + EPA_WD_BF_ACET = 0e0 + + ALLOCATE( EPA_WD_BF_MEK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_MEK' ) + EPA_WD_BF_MEK = 0e0 + + ALLOCATE( EPA_WD_BF_PRPE( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_PRPE' ) + EPA_WD_BF_PRPE = 0e0 + + ALLOCATE( EPA_WD_BF_C2H6( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_C2H6' ) + EPA_WD_BF_C2H6 = 0e0 + + ALLOCATE( EPA_WD_BF_C3H8( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_C3H8' ) + EPA_WD_BF_C3H8 = 0e0 + + ALLOCATE( EPA_WD_BF_CH2O( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_CH2O' ) + EPA_WD_BF_CH2O = 0e0 + + ALLOCATE( EPA_WD_BF_NH3( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_NH3' ) + EPA_WD_BF_NH3 = 0e0 + + ALLOCATE( EPA_WD_BF_SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_SO2' ) + EPA_WD_BF_SO2 = 0e0 + + ALLOCATE( EPA_WD_BF_SO4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WD_BF_SO4' ) + EPA_WD_BF_SO4 = 0e0 + + !----------------------- + ! Biofuel - weekend avg + !----------------------- + ALLOCATE( EPA_WE_BF_NOX( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_NOX' ) + EPA_WE_BF_NOX = 0e0 + + ALLOCATE( EPA_WE_BF_CO( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_CO' ) + EPA_WE_BF_CO = 0e0 + + ALLOCATE( EPA_WE_BF_ALK4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_ALK4' ) + EPA_WE_BF_ALK4 = 0e0 + + ALLOCATE( EPA_WE_BF_ACET( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_ACET' ) + EPA_WE_BF_ACET = 0e0 + + ALLOCATE( EPA_WE_BF_MEK( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_MEK' ) + EPA_WE_BF_MEK = 0e0 + + ALLOCATE( EPA_WE_BF_PRPE( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_PRPE' ) + EPA_WE_BF_PRPE = 0e0 + + ALLOCATE( EPA_WE_BF_C2H6( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_C2H6' ) + EPA_WE_BF_C2H6 = 0e0 + + ALLOCATE( EPA_WE_BF_C3H8( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_C3H8' ) + EPA_WE_BF_C3H8 = 0e0 + + ALLOCATE( EPA_WE_BF_CH2O( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_CH2O' ) + EPA_WE_BF_CH2O = 0e0 + + ALLOCATE( EPA_WE_BF_NH3( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_NH3' ) + EPA_WE_BF_NH3 = 0e0 + + ALLOCATE( EPA_WE_BF_SO2( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_SO2' ) + EPA_WE_BF_SO2 = 0e0 + + ALLOCATE( EPA_WE_BF_SO4( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /= 0 ) CALL ALLOC_ERR( 'EPA_WE_BF_SO4' ) + EPA_WE_BF_SO4 = 0e0 + + END SUBROUTINE INIT_EPA_NEI +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: cleanup_epa_nei +! +! !DESCRIPTION: Subroutine CLEANUP\_EPA\_NEI deallocates all module arrays +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE CLEANUP_EPA_NEI +! +! !REVISION HISTORY: +! 10 Nov 2004 - R. Hudman - Initial version +! 07 Feb 2011 - R. Yantosca - Added ProTeX headers +!EOP +!------------------------------------------------------------------------------ +!BOC + !================================================================= + ! CLEANUP_EPA_NEI begins here! + !================================================================= + + ! USA mask + IF ( ALLOCATED( USA_MASK ) ) DEALLOCATE( USA_MASK ) + + ! Fossil fuel -- weekday + IF ( ALLOCATED( EPA_WD_AN_NOX ) ) DEALLOCATE( EPA_WD_AN_NOX ) + IF ( ALLOCATED( EPA_WD_AN_CO ) ) DEALLOCATE( EPA_WD_AN_CO ) + IF ( ALLOCATED( EPA_WD_AN_ALK4 ) ) DEALLOCATE( EPA_WD_AN_ALK4 ) + IF ( ALLOCATED( EPA_WD_AN_ACET ) ) DEALLOCATE( EPA_WD_AN_ACET ) + IF ( ALLOCATED( EPA_WD_AN_MEK ) ) DEALLOCATE( EPA_WD_AN_MEK ) + IF ( ALLOCATED( EPA_WD_AN_PRPE ) ) DEALLOCATE( EPA_WD_AN_PRPE ) + IF ( ALLOCATED( EPA_WD_AN_C2H6 ) ) DEALLOCATE( EPA_WD_AN_C2H6 ) + IF ( ALLOCATED( EPA_WD_AN_C3H8 ) ) DEALLOCATE( EPA_WD_AN_C3H8 ) + IF ( ALLOCATED( EPA_WD_AN_C2H6 ) ) DEALLOCATE( EPA_WD_AN_C2H6 ) + IF ( ALLOCATED( EPA_WD_AN_NH3 ) ) DEALLOCATE( EPA_WD_AN_NH3 ) + IF ( ALLOCATED( EPA_WD_AN_SO2 ) ) DEALLOCATE( EPA_WD_AN_SO2 ) + IF ( ALLOCATED( EPA_WD_AN_SO4 ) ) DEALLOCATE( EPA_WD_AN_SO4 ) + + ! Fossil fuel -- weekend + IF ( ALLOCATED( EPA_WE_AN_NOX ) ) DEALLOCATE( EPA_WE_AN_NOX ) + IF ( ALLOCATED( EPA_WE_AN_CO ) ) DEALLOCATE( EPA_WE_AN_CO ) + IF ( ALLOCATED( EPA_WE_AN_ALK4 ) ) DEALLOCATE( EPA_WE_AN_ALK4 ) + IF ( ALLOCATED( EPA_WE_AN_ACET ) ) DEALLOCATE( EPA_WE_AN_ACET ) + IF ( ALLOCATED( EPA_WE_AN_MEK ) ) DEALLOCATE( EPA_WE_AN_MEK ) + IF ( ALLOCATED( EPA_WE_AN_PRPE ) ) DEALLOCATE( EPA_WE_AN_PRPE ) + IF ( ALLOCATED( EPA_WE_AN_C2H6 ) ) DEALLOCATE( EPA_WE_AN_C2H6 ) + IF ( ALLOCATED( EPA_WE_AN_C3H8 ) ) DEALLOCATE( EPA_WE_AN_C3H8 ) + IF ( ALLOCATED( EPA_WE_AN_C2H6 ) ) DEALLOCATE( EPA_WE_AN_C2H6 ) + IF ( ALLOCATED( EPA_WE_AN_NH3 ) ) DEALLOCATE( EPA_WE_AN_NH3 ) + IF ( ALLOCATED( EPA_WE_AN_SO2 ) ) DEALLOCATE( EPA_WE_AN_SO2 ) + IF ( ALLOCATED( EPA_WE_AN_SO4 ) ) DEALLOCATE( EPA_WE_AN_SO4 ) + + ! Biofuel -- weekday + IF ( ALLOCATED( EPA_WD_BF_NOX ) ) DEALLOCATE( EPA_WD_BF_NOX ) + IF ( ALLOCATED( EPA_WD_BF_CO ) ) DEALLOCATE( EPA_WD_BF_CO ) + IF ( ALLOCATED( EPA_WD_BF_ALK4 ) ) DEALLOCATE( EPA_WD_BF_ALK4 ) + IF ( ALLOCATED( EPA_WD_BF_ACET ) ) DEALLOCATE( EPA_WD_BF_ACET ) + IF ( ALLOCATED( EPA_WD_BF_MEK ) ) DEALLOCATE( EPA_WD_BF_MEK ) + IF ( ALLOCATED( EPA_WD_BF_PRPE ) ) DEALLOCATE( EPA_WD_BF_PRPE ) + IF ( ALLOCATED( EPA_WD_BF_C2H6 ) ) DEALLOCATE( EPA_WD_BF_C2H6 ) + IF ( ALLOCATED( EPA_WD_BF_C3H8 ) ) DEALLOCATE( EPA_WD_BF_C3H8 ) + IF ( ALLOCATED( EPA_WD_BF_C2H6 ) ) DEALLOCATE( EPA_WD_BF_C2H6 ) + IF ( ALLOCATED( EPA_WD_BF_NH3 ) ) DEALLOCATE( EPA_WD_BF_NH3 ) + IF ( ALLOCATED( EPA_WD_BF_SO2 ) ) DEALLOCATE( EPA_WD_BF_SO2 ) + IF ( ALLOCATED( EPA_WD_BF_SO4 ) ) DEALLOCATE( EPA_WD_BF_SO4 ) + + ! Biofuel -- weekend + IF ( ALLOCATED( EPA_WE_BF_NOX ) ) DEALLOCATE( EPA_WE_BF_NOX ) + IF ( ALLOCATED( EPA_WE_BF_CO ) ) DEALLOCATE( EPA_WE_BF_CO ) + IF ( ALLOCATED( EPA_WE_BF_ALK4 ) ) DEALLOCATE( EPA_WE_BF_ALK4 ) + IF ( ALLOCATED( EPA_WE_BF_ACET ) ) DEALLOCATE( EPA_WE_BF_ACET ) + IF ( ALLOCATED( EPA_WE_BF_MEK ) ) DEALLOCATE( EPA_WE_BF_MEK ) + IF ( ALLOCATED( EPA_WE_BF_PRPE ) ) DEALLOCATE( EPA_WE_BF_PRPE ) + IF ( ALLOCATED( EPA_WE_BF_C2H6 ) ) DEALLOCATE( EPA_WE_BF_C2H6 ) + IF ( ALLOCATED( EPA_WE_BF_C3H8 ) ) DEALLOCATE( EPA_WE_BF_C3H8 ) + IF ( ALLOCATED( EPA_WE_BF_C2H6 ) ) DEALLOCATE( EPA_WE_BF_C2H6 ) + IF ( ALLOCATED( EPA_WE_BF_NH3 ) ) DEALLOCATE( EPA_WE_BF_NH3 ) + IF ( ALLOCATED( EPA_WE_BF_SO2 ) ) DEALLOCATE( EPA_WE_BF_SO2 ) + IF ( ALLOCATED( EPA_WE_BF_SO4 ) ) DEALLOCATE( EPA_WE_BF_SO4 ) + + END SUBROUTINE CLEANUP_EPA_NEI +!EOC + END MODULE EPA_NEI_MOD diff --git a/code/error_mod.f b/code/error_mod.f new file mode 100644 index 0000000..b4ec9d4 --- /dev/null +++ b/code/error_mod.f @@ -0,0 +1,1143 @@ +! $Id: error_mod.f,v 1.2 2011/02/23 00:08:47 daven Exp $ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: error_mod.f +! +! !DESCRIPTION: Module ERROR\_MOD contains error checking routines. +!\\ +!\\ +! !INTERFACE: +! + MODULE ERROR_MOD +! +! !USES: +! + IMPLICIT NONE + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: ALLOC_ERR + PUBLIC :: CHECK_VALUE + PUBLIC :: DEBUG_MSG + PUBLIC :: ERROR_STOP + PUBLIC :: GEOS_CHEM_STOP + PUBLIC :: IS_SAFE_DIV + PUBLIC :: IS_SAFE_EXP + PUBLIC :: IT_IS_NAN + PUBLIC :: IT_IS_FINITE + PUBLIC :: SAFE_DIV + PUBLIC :: SAFE_EXP + PUBLIC :: SAFE_LOG + PUBLIC :: SAFE_LOG10 + + ! Interface for NaN-check routines + INTERFACE IT_IS_NAN + MODULE PROCEDURE NAN_FLOAT + MODULE PROCEDURE NAN_DBLE + END INTERFACE + + ! Interface for finite-check routines + INTERFACE IT_IS_FINITE + MODULE PROCEDURE FINITE_FLOAT + MODULE PROCEDURE FINITE_DBLE + END INTERFACE + + ! Interface for check-value routines + INTERFACE CHECK_VALUE + MODULE PROCEDURE CHECK_REAL_VALUE + MODULE PROCEDURE CHECK_DBLE_VALUE + END INTERFACE +! +! !PRIVATE MEMBER FUNCTIONS: +! + PRIVATE :: CHECK_DBLE_VALUE + PRIVATE :: CHECK_REAL_VALUE + PRIVATE :: FINITE_DBLE + PRIVATE :: FINITE_FLOAT + PRIVATE :: NAN_DBLE + PRIVATE :: NAN_FLOAT +! +! !REVISION HISTORY: +! 08 Mar 2001 - R. Yantosca - Initial version +! (1 ) Added subroutines CHECK_REAL_VALUE and CHECK_DBLE_VALUE, which are +! overloaded by interface CHECK_VALUE. This is a convenience +! so that you don't have to always call IT_IS_NAN directly. +! (bmy, 6/13/01) +! (2 ) Updated comments (bmy, 9/4/01) +! (3 ) Now use correct values for bit masking in FINITE_FLOAT for the +! ALPHA platform (bmy, 11/15/01) +! (4 ) Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Also add MODULE INTERFACES section, +! since we have an interface here. (bmy, 5/28/02) +! (5 ) Add NaN and infinity error checking for Linux platform (bmy, 3/22/02) +! (6 ) Added routines ERROR_STOP, GEOS_CHEM_STOP, and ALLOC_ERR to this +! module. Also improved CHECK_STT. (bmy, 11/27/02) +! (7 ) Minor bug fixes in FORMAT statements. Renamed cpp switch from +! DEC_COMPAQ to COMPAQ. Also added code to trap errors on SUN +! platform. (bmy, 3/21/03) +! (8 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03) +! (9 ) Bug fixes for LINUX platform (bmy, 9/29/03) +! (10) Now supports INTEL_FC compiler (bmy, 10/24/03) +! (11) Changed the name of some cpp switches in "define.h" (bmy, 12/2/03) +! (12) Minor fix for LINUX_IFC and LINUX_EFC (bmy, 1/24/04) +! (13) Do not flush buffer for LINUX_EFC in ERROR_STOP (bmy, 4/6/04) +! (14) Move CHECK_STT routine to "tracer_mod.f" (bmy, 7/20/04) +! (15) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05) +! (16) Now print IFORT error messages for Intel v8/v9 compiler (bmy, 11/30/05) +! (17) Cosmetic change in DEBUG_MSG (bmy, 4/10/06) +! (18) Remove support for LINUX_IFC and LINUX_EFC compilers (bmy, 8/4/06) +! (19) Now use intrinsic functions for IFORT, remove C routines (bmy, 8/14/07) +! (20) Added routine SAFE_DIV (phs, bmy, 2/26/08) +! (21) Added routine IS_SAFE_DIV (phs, bmy, 6/11/08) +! (22) Updated routine SAFE_DIV (phs, 4/14/09) +! (23) Remove support for SGI, COMPAQ compilers (bmy, 7/8/09) +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +! 04 Jan 2010 - R. Yantosca - Added SAFE_EXP and IS_SAFE_EXP functions +! 04 Jan 2010 - R. Yantosca - Added SAVE_LOG and SAFE_LOG10 functions +!EOP +!------------------------------------------------------------------------------ +!BOC + CONTAINS +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: nan_float +! +! !DESCRIPTION: Function NAN\_FLOAT returns TRUE if a REAL*4 number is equal +! to the IEEE NaN (Not-a-Number) flag. Returns FALSE otherwise. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION NAN_FLOAT( VALUE ) RESULT( IT_IS_A_NAN ) +! +! !USES: +! +# include "define.h" + +#if defined( IBM_AIX ) || defined( IBM_XLF ) + USE IEEE_ARITHMETIC +#endif +! +! !INPUT PARAMETERS: +! + REAL*4, INTENT(IN) :: VALUE ! Value to be tested for NaN +! +! !RETURN VALUE: +! + LOGICAL :: IT_IS_A_NAN ! =T if VALUE is NaN; =F otherwise +! +! !REVISION HISTORY: +! (1 ) Is overloaded by interface "IT_IS_NAN". +! (2 ) Now call C routine is_nan(x) for Linux platform (bmy, 6/13/02) +! (3 ) Eliminate IF statement in Linux section. Also now trap NaN on +! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to +! COMPAQ. (bmy, 3/23/03) +! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03) +! (5 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03) +! (6 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC, +! and added LINUX_EFC. (bmy, 12/2/03) +! (7 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05) +! (8 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06) +! (9 ) Now use ISNAN for Linux/IFORT compiler (bmy, 8/14/07) +! (10) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch. +! (bmy, 7/8/09) +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + +#if defined( LINUX_IFORT ) + IT_IS_A_NAN = ISNAN( VALUE ) + +#elif defined( LINUX_PGI ) + + ! Declare IS_NAN as an external function + INTEGER, EXTERNAL :: IS_NAN + + ! For LINUX or INTEL_FC compilers, use C routine "is_nan" to test if + ! VALUE is NaN. VALUE must be cast to DBLE since "is_nan" only + ! takes doubles. + IT_IS_A_NAN = ( IS_NAN( DBLE( VALUE ) ) /= 0 ) + +#elif defined( SPARC ) +!----------------------------------------------------------------------------- +! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this +! will turn on -ftrap=common, which checks for NaN, invalid, division, and +! inexact IEEE math errors. (bmy, 12/18/07) +! +! ! Declare IR_ISNAN as an external function +! INTEGER, EXTERNAL :: IR_ISNAN +! +! ! Test if VALUE is a NaN +! IT_IS_A_NAN = ( IR_ISNAN( VALUE ) /= 0 ) +!----------------------------------------------------------------------------- + IT_IS_A_NAN = .FALSE. + +#elif defined( IBM_AIX ) || defined( IBM_XLF ) + + ! For IBM/AIX platform + IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN + IT_IS_A_NAN = IEEE_IS_NAN( VALUE ) + ENDIF + +#endif + + ! Return to calling program + END FUNCTION NAN_FLOAT +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: nan_dble +! +! !DESCRIPTION: Function NAN\_DBLE returns TRUE if a REAL*8 number is equal +! to the IEEE NaN (Not-a-Number) flag. Returns FALSE otherwise. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION NAN_DBLE( VALUE ) RESULT( IT_IS_A_NAN ) +! +! !USES: +! +# include "define.h" + +#if defined( IBM_AIX ) || defined( IBM_XLF ) + USE IEEE_ARITHMETIC +#endif +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: VALUE ! Value to be tested for NaN +! +! !RETURN VALUE: +! + LOGICAL :: IT_IS_A_NAN ! =T if VALUE is NaN; =F otherwise +! +! !REVISION HISTORY: +! (1 ) Is overloaded by interface "IT_IS_NAN". +! (2 ) Now call C routine is_nan(x) for Linux platform (bmy, 6/13/02) +! (3 ) Eliminate IF statement in Linux section. Also now trap NaN on +! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to +! COMPAQ. (bmy, 3/23/03) +! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03) +! (5 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03) +! (6 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC, +! and added LINUX_EFC. (bmy, 12/2/03) +! (7 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05) +! (8 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06) +! (9 ) Now use ISNAN for Linux/IFORT compiler (bmy, 8/14/07) +! (10) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch. +! (bmy, 7/8/09) +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC +! +#if defined( LINUX_IFORT ) + IT_IS_A_NAN = ISNAN( VALUE ) + +#elif defined( LINUX_PGI ) + + ! Declare IS_NAN as an external function + INTEGER, EXTERNAL :: IS_NAN + + ! For LINUX or INTEL_FC compilers, use C routine + ! "is_nan" to test if VALUE is NaN. + IT_IS_A_NAN = ( IS_NAN( VALUE ) /= 0 ) + +#elif defined( SPARC ) +!----------------------------------------------------------------------------- +! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this +! will turn on -ftrap=common, which checks for NaN, invalid, division, and +! inexact IEEE math errors. (bmy, 12/18/07) +! +! ! Declare ID_ISNAN as an external function +! INTEGER, EXTERNAL :: ID_ISNAN +! +! ! Test if VALUE is NaN +! IT_IS_A_NAN = ( ID_ISNAN( VALUE ) /= 0 ) +!----------------------------------------------------------------------------- + IT_IS_A_NAN = .FALSE. + +#elif defined( IBM_AIX ) || defined( IBM_XLF ) + + ! For IBM/AIX platform + IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN + IT_IS_A_NAN = IEEE_IS_NAN( VALUE ) + ENDIF + +#endif + + ! Return to calling program + END FUNCTION NAN_DBLE +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: finite_float +! +! !DESCRIPTION: Function FINITE\_FLOAT returns FALSE if a REAL*4 number is +! equal to the IEEE Infinity flag. Returns TRUE otherwise. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION FINITE_FLOAT( VALUE ) RESULT( IT_IS_A_FINITE ) +! +! !USES: +! +# include "define.h" + +#if defined( IBM_AIX ) || defined( IBM_XLF ) + USE IEEE_ARITHMETIC +#endif +! +! !INPUT PARAMETERS: +! + REAL*4, INTENT(IN) :: VALUE ! Value to be tested for infinity +! +! !RETURN VALUE: +! + LOGICAL :: IT_IS_A_FINITE ! =T if VALUE is finite; =F else +! +! !REVISION HISTORY: +! (1 ) Is overloaded by interface "IT_IS_FINITE". +! (2 ) Now use correct values for bit masking (bmy, 11/15/01) +! (3 ) Eliminate IF statement in Linux section. Also now trap Infinity on +! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to +! COMPAQ. (bmy, 3/23/03) +! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03) +! (5 ) Bug fix: now use external C IS_FINITE for PGI/Linux (bmy, 9/29/03) +! (6 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03) +! (7 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC, +! and added LINUX_EFC. (bmy, 12/2/03) +! (8 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05) +! (9 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06) +! (10) Now use FP_CLASS for IFORT compiler (bmy, 8/14/07) +! (11) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch. +! (bmy, 7/8/09) +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + +#if defined( LINUX_IFORT ) + + ! Local variables (parameters copied from "fordef.for") + INTEGER, PARAMETER :: SNAN=0, QNAN=1, POS_INF=2, NEG_INF=3 + INTEGER :: FPC + + ! Get the floating point type class for VALUE + FPC = FP_CLASS( VALUE ) + + ! VALUE is infinite if it is either +Inf or -Inf + ! Also flag an error if VALUE is a signaling or quiet NaN + IT_IS_A_FINITE = ( FPC /= POS_INF .and. FPC /= NEG_INF .and. + & FPC /= SNAN .and. FPC /= QNAN ) + +#elif defined( LINUX_PGI ) + + ! Declare IS_FINITE as an external function + INTEGER, EXTERNAL :: IS_FINITE + + ! For LINUX or INTEL_FC compilers use C routine "is_finite" to test + ! if VALUE is finite. VALUE must be cast to DBLE since "is_inf" + ! only takes doubles. + IT_IS_A_FINITE = ( IS_FINITE( DBLE( VALUE ) ) /= 0 ) + +#elif defined( SPARC ) +!----------------------------------------------------------------------------- +! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this +! will turn on -ftrap=common, which checks for NaN, invalid, division, and +! inexact IEEE math errors. (bmy, 12/18/07) +! ! Declare IR_FINITE as an external function +! INTEGER, EXTERNAL :: IR_FINITE +! +! ! Test if VALUE is a finite number +! IT_IS_A_FINITE = ( IR_FINITE( VALUE ) /= 0 ) +!----------------------------------------------------------------------------- + IT_IS_A_FINITE = .TRUE. + +#elif defined( IBM_AIX ) || defined( IBM_XLF ) + + ! For IBM/AIX platform + IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN + IT_IS_A_FINITE = IEEE_IS_FINITE( VALUE ) + ENDIF + +#endif + + ! Return to calling program + END FUNCTION FINITE_FLOAT +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: finite_dble +! +! !DESCRIPTION: Function FINITE\_FLOAT returns FALSE if a REAL*8 number is +! equal to the IEEE Infinity flag. Returns TRUE otherwise. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION FINITE_DBLE( VALUE ) RESULT( IT_IS_A_FINITE ) +! +! !USES: +! +# include "define.h" + +#if defined( IBM_AIX ) || defined( IBM_XLF ) + USE IEEE_ARITHMETIC +#endif +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: VALUE ! Value to be tested for infinity +! +! !RETURN VALUE: +! + LOGICAL :: IT_IS_A_FINITE ! =T if VALUE is finite; =F else +! +! !REVISION HISTORY: +! (1 ) Is overloaded by interface "IT_IS_FINITE". +! (2 ) Now use correct values for bit masking (bmy, 11/15/01) +! (3 ) Eliminate IF statement in Linux section. Also now trap Infinity on +! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to +! COMPAQ. (bmy, 3/23/03) +! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03) +! (5 ) Bug fix: now use external C IS_FINITE for PGI/Linux (bmy, 9/29/03) +! (6 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03) +! (7 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC, +! and added LINUX_EFC. (bmy, 12/2/03) +! (8 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05) +! (9 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06) +! (10) Now use FP_CLASS for IFORT compiler (bmy, 8/14/07) +! (11) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch. +! (bmy, 7/8/09) +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + +#if defined( LINUX_IFORT ) + + ! Local variables (parameters copied from "fordef.for") + INTEGER, PARAMETER :: SNAN=0, QNAN=1, POS_INF=2, NEG_INF=3 + INTEGER :: FPC + + ! Get the floating point type class for VALUE + FPC = FP_CLASS( VALUE ) + + ! VALUE is infinite if it is either +Inf or -Inf + ! Also flag an error if VALUE is a signaling or quiet NaN + IT_IS_A_FINITE = ( FPC /= POS_INF .and. FPC /= NEG_INF .and. + & FPC /= SNAN .and. FPC /= QNAN ) + +#elif defined( LINUX_PGI ) + + ! Declare IS_FINITE as an external function + INTEGER, EXTERNAL :: IS_FINITE + + ! For LINUX or INTEL_FC compilers, use C routine + ! "is_finite" to test if VALUE is infinity + IT_IS_A_FINITE = ( IS_FINITE( VALUE ) /= 0 ) + +#elif defined( SPARC ) +!----------------------------------------------------------------------------- +! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this +! will turn on -ftrap=common, which checks for NaN, invalid, division, and +! inexact IEEE math errors. (bmy, 12/18/07) +! +! ! Declare ID_FINITE as an external function +! INTEGER, EXTERNAL :: ID_FINITE +! +! ! Test if VALUE is a finite number +! IT_IS_A_FINITE = ( ID_FINITE( VALUE ) /= 0 ) +!----------------------------------------------------------------------------- + IT_IS_A_FINITE = .TRUE. + +#elif defined( IBM_AIX ) || defined( IBM_XLF ) + + ! For IBM/AIX platform + IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN + IT_IS_A_FINITE = IEEE_IS_FINITE( VALUE ) + ENDIF + +#endif + + ! Return to calling program + END FUNCTION FINITE_DBLE +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: check_real_value +! +! !DESCRIPTION: Subroutine CHECK\_REAL\_VALUE checks to make sure a REAL*4 +! value is not NaN or Infinity. This is a wrapper for the interfaces +! IT\_IS\_NAN and IT\_IS\_FINITE. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE CHECK_REAL_VALUE( VALUE, LOCATION, VARNAME, MESSAGE ) +! +! !INPUT PARAMETERS: +! + REAL*4, INTENT(IN) :: VALUE ! Value to be checked + CHARACTER(LEN=255), INTENT(IN) :: VARNAME ! Name of variable + CHARACTER(LEN=255), INTENT(IN) :: MESSAGE ! Short descriptive msg + INTEGER, INTENT(IN) :: LOCATION(4) ! (/ I, J, L, N /) indices +! +! !REVISION HISTORY: +! 13 Jun 2001 - R. Yantosca - Initial version +! 15 Oct 2002 - R. Yantosca - Now call GEOS_CHEM_STOP to shutdown safely +! 15 Oct 2002 - R. Yantosca - Updated comments, cosmetic changes +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + ! First check for NaN -- print info & stop run if found + IF ( IT_IS_NAN( VALUE ) ) THEN + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 110 ) TRIM( VARNAME ) + WRITE( 6, 115 ) LOCATION + WRITE( 6, '(a)' ) TRIM( MESSAGE ) + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + CALL GEOS_CHEM_STOP + ENDIF + + ! Next check for infinity -- print info & stop run if found + IF ( .not. IT_IS_FINITE( VALUE ) ) THEN + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 120 ) TRIM( VARNAME ) + WRITE( 6, 115 ) LOCATION + WRITE( 6, '(f13.6)' ) VALUE + WRITE( 6, '(a)' ) TRIM ( MESSAGE ) + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + CALL GEOS_CHEM_STOP + ENDIF + + ! FORMAT statements + 110 FORMAT( 'CHECK_VALUE: ', a, ' is NaN!' ) + 115 FORMAT( 'Grid box (I,J,L,N) : ', 4i4 ) + 120 FORMAT( 'CHECK_VALUE: ', a, ' is not finite!' ) + + ! Return to calling program + END SUBROUTINE CHECK_REAL_VALUE +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: check_dble_value +! +! !DESCRIPTION: Subroutine CHECK\_DBLE\_VALUE checks to make sure a REAL*4 +! value is not NaN or Infinity. This is a wrapper for the interfaces +! IT\_IS\_NAN and IT\_IS\_FINITE. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE CHECK_DBLE_VALUE( VALUE, LOCATION, VARNAME, MESSAGE ) +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: VALUE ! Value to be checked + CHARACTER(LEN=255), INTENT(IN) :: VARNAME ! Name of variable + CHARACTER(LEN=255), INTENT(IN) :: MESSAGE ! Short descriptive msg + INTEGER, INTENT(IN) :: LOCATION(4) ! (/ I, J, L, N /) indices +! +! !REVISION HISTORY: +! 13 Jun 2001 - R. Yantosca - Initial version +! 15 Oct 2002 - R. Yantosca - Now call GEOS_CHEM_STOP to shutdown safely +! 15 Oct 2002 - R. Yantosca - Updated comments, cosmetic changes +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + ! First check for NaN + IF ( IT_IS_NAN( VALUE ) )THEN + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 110 ) TRIM( VARNAME ) + WRITE( 6, 115 ) LOCATION + WRITE( 6, '(a)' ) TRIM( MESSAGE ) + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + CALL GEOS_CHEM_STOP + ENDIF + + ! Next check for infinity + IF ( .not. IT_IS_FINITE( VALUE ) ) THEN + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, 120 ) TRIM( VARNAME ) + WRITE( 6, 115 ) LOCATION + WRITE( 6, '(f13.6)' ) VALUE + WRITE( 6, '(a)' ) TRIM ( MESSAGE ) + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + CALL GEOS_CHEM_STOP + ENDIF + + ! FORMAT statements + 110 FORMAT( 'CHECK_VALUE: ', a, ' is NaN!' ) + 115 FORMAT( 'Grid box (I,J,L,N) : ', 4i4 ) + 120 FORMAT( 'CHECK_VALUE: ', a, ' is not finite!' ) + + ! Return to calling program + END SUBROUTINE CHECK_DBLE_VALUE +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: error_stop +! +! !DESCRIPTION: Subroutine ERROR\_STOP is a wrapper for GEOS\_CHEM\_STOP. It +! prints an error message then calls GEOS\_CHEM\_STOP to free memory and quit. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE ERROR_STOP( MESSAGE, LOCATION ) +! +! !INPUT PARAMETERS: +! + CHARACTER(LEN=*), INTENT(IN) :: MESSAGE ! Error msg to print + CHARACTER(LEN=*), INTENT(IN) :: LOCATION ! Where ERROR_STOP is called +! +! !REVISION HISTORY: +! 15 Oct 2002 - R. Yantosca - Initial version +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + +!$OMP CRITICAL + + ! Write msg + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a)' ) 'GEOS-CHEM ERROR: ' // TRIM( MESSAGE ) + WRITE( 6, '(a)' ) 'STOP at ' // TRIM( LOCATION ) + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + +!$OMP END CRITICAL + + ! Deallocate memory and stop the run + CALL GEOS_CHEM_STOP + + ! Return to calling program + END SUBROUTINE ERROR_STOP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: geos_chem_stop +! +! !DESCRIPTION: Subroutine GEOS\_CHEM\_STOP calls CLEANUP to deallocate all +! module arrays and then stops the run. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE GEOS_CHEM_STOP +! +! !USES: +! +# include "define.h" + +! !REVISION HISTORY: +! 15 Oct 2002 - R. Yantosca - Initial version +! 20 Nov 2009 - R. Yantosca - Now EXIT works for LINUX_IFC, LINUX_EFC, +! so remove #if block. +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + +!$OMP CRITICAL + + ! Deallocate all module arrays + CALL CLEANUP + + ! Flush all files and stop + CALL EXIT( 99999 ) + +!$OMP END CRITICAL + + ! End of program + END SUBROUTINE GEOS_CHEM_STOP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: alloc_err +! +! !DESCRIPTION: Subroutine ALLOC\_ERR prints an error message if there is not +! enough memory to allocate a particular allocatable array. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE ALLOC_ERR( ARRAYNAME, AS ) +! +! !USES: +! +# include "define.h" +! +! !INPUT PARAMETERS: +! + CHARACTER(LEN=*), INTENT(IN) :: ARRAYNAME ! Name of array + INTEGER, OPTIONAL, INTENT(IN) :: AS ! Error output from "STAT" +! +! !REVISION HISTORY: +! 26 Jun 2000 - R. Yantosca - Initial version, split off from "ndxx_setup.f" +! 15 Oct 2002 - R. Yantosca - Added to "error_mod.f" +! 30 Nov 2005 - R. Yantosca - Call IFORT_ERRMSG for Intel Fortran compiler +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + CHARACTER(LEN=255) :: ERRMSG + + !================================================================= + ! ALLOC_ERR begins here! + !================================================================= + +#if defined( LINUX_IFORT ) + + !----------------------- + ! Linux/IFORT compiler + !----------------------- + + ! More local variables + CHARACTER(LEN=255) :: IFORT_ERRMSG, MSG + + ! Define error message + ERRMSG = 'Allocation error in array: ' // TRIM( ARRAYNAME ) + + ! If we have passed the allocation status argument ... + IF ( PRESENT( AS ) ) THEN + + ! Get IFORT error message + MSG = IFORT_ERRMSG( AS ) + + ! Append IFORT error message + ERRMSG = TRIM( ERRMSG ) // ' :: ' // TRIM( MSG ) + + ENDIF + +#else + + !----------------------- + ! All other compilers + !----------------------- + + ! Define error message + ERRMSG = 'Allocation error in array: ' // TRIM( ARRAYNAME ) + +#endif + + ! Print error message, deallocate memory, and stop the run + CALL ERROR_STOP( ERRMSG, 'alloc_err.f' ) + + ! End of subroutine + END SUBROUTINE ALLOC_ERR +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: debug_msg +! +! !DESCRIPTION: Subroutine DEBUG\_MSG prints a message to the stdout buffer +! and flushes. This is useful for determining the exact location where +! errors occur. +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE DEBUG_MSG( MESSAGE ) +! +! !USES: +! +# include "define.h" +! +! !INPUT PARAMETERS: +! + CHARACTER(LEN=*), INTENT(IN) :: MESSAGE ! Message to print +! +! !REVISION HISTORY: +! 07 Jan 2002 - R. Yantosca - Initial version +! (1 ) Now just write the message and flush the buffer (bmy, 7/5/01) +! (2 ) Renamed from "paftop.f" to "debug_msg.f" (bmy, 1/7/02) +! (3 ) Bundled into "error_mod.f" (bmy, 11/22/02) +! (4 ) Now do not FLUSH the buffer for EFC compiler (bmy, 4/6/04) +! (5 ) Now add a little space for debug output (bmy, 4/10/06) +! (6 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06) +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + + ! Print message + WRITE( 6, '(5x,a)' ) MESSAGE + + ! Call FLUSH routine to flush the output buffer + CALL FLUSH( 6 ) + + ! Return to calling program + END SUBROUTINE DEBUG_MSG +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: safe_div +! +! !DESCRIPTION: Function SAFE\_DIV performs "safe division", that is to +! prevent overflow, underlow, NaN, or infinity errors. An alternate value +! is returned if the division cannot be performed. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION SAFE_DIV( N, D, + & ALT_NAN, ALT_OVER, + & ALT_UNDER ) RESULT( Q ) +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: N ! Numerator + REAL*8, INTENT(IN) :: D ! Denominator + REAL*8, INTENT(IN) :: ALT_NAN ! Alternate value to be + ! returned if the division + ! is either NAN (0/0) or + ! leads to overflow (i.e., + ! a too large number) + REAL*8, OPTIONAL, INTENT(IN) :: ALT_OVER ! Alternate value to be + ! returned if the division + ! leads to overflow (default + ! is ALT_NAN) + REAL*8, OPTIONAL, INTENT(IN) :: ALT_UNDER ! Alternate value to be + ! returned if the division + ! leads to underflow + ! (default is 0, but you + ! could use TINY() if you + ! want a non-zero result). +! +! !RETURN VALUE: +! + REAL*8 :: Q ! Output from the division + +! +! !REMARKS: +! For more information, see the discussion on: +! http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/8b367f44c419fa1d/ +! +! !REVISION HISTORY: +! 26 Feb 2008 - P. Le Sager & R. Yantosca - Initial version +! (1) Now can return different alternate values if NAN (that is 0/0), +! overflow (that is a too large number), or too small (that is greater +! than 0 but less than smallest possible number). Default value is +! zero in case of underflow (phs, 4/14/09) +! (2) Some compiler options flush underflows to zero (-ftz for IFort). +! To think about it (phs, 4/14/09) +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC + + IF ( N==0 .and. D==0 ) THEN + + ! NAN + Q = ALT_NAN + + ELSE IF ( EXPONENT(N) - EXPONENT(D) >= MAXEXPONENT(N) .OR. + & D==0 ) THEN + + ! OVERFLOW + Q = ALT_NAN + IF ( PRESENT(ALT_OVER) ) Q = ALT_OVER + + ELSE IF ( EXPONENT(N) - EXPONENT(D) <= MINEXPONENT(N) ) THEN + + ! UNDERFLOW + Q = 0D0 + IF ( PRESENT(ALT_UNDER) ) Q = ALT_UNDER + + ELSE + + ! No problem + Q = N / D + + ENDIF + + ! Return to calling program + END FUNCTION SAFE_DIV +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: is_safe_div +! +! !DESCRIPTION: Function IS\_SAFE\_DIV tests for "safe division", that is +! check if the division will overflow/underflow or hold NaN. .FALSE. is +! returned if the division cannot be performed. (phs, 6/11/08) +!\\ +!\\ +! !INTERFACE: +! + FUNCTION IS_SAFE_DIV( N, D, R4 ) RESULT( F ) +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: N ! Numerator + REAL*8, INTENT(IN) :: D ! Denominator + LOGICAL, INTENT(IN), OPTIONAL :: R4 ! Logical flag to use the limits + ! of REAL*4 to define underflow + ! or overflow. Extra defensive. +! +! !OUTPUT PARAMETERS: +! + LOGICAL :: F ! =F if division isn't allowed + ! =T otherwise +! +! !REMARKS: +! UnderFlow, OverFlow and NaN are tested for. If you need to +! differentiate between the three, use the SAFE_DIV (phs, 4/14/09) +! +! !REVISION HISTORY: +! 11 Jun 2008 - P. Le Sager - Initial version +! 20 Nov 2009 - R. Yantosca - Added ProTeX header +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + INTEGER MaxExp, MinExp + REAL*4 RR + + !================================================================== + ! IS_SAFE_DIV begins here! + !================================================================== + + MaxExp = MAXEXPONENT( N ) + MinExp = MINEXPONENT( N ) + + IF ( PRESENT( R4 ) ) THEN + IF ( R4 ) THEN + MaxExp = MAXEXPONENT( RR ) + MinExp = MINEXPONENT( RR ) + ENDIF + ENDIF + + IF ( EXPONENT(N) - EXPONENT(D) >= MaxExp .or. D==0 .or. + & EXPONENT(N) - EXPONENT(D) <= MinExp ) THEN + F = .FALSE. + ELSE + F = .TRUE. + ENDIF + + ! Return to calling program + END FUNCTION IS_SAFE_DIV +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: safe_exp +! +! !DESCRIPTION: Function SAFE\_EXP performs a "safe exponential", that is to +! prevent overflow, underlow, NaN, or infinity errors when taking the +! value EXP( x ). An alternate value is returned if the exponential +! cannot be performed. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION SAFE_EXP( X, ALT ) RESULT( VALUE ) +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: X ! Argument of EXP + REAL*8, INTENT(IN) :: ALT ! Alternate value to be returned +! +! !RETURN VALUE: +! + REAL*8 :: VALUE ! Output from the exponential +! +! !REVISION HISTORY: +! 04 Jan 2010 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC + IF ( IS_SAFE_EXP( X ) ) THEN + VALUE = EXP( X ) + ELSE + VALUE = ALT + ENDIF + + END FUNCTION SAFE_EXP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: is_safe_exp +! +! !DESCRIPTION: Function IS\_SAFE\_EXP returns TRUE if it is safe to take +! the value EXP( x ) without encountering a floating point exception. FALSE +! is returned if the exponential cannot be performed. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION IS_SAFE_EXP( X ) RESULT( F ) +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: X ! Argument to the exponential function +! +! !OUTPUT PARAMETERS: +! + LOGICAL :: F ! =F if exponential isn't allowed + ! =T otherwise +! +! !REMARKS: +! Empirical testing has revealed that -600 < X < 600 will not result in +! a floating-point exception on Sun and IFORT compilers. This is good +! enough for most purposes. +! +! !REVISION HISTORY: +! 04 Jan 2010 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !DEFINED PARAMETERS: +! + REAL*8, PARAMETER :: CUTOFF = 600d0 + + ! If -CUTOFF < x < CUTOFF, then it is safe to take EXP( x ) + F = ( ABS( X ) < CUTOFF ) + + END FUNCTION IS_SAFE_EXP +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: safe_log +! +! !DESCRIPTION: Function SAFE\_LOG performs a "safe natural logarithm", that +! is to prevent overflow, underlow, NaN, or infinity errors when taking the +! value LOG( x ). An alternate value is returned if the logarithm +! cannot be performed. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION SAFE_LOG( X, ALT ) RESULT( VALUE ) +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: X ! Argument of LOG + REAL*8, INTENT(IN) :: ALT ! Alternate value to be returned +! +! !RETURN VALUE: +! + REAL*8 :: VALUE ! Output from the natural logarithm +! +! !REVISION HISTORY: +! 04 Jan 2010 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !DEFINED PARAMETERS: +! + IF ( X > 0d0 ) THEN + VALUE = LOG( X ) ! Take LOG(x) for positive-definite X + ELSE + VALUE = ALT ! Otherwise return alternate value + ENDIF + + END FUNCTION SAFE_LOG +!EOC +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: safe_log10 +! +! !DESCRIPTION: Function SAFE\_LOG10 performs a "safe log10", that +! is to prevent overflow, underlow, NaN, or infinity errors when taking the +! value LOG10( x ). An alternate value is returned if the logarithm +! cannot be performed. +!\\ +!\\ +! !INTERFACE: +! + FUNCTION SAFE_LOG10( X, ALT ) RESULT( VALUE ) +! +! !INPUT PARAMETERS: +! + REAL*8, INTENT(IN) :: X ! Argument of LOG10 + REAL*8, INTENT(IN) :: ALT ! Alternate value to be returned +! +! !RETURN VALUE: +! + REAL*8 :: VALUE ! Output from the natural logarithm +! +! !REVISION HISTORY: +! 04 Jan 2010 - R. Yantosca - Initial version +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !DEFINED PARAMETERS: +! + IF ( X > 0d0 ) THEN + VALUE = LOG10( X ) ! Take LOG10(x) for positive-definite X + ELSE + VALUE = ALT ! Otherwise return alternate value + ENDIF + + END FUNCTION SAFE_LOG10 +!EOC + END MODULE ERROR_MOD diff --git a/code/fast_j.f b/code/fast_j.f new file mode 100644 index 0000000..38403af --- /dev/null +++ b/code/fast_j.f @@ -0,0 +1,397 @@ +! $Id: fast_j.f,v 1.1 2009/06/09 21:51:50 daven Exp $ + SUBROUTINE FAST_J( SUNCOS, OD, ALBD ) +! +!****************************************************************************** +! Subroutine FAST_J loops over longitude and latitude, and calls PHOTOJ +! to compute J-Values for each column at every chemistry time-step. +! (ppm, 4/98; bmy, rvm, 9/99, 2/6/04; hyl, 4/25/04; phs, bmy, 10/7/08) +! +! Arguments as Input: +! ============================================================================ +! (1 ) SUNCOS (REAL*8) : Cosine of solar zenith angle [unitless] +! (2 ) OD (REAL*8) : Cloud optical depth [unitless] +! (3 ) ALBD (REAL*8) : UV albedo [unitless] +! +! Parameter to choose cloud overlap algorithm: +! ============================================================================ +! (1 ) OVERLAP (INTEGER) : 1 - Linear Approximation (used up to v7-04-12) +! 2 - Approximate Random Overlap (default) +! 3 - Maximum Random Overlap (computation intensive) +! +! References: +! ============================================================================ +! (1) H. Liu, J.H. Crawford, R.B. Pierce, P. Norris, S.E. Platnick, G. Chen, +! J.A. Logan, R.M. Yantosca, M.J. Evans, C. Kittaka, Y. Feng, and +! X. Tie, "Radiative effect of clouds on tropospheric chemistry in a +! global three-dimensional chemical transport model", J. Geophys. Res., +! vol.111, D20303, doi:10.1029/2005JD006403, 2006. +! http://research.nianet.org/~hyl/publications/liu2006_cloud1.abs.html +! +! NOTES: +! ====== +! (1 ) Call this routine EACH chemistry time-step, before solver. +! (2 ) This routine must know IMAX, JMAX, LMAX. +! (3 ) Now use new !$OMP compiler directives for parallelization (bmy, 5/2/00) +! (4 ) Now reference "cmn_fj.h" and "jv_cmn.h" for the aerosol +! optical depths (bmy, 10/2/00) +! (5 ) Add OPTDUST as a local variable -- make OPTDUST private for +! the parallel DO-loop, since it stores 1 column of aerosol optical +! depth for each dust type (bmy, rvm, 10/2/00) +! (6 ) For now, LPAR in "cmn_fj.h" = LGLOB in "CMN_SIZE". Therefore we +! assume that we are always doing global runs. (bmy, 10/2/00) +! (7 ) Removed obsolete code from 10/2/00 (bmy, 12/21/00) +! (8 ) Replace {IJL}GLOB w/ IIPAR,JJPAR,LLPAR everywhere. Also YLMID(NLAT) +! needs to be referenced by YLMID(NLAT+J0). (bmy, 9/26/01) +! (9 ) Remove obsolete code from 9/01. Updated comments. (bmy, 10/24/01) +! (10) Add OPTAER as a local variable, make it private for the parallel +! DO loop, since it stores 1 column of aerosol optical depths for each +! aerosol type. Pass OPTAER to PHOTOJ via the argument list. Declare +! OPTAER as PRIVATE for the parallel DO-loop. (rvm, bmy, 2/27/02) +! (11) Now reference GET_PEDGE from "pressure_mod.f", which returns the +! correct "floating" pressure. (dsa, bdf, bmy, 8/20/02) +! (12) Now reference T from "dao_mod.f" (bmy, 9/23/02) +! (13) Now uses routine GET_YMID from "grid_mod.f" to compute grid box +! latitude. Now make IDAY, MONTH local variables. Now use function +! GET_DAY_OF_YEAR from "time_mod.f". Bug fix: now IDAY (as passed to +! photoj.f) is day of year rather than cumulative days since Jan 1, +! 1985. (bmy, 2/11/03) +! (14) Now reference routine GET_YEAR from "time_mod.f". Added LASTMONTH +! as a SAVEd variable. Now call READ_TOMSO3 from "toms_mod.f" at the +! beginning of a new month (or the first timestep) to read TOMS O3 +! columns which will be used by "set_prof.f". Now also reference +! routine GET_DAY from "time_mod.f". Rename IDAY to DAY_OF_YR. Pass +! day of month to PHOTOJ. Updated comments, cosmetic changes. +! (bmy, 7/17/03) +! (15) Bug fix: PRES needs to be the true surface pressure for GEOS-4, but +! PS-PTOP for all prior GEOS models. (bmy, 2/6/04) +! (16) Now account for cloud overlap (Maximum-Random Overlap and Random +! Overlap) in each column (hyl, phs, bmy, 9/18/07) +! (17) Now initialize the PJ array here, instead of two layers below in +! "set_prof.f". Now no longer pass PRES to "photoj.f". (bmy, 11/29/07) +! (18) Now switch to approx. random overlap option (hyl, phs, bmy, 10/7/08) +! (19) Now can handle GEOS-5 reprocessed met data with OPTDEPTH being +! in-cloud optical depths. (bmy, hyl, 10/24/08) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : T, CLDF + USE ERROR_MOD, ONLY : ERROR_STOP + USE GRID_MOD, ONLY : GET_YMID + USE PRESSURE_MOD, ONLY : GET_PEDGE + USE TIME_MOD, ONLY : GET_MONTH, GET_DAY, GET_DAY_OF_YEAR + USE TIME_MOD, ONLY : GET_TAU, GET_YEAR + USE TOMS_MOD, ONLY : READ_TOMS + + IMPLICIT NONE + +# include "cmn_fj.h" ! IPAR, JPAR, LPAR, CMN_SIZE +# include "jv_cmn.h" ! ODMDUST, PJ + + ! Arguments + REAL*8, INTENT(IN) :: SUNCOS(MAXIJ) + REAL*8, INTENT(IN) :: OD(LLPAR,IIPAR,JJPAR) + REAL*8, INTENT(IN) :: ALBD(IIPAR,JJPAR) + + ! Local variables + INTEGER, SAVE :: LASTMONTH = -1 + INTEGER :: NLON, NLAT, DAY, MONTH, DAY_OF_YR, L + REAL*8 :: CSZA, PRES, SFCA, YLAT + REAL*8 :: TEMP(LLPAR), OPTD(LLPAR) + REAL*8 :: OPTDUST(LLPAR,NDUST) + REAL*8 :: OPTAER(LLPAR,NAER*NRH) + + ! Local variables for cloud overlap (hyl, phs) + INTEGER :: NUMB, KK, I + INTEGER :: INDIC(LLPAR+1) + INTEGER :: INDGEN(LLPAR+1) = (/ (i,i=1,LLPAR+1) /) + INTEGER :: KBOT(LLPAR) + INTEGER :: KTOP(LLPAR) + INTEGER :: INDICATOR(LLPAR+2) + REAL*8 :: FMAX(LLPAR) ! maximum cloud fraction + ! in a block, size can be to + ! FIX(LLPAR)+1 + REAL*8 :: CLDF1D(LLPAR) + REAL*8 :: ODNEW(LLPAR) + + ! NOTE: Switch from linear approximation (OVERLAP=1) to approximate + ! random overlap (OVERLAP=2) because we have re-processed the GEOS-5 + ! met data such that OPTDEPTH, TAUCLI, and TAUCLW are now the in-cloud + ! optical depths rather than the grid-box optical depths. + ! (hyl, phs, bmy, 10/7/08) + INTEGER, PARAMETER :: OVERLAP = 2 + + LOGICAL, SAVE :: FIRST = .true. + + !================================================================= + ! FAST_J begins here! + !================================================================= + + ! Get day of year (0-365 or 0-366) + DAY_OF_YR = GET_DAY_OF_YEAR() + + ! Get current month + MONTH = GET_MONTH() + + ! Get day of month + DAY = GET_DAY() + + ! Read TOMS O3 columns if it's a new month + IF ( MONTH /= LASTMONTH ) THEN + CALL READ_TOMS( MONTH, GET_YEAR() ) + LASTMONTH = MONTH + ENDIF + + !================================================================= + ! For each (NLON,NLAT) location, call subroutine PHOTOJ (in a + ! parallel loop to compute J-values for the entire column. + ! J-values will be stored in the common-block variable ZPJ, and + ! will be later accessed via function FJFUNC. + !================================================================= +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( NLON, NLAT, YLAT, CSZA, OPTAER ) +!$OMP+PRIVATE( PRES, TEMP, OPTD, SFCA, OPTDUST ) +!$OMP+PRIVATE( FMAX, CLDF1D, KK, NUMB, L ) +!$OMP+PRIVATE( KBOT, KTOP, ODNEW, INDICATOR, INDIC ) +!$OMP+SCHEDULE( DYNAMIC ) + + ! Loop over latitudes + DO NLAT = 1, JJPAR + + ! Grid box latitude [degrees] + YLAT = GET_YMID( NLAT ) + + ! Loop over longitudes + DO NLON = 1, IIPAR + + ! Cosine of solar zenith angle [unitless] at (NLON,NLAT) + CSZA = SUNCOS( (NLAT-1)*IIPAR + NLON ) + + ! Define the PJ array here (bmy, 11/16/07) + DO L = 1, NB + PJ(L) = GET_PEDGE( NLON, NLAT, L ) + ENDDO + + ! Top edge of PJ is top of atmosphere (bmy, 2/13/07) + PJ(NB+1) = 0d0 + + ! Temperature profile [K] at (NLON,NLAT) + TEMP = T(NLON,NLAT,1:LLPAR) + + ! Surface albedo [unitless] at (NLON,NLAT) + SFCA = ALBD(NLON,NLAT) + + ! Aerosol OD profile [unitless] at (NLON,NLAT) + OPTAER(:,:) = ODAER(NLON,NLAT,:,:) + + ! Mineral dust OD profile [unitless] at (NLON,NLAT) + OPTDUST(:,:) = ODMDUST(NLON,NLAT,:,:) + + ! Cloud OD profile [unitless] at (NLON,NLAT) + OPTD = OD(1:LLPAR,NLON,NLAT) + + !----------------------------------------------------------- + !### If you want to exclude aerosol OD, mineral dust OD, + !### or cloud OD, then uncomment the following lines: + !OPTAER = 0d0 + !OPTDUST = 0d0 + !OPTD = 0d0 + !----------------------------------------------------------- + + !=========================================================== + ! CLOUD OVERLAP : LINEAR ASSUMPTION + ! Directly use OPTDEPTH = TAUCLD * CLDTOT + ! + ! NOTE: Use this option if you want to compare to results + ! from GEOS-Chem v7-04-12 and prior versions. + !=========================================================== + IF ( OVERLAP == 1 ) then + +!! #if defined( GEOS_5 ) && defined( IN_CLOUD_OD ) +!! (lzh, 11/01/2014) +#if defined( GEOS_5 ) || defined( GEOS_FP ) + + ! Column cloud fraction (not less than zero) + CLDF1D = CLDF(1:LLPAR,NLON,NLAT) + WHERE ( CLDF1D < 0d0 ) CLDF1D = 0d0 + + ! NOTE: for the reprocessed GEOS-5 met fields (i.e. with + ! optical depth & cloud fractions regridded with RegridTau) + ! OPTD is the in-cloud optical depth. At this point it has + ! NOT been multiplied by cloud fraction yet. Therefore, + ! we can just apply the linear overlap formula as written + ! above (i.e. multiply by cloud fraction). (hyl, bmy, 10/24/08) + OPTD = OPTD * CLDF1D +#endif + + ! Call FAST-J routines to compute J-values + CALL PHOTOJ( NLON, NLAT, YLAT, DAY_OF_YR, + & MONTH, DAY, CSZA, TEMP, + & SFCA, OPTD, OPTDUST, OPTAER ) + + !=========================================================== + ! CLOUD OVERLAP : APPROXIMATE RANDOM OVERLAP + ! Use OPTDEPTH = TAUCLD * CLDTOT**1.5 + !=========================================================== + ELSE IF ( OVERLAP == 2 ) THEN + + ! Column cloud fraction (not less than zero) + CLDF1D = CLDF(1:LLPAR,NLON,NLAT) + WHERE ( CLDF1D < 0d0 ) CLDF1D = 0d0 + +!! #if defined( GEOS_5 ) && defined( IN_CLOUD_OD ) +#if defined( GEOS_5 ) || defined( GEOS_FP ) + + ! NOTE: for the reprocessed GEOS-5 met fields (i.e. with + ! optical depth & cloud fractions regridded with RegridTau) + ! OPTD is the in-cloud optical depth. At this point it has + ! NOT been multiplied by cloud fraction yet. Therefore, + ! we can just apply the approximate random overlap formula + ! as written above (i.e. multiply by cloud fraction^1.5). + ! (hyl, bmy, 10/24/08) + OPTD = OPTD * ( CLDF1D )**1.5d0 + +#else + ! Otherwise, OPTD is the grid-box optical depth and has + ! already been multiplied by the cloud fraction. Therefore + ! we only need to multiply by the square root of the cloud + ! fraction here for the approximate random overlap option. + ! (hyl, bmy, 10/24/08) + OPTD = OPTD * SQRT( CLDF1D ) + +#endif + + ! Call FAST-J routines to compute J-values + CALL PHOTOJ( NLON, NLAT, YLAT, DAY_OF_YR, + & MONTH, DAY, CSZA, TEMP, + & SFCA, OPTD, OPTDUST, OPTAER ) + + !=========================================================== + ! CLOUD OVERLAP : MAXIMUM RANDOM OVERLAP + ! + ! The Maximum-Random Overlap (MRAN) scheme assumes that + ! clouds in adjacent layers are maximally overlapped to + ! form a cloud block and that blocks of clouds separated by + ! clear layers are randomly overlapped. A vertical profile + ! of fractional cloudiness is converted into a series of + ! column configurations with corresponding fractions + ! (see Liu et al., JGR 2006; hyl,3/3/04). + ! + ! For more details about cloud overlap assumptions and + ! their effect on photolysis frequencies and key oxidants + ! in the troposphere, refer to the following articles: + ! + ! (1) Liu, H., et al., Radiative effect of clouds on + ! tropospheric chemistry in a global three-dimensional + ! chemical transport model, J. Geophys. Res., vol.111, + ! D20303, doi:10.1029/2005JD006403, 2006. + ! (2) Tie, X., et al., Effect of clouds on photolysis and + ! oxidants in the troposphere, J. Geophys. Res., + ! 108(D20), 4642, doi:10.1029/2003JD003659, 2003. + ! (3) Feng, Y., et al., Effects of cloud overlap in + ! photochemical models, J. Geophys. Res., 109, + ! D04310, doi:10.1029/2003JD004040, 2004. + ! (4) Stubenrauch, C.J., et al., Implementation of subgrid + ! cloud vertical structure inside a GCM and its effect + ! on the radiation budget, J. Clim., 10, 273-287, 1997. + !----------------------------------------------------------- + ! MMRAN needs IN-CLOUD optical depth (ODNEW) as input + ! Use cloud fraction, instead of OPTD, to form cloud blocks + ! (hyl,06/19/04) + !=========================================================== + ELSE IF ( OVERLAP == 3 ) THEN + + ! Initialize + FMAX(:) = 0d0 ! max cloud fraction in each cloud block + ODNEW(:) = 0d0 ! in-cloud optical depth + CLDF1D = CLDF(1:LLPAR,NLON,NLAT) + INDICATOR = 0 + + ! set small negative CLDF or OPTD to zero. + ! Set indicator vector. + WHERE ( CLDF1D <= 0d0 ) + CLDF1D = 0d0 + OPTD = 0D0 + ELSEWHERE + INDICATOR(2:LLPAR+1) = 1 + ENDWHERE + + ! Prevent negative opt depth + WHERE ( OPTD < 0D0 ) OPTD = 0D0 + + !-------------------------------------------------------- + ! Generate cloud blocks & get their Bottom and Top levels + !-------------------------------------------------------- + INDICATOR = CSHIFT(INDICATOR, 1) - INDICATOR + INDIC = INDICATOR(1:LLPAR+1) + + ! Number of cloud block + NUMB = COUNT( INDIC == 1 ) + + ! Bottom layer of each block + KBOT(1:NUMB) = PACK(INDGEN, (INDIC == 1 ) ) + + ! Top layer of each block + KTOP(1:NUMB) = PACK(INDGEN, (INDIC == -1) ) - 1 + + !-------------------------------------------------------- + ! For each cloud block, get Max Cloud Fractions, and + ! in-cloud optical depth vertical distribution. + !-------------------------------------------------------- + DO KK = 1, NUMB + + ! Max cloud fraction + FMAX(KK) = MAXVAL( CLDF1D(KBOT(KK):KTOP(KK)) ) + +!! #if defined( GEOS_5 ) && defined( IN_CLOUD_OD ) +#if defined( GEOS_5 ) || defined( GEOS_FP ) + + ! NOTE: for the reprocessed GEOS-5 met fields (i.e. with + ! optical depth & cloud fractions regridded with RegridTau) + ! OPTD is the in-cloud optical depth. At this point it has + ! NOT been multiplied by cloud fraction yet. Therefore, + ! we can just set ODNEW = OPTD. (bmy, hyl, 10/24/08) + + ! ODNEW is adjusted in-cloud OD vertical distrib. + ODNEW(KBOT(KK):KTOP(KK)) = OPTD(KBOT(KK):KTOP(KK)) + +#else + + ! Otherwise, OPTD is the grid-box optical depth. + ! Therefore, we must divide out by the cloud fraction + ! and thus set ODNEW = OPTD / FMAX. (bmy, hyl, 10/24/08) + + ! ODNEW is adjusted in-cloud OD vertical distrib. + ODNEW(KBOT(KK):KTOP(KK)) = OPTD(KBOT(KK):KTOP(KK)) / + & FMAX(KK) + +#endif + ENDDO + + !-------------------------------------------------------- + ! Apply Max RANdom if 1-6 clouds blocks, else use linear + !-------------------------------------------------------- + SELECT CASE( NUMB ) + + CASE( 0,7: ) + CALL PHOTOJ( NLON, NLAT, YLAT, DAY_OF_YR, + & MONTH, DAY, CSZA, TEMP, + & SFCA, OPTD, OPTDUST, OPTAER ) + + CASE( 1:6 ) + CALL MMRAN_16( NUMB, NLON, NLAT, YLAT, + & DAY, MONTH, DAY_OF_YR, CSZA, + & TEMP, SFCA, OPTDUST, OPTAER, + & LLPAR, FMAX, ODNEW, KBOT, + & KTOP ) + + END SELECT + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + + !----------------------------------------------------------- + ! END OF SUBROUTINE FAST-J + !----------------------------------------------------------- + END SUBROUTINE FAST_J diff --git a/code/fcro2ho2.f b/code/fcro2ho2.f new file mode 100644 index 0000000..cef15aa --- /dev/null +++ b/code/fcro2ho2.f @@ -0,0 +1,13 @@ +!fgap +!based on saunder 2003 k14 + REAL*8 FUNCTION FCRO2HO2( XCARBN ) + + IMPLICIT NONE + + ! Arguments + REAL*8, INTENT(IN) :: XCARBN + + FCRO2HO2 = 1D0-EXP(-0.245D0*XCARBN) + + ! Return to calling program + END FUNCTION FCRO2HO2 \ No newline at end of file diff --git a/code/fertadd.f b/code/fertadd.f new file mode 100644 index 0000000..94e0cd5 --- /dev/null +++ b/code/fertadd.f @@ -0,0 +1,124 @@ +! $Id: fertadd.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + FUNCTION FERTADD( J, M, NN ) +! +!****************************************************************************** +! Subroutine FERTADD computes the amount of soil fertilizer released +! in a particular grid box according to the Yienger & Levy scheme. +! (yhw, gmg, djj, 1994; bmy, 2/11/03) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : Grid box latitude index +! (2 ) M (INTEGER) : Grid box surface index (M=1,NLAND) +! (3 ) NN (INTEGER) : Land type index +! +! References: +! ============================================================================ +! (1 ) Yienger, J.J, and H. Levy II, "Empirical model of global soil-biogenic +! NOx emissions", JGR, 100 (D6), pp. 11447-11464, June 20, 1995. +! +! NOTES: +! (1 ) Original code by by Yuhang Wang, Gerry Gardner and Prof. Daniel Jacob +! written in the early 1990's. Updated and modified for GEOS-CHEM by +! Bob Yantosca. Now uses function GET_YMID of "grid_mod.f" to compute +! grid box latitudes. Now use function GET_MONTH from "time_mod.f". +! Removed reference to header file CMN. Updated comments, +! cosmetic changes. (bmy, 2/11/03) +! (2 ) Add LANTHRO switch to correctly turn off anthropogenic emissions. +! (ccc, 4/15/09) +!****************************************************************************** +! + ! References to F90 modules + USE GRID_MOD, ONLY : GET_YMID + USE TIME_MOD, ONLY : GET_MONTH + USE LOGICAL_MOD, ONLY : LANTHRO + + IMPLICIT NONE + +# include "CMN_SIZE" ! Size parameters +# include "commsoil.h" ! SOILFERT + + ! Arguments + INTEGER, INTENT(IN) :: J, M, NN + + ! Local variables + REAL*8 :: Y + REAL*8, PARAMETER :: UNITCONV = 4.3d9 + + ! Function value + REAL*8 :: FERTADD + + !================================================================= + ! FERTADD begins here! + !================================================================= + + ! Initialize + FERTADD = 0.D0 + + ! Return if soil types are not correct + ! Soil type 8 refers to different kinds of farmland + ! Soil type 9 refers to rice paddies + IF ( NN /= 8 .and. NN /= 9 ) RETURN + + ! Return if anthropogenic emissions are turned off (ccc, 4/15/09) + IF (.not.LANTHRO) RETURN + + ! Latitude of grid box [degrees] + Y = GET_YMID( J ) + + !================================================================= + ! Case 1: Northern Hemisphere midlatitudes ( Y > 28 degrees ) + !================================================================= + IF ( Y > 28d0 ) THEN + + ! May, June, July, August... + IF ( GET_MONTH() >= 5 .and. GET_MONTH() <= 8 ) THEN + + ! NH summer: use value from SOILFERT + FERTADD = SOILFERT(M) + + ELSE + + ! NH winter: no soil NOx emissions + FERTADD = 0.D0 + ENDIF + + !================================================================= + ! Case 2: Tropics ( -28 <= Y < 28 degrees ) + !================================================================= + ELSE IF ( Y > -28d0 ) THEN + + ! Tropics: use value from soilfert + FERTADD = SOILFERT(M) + + !================================================================= + ! Case 3: Southern hemisphere midlatitudes ( Y <= -28 degrees ) + !================================================================= + ELSE + + ! Jan, Feb, Nov, Dec + IF ( GET_MONTH() <= 2 .or. GET_MONTH() >= 11 ) THEN + + ! SH summer: use the values from SOILFERT + FERTADD = SOILFERT(M) + ELSE + + ! SH winter: no fertilizer emissions + FERTADD = 0.d0 + ENDIF + ENDIF + + !================================================================= + ! Unit conversion + !================================================================= + + ! Yienger & Levy state that over rice paddies the fertilizer + ! emissions should be cut by a factor of 30, since the very + ! wet soil of rice paddies impedes NOx emission. + IF ( NN == 9 ) FERTADD = FERTADD / 30.D0 + + ! Convert [ng N/m2/s] to [molec/cm2/s] + FERTADD = FERTADD * UNITCONV + + ! Return to calling program + END FUNCTION FERTADD diff --git a/code/file_mod.f b/code/file_mod.f new file mode 100644 index 0000000..30e0357 --- /dev/null +++ b/code/file_mod.f @@ -0,0 +1,462 @@ +! $Id: file_mod.f,v 1.2 2012/03/01 22:00:26 daven Exp $ + MODULE FILE_MOD +! +!****************************************************************************** +! Module FILE_MOD contains file unit numbers, as well as file I/O routines +! for GEOS-CHEM. FILE_MOD keeps all of the I/O unit numbers in a single +! location for convenient access. (bmy, 7/1/02, 8/4/06) +! +! Module Variables: +! ============================================================================ +! (1 ) IU_RST : Unit # for file "gctm.trc.YYYYMMDD" +! (3 ) IU_CHEMDAT : Unit # for file "chem.dat" +! (4 ) IU_FASTJ : Unit # for file "ratj.d", "jv_atms.dat", "jv_spec.dat" +! (6 ) IU_GEOS : Unit # for file "input.geos" +! (7 ) IU_TS : Unit # for file "ctm.ts" +! (8 ) IU_BPCH : Unit # for file "ctm.bpch" +! (9 ) IU_ND20 : Unit # for file "rate.YYYYMMDD" +! (10) IU_ND49 : Unit # for file "tsYYYYMMDD.bpch" +! (11) IU_ND50 : Unit # for file "ts24h.bpch" +! (12) IU_ND51 : Unit # for file "ts10_12am.bpch" or "ts1_4pm.bpch" +! (13) IU_PLANE : Unit # for plane flight diagnostic output file +! (14) IU_FILE : Unit # for files opened & closed in same routine +! (15) IU_PH : Unit # for GEOS-CHEM PHIS met field file +! (16) IU_I6 : Unit # for GEOS-CHEM I-6 met field file +! (17) IU_A6 : Unit # for GEOS-CHEM A-6 met field file +! (18) IU_A3 : Unit # for GEOS-CHEM A-3 met field file +! (19) IU_KZZ : Unit # for GEOS-CHEM KZZ met field file +! (20) IU_GWET : Unit # for GEOS-CHEM GWET met field file +! (21) IU_SMV2LOG : Unit # for "smv2.log" file -- SMVGEAR II rxns & species +! (22) IU_DEBUG : Unit # left for debugging purposes +! +! Module Routines +! ============================================================================ +! (1 ) IOERROR : Stops w/ error msg output if I/O errors are detected +! (2 ) FILE_EX_C : Tests if a directory or file is valid +! (3 ) FILE_EX_I : Tests if a file unit refers to a valid file +! (4 ) CLOSE_FILES : Closes all files at the end of a GEOS-CHEM run +! +! GEOS-CHEM modules referenced by file_mod.f +! ============================================================================ +! (1 ) error_mod.f : Module containing NaN and other error check routines +! +! NOTES: +! (1 ) Moved "ioerror.f" into this module. (bmy, 7/1/02) +! (2 ) Now references "error_mod.f" (bmy, 10/15/02) +! (3 ) Renamed cpp switch from DEC_COMPAQ to COMPAQ. Also added code to +! trap I/O errors on SUN/Sparc platform. (bmy, 3/23/03) +! (4 ) Now added IU_BC for nested boundary conditions as unit 18 +! (bmy, 3/27/03) +! (5 ) Renamed IU_CTMCHEM to IU_SMV2LOG (bmy, 4/21/03) +! (6 ) Now print out I/O errors for IBM and INTEL_FC compilers (bmy, 11/6/03) +! (7 ) Changed the name of some cpp switches in "define.h" (bmy, 12/2/03) +! (8 ) Renumbered the order of the files. Also removed IU_INPTR and +! IU_INPUT since they are now obsolete. (bmy, 7/20/04) +! (9 ) Added overloaded routines FILE_EX_C and FILE_EX_I (bmy, 3/23/05) +! (10) Added LINUX_IFORT switch for Intel v8 & v9 compilers (bmy, 10/18/05) +! (11) Added IU_XT for GEOS3 XTRA met fields files for MEGAN (tmf, 10/20/05) +! (12) Extra modification for Intel v9 compiler (bmy, 11/2/05) +! (13) Now print IFORT error messages (bmy, 11/30/05) +! (14) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "file_mod.f" + !================================================================= + + ! PRIVATE routines + PRIVATE :: FILE_EX_C + PRIVATE :: FILE_EX_I + + !================================================================= + ! MODULE VARIABLES + !================================================================= + INTEGER, PARAMETER :: IU_RST = 1 + INTEGER, PARAMETER :: IU_CHEMDAT = 7 + INTEGER, PARAMETER :: IU_FASTJ = 8 + INTEGER, PARAMETER :: IU_GEOS = 10 + INTEGER, PARAMETER :: IU_BPCH = 11 + INTEGER, PARAMETER :: IU_ND20 = 12 + INTEGER, PARAMETER :: IU_ND48 = 13 + INTEGER, PARAMETER :: IU_ND49 = 14 + INTEGER, PARAMETER :: IU_ND50 = 15 + INTEGER, PARAMETER :: IU_ND51 = 16 + INTEGER, PARAMETER :: IU_ND52 = 17 + INTEGER, PARAMETER :: IU_PLANE = 18 + INTEGER, PARAMETER :: IU_BC = 19 + INTEGER, PARAMETER :: IU_BC_NA = 20 !(lzh,02/01/2015)add nested domain + INTEGER, PARAMETER :: IU_BC_EU = 21 + INTEGER, PARAMETER :: IU_BC_CH = 22 + INTEGER, PARAMETER :: IU_BC_05x06= 23 + INTEGER, PARAMETER :: IU_FILE = 65 + INTEGER, PARAMETER :: IU_TP = 69 + INTEGER, PARAMETER :: IU_PH = 70 + INTEGER, PARAMETER :: IU_I6 = 71 + INTEGER, PARAMETER :: IU_A6 = 72 + INTEGER, PARAMETER :: IU_A3 = 73 + INTEGER, PARAMETER :: IU_KZZ = 74 + INTEGER, PARAMETER :: IU_GWET = 75 + INTEGER, PARAMETER :: IU_XT = 76 + INTEGER, PARAMETER :: IU_SMV2LOG = 93 + INTEGER, PARAMETER :: IU_DEBUG = 98 + INTEGER, PARAMETER :: IU_STR = 54 !(hml, 04/03/13) + INTEGER, PARAMETER :: IU_RXN = 55 !(hml, 04/03/13) + + !================================================================= + ! MODULE INTERFACES -- "bind" two or more routines with different + ! argument types or # of arguments under one unique name + !================================================================= + INTERFACE FILE_EXISTS + MODULE PROCEDURE FILE_EX_C, FILE_EX_I + END INTERFACE + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE IOERROR( ERROR_NUM, UNIT, LOCATION ) +! +!****************************************************************************** +! Subroutine IOERRROR prints out I/O error messages. The error number, +! file unit, location, and a brief description will be printed, and +! program execution will be halted. (bmy, 5/28/99, 8/4/06) +! +! Arguments as input: +! =========================================================================== +! (1 ) ERROR_NUM : I/O error number (output from the IOSTAT flag) +! (2 ) UNIT : Unit # of the file where the I/O error occurred +! (3 ) LOCATION : Name of the routine in which the error occurred +! +! NOTES: +! (1 ) Now flush the standard output buffer before stopping. +! Also updated comments. (bmy, 2/7/00) +! (2 ) Changed ROUTINE_NAME to LOCATION. Now also use C-library routines +! gerror and strerror() to get the error string corresponding to +! ERROR_NUM. For SGI platform, also print the command string that +! will call the SGI "explain" command, which will yield additional +! information about the error. Updated comments, cosmetic changes. +! Now also reference "define.h". (bmy, 3/21/02) +! (3 ) Moved into "file_mod.f". Now reference GEOS_CHEM_STOP from module +! "error_mod.f". Updated comments, cosmetic changes. (bmy, 10/15/02) +! (4 ) Renamed cpp switch from DEC_COMPAQ to COMPAQ. Also added code to +! display I/O errors on SUN platform. (bmy, 3/23/03) +! (5 ) Now call GERROR for IBM and INTEL_FC compilers (bmy, 11/6/03) +! (6 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC, +! and added LINUX_EFC. (bmy, 12/2/03) +! (7 ) Now don't flush the buffer for LINUX_EFC (bmy, 4/23/04) +! (8 ) Modifications for Linux/IFORT Intel v9 compiler (bmy, 11/2/05) +! (9 ) Now call IFORT_ERRMSG to get the IFORT error messages (bmy, 11/30/05) +! (10) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : GEOS_CHEM_STOP + + IMPLICIT NONE + +# include "define.h" ! C-preprocessor switches + + ! Arguments + INTEGER, INTENT(IN) :: ERROR_NUM, UNIT + CHARACTER(LEN=*), INTENT(IN) :: LOCATION + + ! Local variables + CHARACTER(LEN=10) :: ERROR_NUMSTR + CHARACTER(LEN=255) :: ERROR_MSG + CHARACTER(LEN=255) :: EXPLAIN_CMD + + ! External functions + CHARACTER(LEN=255), EXTERNAL :: GERROR, IFORT_ERRMSG + + !================================================================= + ! IOERROR begins here! + !================================================================= + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! Write error number, unit, location + WRITE( 6, 110 ) ERROR_NUM, UNIT, TRIM( LOCATION ) + 110 FORMAT( 'GEOS-CHEM I/O ERROR ', i5, ' in file unit ', i5, /, + & 'Encountered at routine:location ', a ) + +#if defined( SGI_MIPS ) + + !================================================================= + ! For SGI: print error msg and construct explain command string + !================================================================= + IF ( ERROR_NUM == 2 ) THEN + + ! Error 2 is "file not found", so handle that separately. + ! You can't use the explain command w/ error 2. + WRITE( 6, '(/,a)' ) 'Error: No such file or directory' + + ELSE + + ! Call SGI strerror routine to convert ERROR_NUM to ERROR_MSG + ERROR_MSG = GERROR() + + ! Print error message to std output + WRITE( 6, 120 ) TRIM( ERROR_MSG ) + 120 FORMAT( /, 'Error: ', a ) + + ! Convert ERROR_NUM to string format + WRITE( ERROR_NUMSTR, '(i10)' ) ERROR_NUM + + ! Construct argument for SGI explain command + IF ( ERROR_NUM >= 1000 .and. ERROR_NUM < 4000 ) THEN + EXPLAIN_CMD = 'explain cf90-' // + & TRIM( ADJUSTL( ERROR_NUMSTR )) + + ELSE IF ( ERROR_NUM >= 4000 ) THEN + EXPLAIN_CMD = 'explain lib-' // + & TRIM( ADJUSTL( ERROR_NUMSTR )) + ENDIF + + ! Print command string for the SGI explain command + WRITE( 6, 130 ) TRIM( EXPLAIN_CMD ) + 130 FORMAT( /, 'Type "', a, '" at the Unix prompt for an ', + & 'explanation of the error.' ) + ENDIF + +#elif defined( COMPAQ ) + + !================================================================= + ! For COMPAQ/Alpha: call gerror() to get the I/O error msg + !================================================================= + + ! GERROR returns ERROR_MSG corresponding to ERROR_NUM + ERROR_MSG = GERROR() + + ! Print error message to std output + WRITE( 6, 120 ) TRIM( ERROR_MSG ) + 120 FORMAT( /, 'Error: ', a ) + +#elif defined( LINUX_PGI ) + + !================================================================= + ! For LINUX platform w/ PGI compiler + ! Call gerror() to get the I/O error msg + !================================================================= + + ! GERROR returns ERROR_MSG corresponding to ERROR_NUM + ERROR_MSG = GERROR() + + ! Print error message to std output + WRITE( 6, 120 ) TRIM( ERROR_MSG ) + 120 FORMAT( /, 'Error: ', a ) + +#elif defined( LINUX_IFORT ) + + !================================================================= + ! For LINUX platform w/ IFORT v8/v9 compiler: + ! Call IFORT_ERRMSG to get the error number and message + !================================================================= + + ! Get an error msg corresponding to this error number + ERROR_MSG = IFORT_ERRMSG( ERROR_NUM ) + + ! Print error message to std output + WRITE( 6, 120 ) ERROR_NUM, TRIM( ERROR_MSG ) + 120 FORMAT( /, 'Error ', i4, ': ', a ) + +#elif defined( SPARC ) + + !================================================================= + ! For SUN/Sparc platform: call gerror() to get the I/O error msg + !================================================================= + + ! GERROR returns ERROR_MSG corresponding to ERROR_NUM + ERROR_MSG = GERROR() + + ! Print error message to std output + WRITE( 6, 120 ) TRIM( ERROR_MSG ) + 120 FORMAT( /, 'Error: ', a ) + +#elif defined( IBM_AIX ) + + !================================================================= + ! For IBM/AIX platform: call gerror() to get the I/O error msg + !================================================================= + + ! GERROR returns ERROR_MSG corresponding to ERROR_NUM + ERROR_MSG = GERROR() + + ! Print error message to std output + WRITE( 6, 120 ) TRIM( ERROR_MSG ) + 120 FORMAT( /, 'Error: ', a ) + +#endif + + ! Fancy output + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + +#if !defined( LINUX_EFC ) + CALL FLUSH( 6 ) +#endif + + ! Deallocate arrays and stop safely + CALL GEOS_CHEM_STOP + + ! End of program + END SUBROUTINE IOERROR + +!------------------------------------------------------------------------------ + + FUNCTION FILE_EX_C( FILENAME ) RESULT( IT_EXISTS ) +! +!****************************************************************************** +! Function FILE_EX_C returns TRUE if FILENAME exists or FALSE otherwise. +! This is handled in a platform-independent way. The argument is of +! CHARACTER type. (bmy, 3/23/05, 11/2/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FILENAME (CHARACTER) : Name of file or directory to test +! +! NOTES: +! (1 ) Updated for LINUX/IFORT Intel v9 compiler (bmy, 11/2/05) +!****************************************************************************** +! +# include "define.h" + + ! Arguments + CHARACTER(LEN=*), INTENT(IN) :: FILENAME + + ! Function value + LOGICAL :: IT_EXISTS + + !================================================================= + ! FILE_EX_C begins here! + !================================================================= + +#if defined( COMPAQ ) + + !------------------ + ! COMPAQ compiler + !------------------ + + ! Reference external library function + INTEGER*4, EXTERNAL :: ACCESS + + ! Test whether directory exists for COMPAQ + IT_EXISTS = ( ACCESS( TRIM( FILENAME ), ' ' ) == 0 ) + +#else + + !------------------ + ! Other compilers + !------------------ + + ! Test whether directory exists w/ F90 INQUIRE function + INQUIRE( FILE=TRIM( FILENAME ), EXIST=IT_EXISTS ) + +#if defined( LINUX_IFORT ) + + ! Intel IFORT v9 compiler requires use of the DIRECTORY keyword to + ! INQUIRE for checking existence of directories. (bmy, 11/2/05) + IF ( .not. IT_EXISTS ) THEN + INQUIRE( DIRECTORY=TRIM( FILENAME ), EXIST=IT_EXISTS ) + ENDIF + +#endif + +#endif + + ! Return to calling program + END FUNCTION FILE_EX_C + +!------------------------------------------------------------------------------ + + FUNCTION FILE_EX_I( IUNIT ) RESULT( IT_EXISTS ) +! +!****************************************************************************** +! Function FILE_EX_I returns TRUE if FILENAME exists or FALSE otherwise. +! This is handled in a platform-independent way. The argument is of +! INTEGER type. (bmy, 3/23/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FILENAME (INTEGER) : Name of file unit to test +! +! NOTES: +!****************************************************************************** +! +# include "define.h" + + ! Arguments + INTEGER, INTENT(IN) :: IUNIT + + ! Function value + LOGICAL :: IT_EXISTS + + !================================================================= + ! FILE_EX_I begins here! + !================================================================= + + ! Test whether file unit exists w/ F90 INQUIRE function + INQUIRE( IUNIT, EXIST=IT_EXISTS ) + + ! Return to calling program + END FUNCTION FILE_EX_I + +!------------------------------------------------------------------------------ + + SUBROUTINE CLOSE_FILES +! +!****************************************************************************** +! Subroutine CLOSE_FILES closes files used by GEOS-CHEM. This should be +! called only from the end of the "main.f" program. (bmy, 3/4/98, 10/20/05) +! +! NOTES: +! (1 ) Moved into "file_mod.f" (bmy, 6/27/02) +! (2 ) Also close IU_BC (bmy, 3/27/03) +! (3 ) Removed IU_INPUT and IU_INPTR, these are obsolete. Also renamed +! IU_TS to IU_ND48 (bmy, 7/20/04) +! (4 ) Also close IU_XT (tmf, bmy, 10/20/05) +!****************************************************************************** +! + !================================================================= + ! CLOSE_FILES begins here! + !================================================================= + CLOSE( IU_RST ) + CLOSE( IU_CHEMDAT ) + CLOSE( IU_FASTJ ) + CLOSE( IU_GEOS ) + CLOSE( IU_BPCH ) + CLOSE( IU_ND20 ) + CLOSE( IU_ND48 ) + CLOSE( IU_ND49 ) + CLOSE( IU_ND50 ) + CLOSE( IU_ND51 ) + CLOSE( IU_ND52 ) + CLOSE( IU_PLANE ) + CLOSE( IU_BC ) + CLOSE( IU_BC_05x06) + CLOSE( IU_FILE ) + CLOSE( IU_PH ) + CLOSE( IU_TP ) + CLOSE( IU_I6 ) + CLOSE( IU_A6 ) + CLOSE( IU_A3 ) + CLOSE( IU_KZZ ) + CLOSE( IU_GWET ) + CLOSE( IU_XT ) + CLOSE( IU_SMV2LOG ) + CLOSE( IU_DEBUG ) + CLOSE( IU_STR ) + CLOSE( IU_RXN ) + + ! Return to calling program + END SUBROUTINE CLOSE_FILES + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE FILE_MOD diff --git a/code/findmon.f b/code/findmon.f new file mode 100644 index 0000000..bb83b35 --- /dev/null +++ b/code/findmon.f @@ -0,0 +1,41 @@ +! $Id: findmon.f,v 1.1 2009/06/09 21:51:50 daven Exp $ + SUBROUTINE FINDMON( JDAY, INMONTH, MM, STARTDAY ) +! +!****************************************************************************** +! Function FINDMON finds which month JDAY (day of this year) is in. +! FINDMON is called by the Leaf Area Index routine rdlai.f. +! (yhw, gmg, djj, 1994; bmy, 4/4/03) +! +! Arguments as Input: +! ============================================================================ +! (1 ) JDAY (INTEGER) : Current day of year (0-365 or 0-366, leap years) +! (2 ) INMONTH (INTEGER) : Current month (1-12) +! (4 ) STARTDAY (INTEGER) : Array of starting days for LAI monthly data +! +! Arguments as Output: +! ============================================================================ +! (3 ) MM (INTEGER) : Output month number (1-12) +! +! NOTES: +! (1 ) Updated comments, cosmetic changes (bmy, 4/4/03) +!****************************************************************************** +! + IMPLICIT NONE + + ! Arguments + INTEGER, INTENT(IN) :: JDAY, INMONTH, STARTDAY(13) + INTEGER, INTENT(OUT) :: MM + + !================================================================= + ! FINDMON begins here! + !================================================================= + IF ( JDAY < STARTDAY(1) ) THEN + MM = 12 + ELSE IF ( JDAY < STARTDAY(INMONTH) ) THEN + MM = INMONTH-1 + ELSE + MM = INMONTH + ENDIF + + ! Return to calling program + END SUBROUTINE FINDMON diff --git a/code/fjfunc.f b/code/fjfunc.f new file mode 100644 index 0000000..425aac6 --- /dev/null +++ b/code/fjfunc.f @@ -0,0 +1,71 @@ +! $Id: fjfunc.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + REAL*8 FUNCTION FJFUNC( I, J, L, NREAC, BRCH, NAME ) +! +!***************************************************************************** +! Subroutine FJFUNC supplies J-values to SMVGEAR solver. +! (ppm, 4/98, bmy, 9/99, 10/15/02) +! +! Arguments as input: +! =========================================================================== +! (1-3) I, J, L : Latitude, Longitude, Altitude indices of CTM grid box +! (4 ) NREAC : SMVGEAR photo reaction number (read from "chem.dat") +! (5 ) BRCH : SMVGEAR branch index (computed from "chem.dat") +! (6 ) NAME : SMVGEAR species name (read from "chem.dat") +! +! NOTES: +! (1 ) "cmn_fj.h" also includes "CMN_SIZE" and "define.h". +! (2 ) J-values are stored in array "ZPJ" from "cmn_fj.h". +! (3 ) Now references ERROR_STOP from "error_mod.f". Updated comments, +! and made some cosmetic changes. (bmy, 10/15/02) +!***************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ERROR_STOP + + IMPLICIT NONE + +# include "cmn_fj.h" + + ! Arguments + INTEGER, INTENT(IN) :: I, J, L, NREAC, BRCH + CHARACTER (LEN=4), INTENT(IN) :: NAME + + ! Local variables + INTEGER :: N + + !================================================================= + ! FJFUNC begins here! + ! + ! If your compiler has subscript-range checking (-C or + ! -check_bounds) then it is recommended to use this option to + ! test for the validity of (I,J,L), since repeated IF statements + ! are computationally expensive. + ! + ! If your compiler does not have subscript-range checking, then + ! uncomment the following lines to do a manual test for the + ! validity of (I,J,L). + !================================================================= + !IF ( I > IPAR .OR. J > JPAR .OR. L > JPNL ) THEN + ! STOP 'invalid grid-box # in call to fjfunc - check fjfunc.f' + !ENDIF + + !================================================================= + ! RINDEX converts the J-value index as read from "chem.dat" to + ! the J-value index as read from "ratj.d". (bmy, 10/5/98) + ! + ! Make sure that we have taken the proper reaction! + !================================================================= + N = RINDEX(NREAC) + + IF ( N > JPPJ ) THEN + WRITE(6,*) 'RXN for ',name,', branch ',brch,' not found!' + CALL ERROR_STOP( 'Check FJFUNC.F', 'fjfunc.f' ) + ENDIF + + !================================================================= + ! Return the appropriate J-value as the value of the function + !================================================================= + FJFUNC = ZPJ(L,N,I,J) + + ! Return to calling program + END FUNCTION FJFUNC diff --git a/code/fjx_acet_mod.f b/code/fjx_acet_mod.f new file mode 100644 index 0000000..d13404c --- /dev/null +++ b/code/fjx_acet_mod.f @@ -0,0 +1,212 @@ +!------------------------------------------------------------------------------ +! GEOS-Chem Global Chemical Transport Model ! +!------------------------------------------------------------------------------ +!BOP +! +! !MODULE: FJX_ACET_MOD +! +! !DESCRIPTION: \subsection*{Overview} +! This module contains functions used for the new acetone pressure +! dependency calculation in JRATET.f introduced in FAST-JX version 6.7 +! This is a hack to effectively implement Fast-JX v7.0b acetone +! photolysis into Fast-J. See use in JRATET.f +! +!\subsection*{Reference} +! Blitz, M. A., D. E. Heard, M. J. Pilling, S. R. Arnold, M. P. Chipperfield +! 2004: \emph{Pressure and temperature-dependent quantum yields for the +! photodissociation of acetone between 279 and 327.5 nm}, +! \underline{GRL}, \textbf{31}, 9, L09104. +!\\ +!\\ +! +! !INTERFACE: +! + MODULE FJX_ACET_MOD +! +! !USES: +! + IMPLICIT NONE + PRIVATE +! +! !PUBLIC MEMBER FUNCTIONS: +! + PUBLIC :: QQA + PUBLIC :: QQB +! +! !AUTHOR: +! Original code from Michael Prather. +! Implemented into GEOS-Chem by Claire Carouge (ccarouge@seas.harvard.edu) +! +! !REVISION HISTORY: +! 20 Apr 2009 - C. Carouge - Created the module from fastJX64.f code. +! 20 Aug 2013 - R. Yantosca - Removed "define.h", this is now obsolete +! 19 May 2014 - M. Sulprizio- Update acetone photolysis to Fast-JX v7.0b +! (S.D. Eastham) +!EOP +!------------------------------------------------------------------------------ + CONTAINS + +!------------------------------------------------------------------------------ +! GEOS-Chem Global Chemical Transport Model ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: QQA +! +! !DESCRIPTION: +!\\ +!\\ +! !INTERFACE: +! + subroutine QQA(PP,QQQT,K) +! +! !USES: +! + implicit none +# include "cmn_fj.h" +! +! !INPUT PARAMETERS: +! + real*8, intent(in) :: PP + integer, intent(in) :: K +! +! !OUTPUT PARAMETERS: +! + real*8, intent(out) :: QQQT +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + logical,save::FIRST=.TRUE. + real*8,dimension(7,3),save::QQQ + real*8,dimension(3),save::TQQ + + if (FIRST) then + FIRST=.false. + ! Declare arrays + ! Pressure at which cross-sections calculated + TQQ = (/177.0d0,566.0d0,999.0d0/) + ! Taking only the last 7 bins from Fast-JX (!) + QQQ(:,1) = (/ 1.980d-20, 5.927d-21, 6.000d-22, 5.868d-23, + & 5.934d-25, 0.000d0, 0.000d0 /) + QQQ(:,2) = (/ 1.240d-20, 4.464d-21, 7.146d-22, 1.171d-22, + & 2.202d-24, 0.000d0, 0.000d0 /) + QQQ(:,3) = (/ 9.213d-21, 3.702d-21, 7.100d-22, 1.357d-22, + & 3.115d-24, 0.000d0, 0.000d0 /) + endif + call X_interp_FJX (PP,QQQT, TQQ(1),QQQ(K,1), + & TQQ(2),QQQ(K,2), TQQ(3),QQQ(K,3), 3) + + end subroutine QQA +!EOC +!------------------------------------------------------------------------------ +! GEOS-Chem Global Chemical Transport Model ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: QQB +! +! !DESCRIPTION: +!\\ +!\\ +! !INTERFACE: +! + subroutine QQB(TT,QQQT,K) +! +! !USES: +! + implicit none +# include "cmn_fj.h" +! +! !INPUT PARAMETERS: +! + real*8, intent(in) :: TT + integer, intent(in) :: K +! +! !OUTPUT PARAMETERS: +! + real*8, intent(out) :: QQQT +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + logical,save::FIRST=.TRUE. + real*8,dimension(7,3),save::QQQ + real*8,dimension(3),save::TQQ + + if (FIRST) then + FIRST=.false. + ! Declare arrays + ! Temperature at which cross-sections calculated + TQQ = (/235.0d0,260.0d0,298.0d0/) + ! Taking only the last 7 bins from Fast-JX (!) + QQQ(:,1) = (/ 1.158d-22, 2.648d-23, 6.014d-24, 1.502d-24, + & 4.211d-26, 0.000d0, 0.000d0 /) + QQQ(:,2) = (/ 5.664d-22, 1.681d-22, 4.919d-23, 1.477d-23, + & 5.602d-25, 0.000d0, 0.000d0 /) + QQQ(:,3) = (/ 2.804d-21, 1.092d-21, 4.079d-22, 1.496d-22, + & 7.707d-24, 0.000d0, 0.000d0 /) + endif + call X_interp_FJX (TT,QQQT, TQQ(1),QQQ(K,1), + & TQQ(2),QQQ(K,2), TQQ(3),QQQ(K,3), 3) + + end subroutine QQB +!EOC +!------------------------------------------------------------------------------ +! GEOS-Chem Global Chemical Transport Model ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: x_interp_fjx +! +! !DESCRIPTION: Up-to-three-point linear interpolation function for X-sections +!\\ +!\\ +! !INTERFACE: +! + subroutine X_interp_FJX (TINT,XINT, T1,X1, T2,X2, T3,X3, L123) +! +! !USES: +! + implicit none +# include "cmn_fj.h" +! +! !INPUT PARAMETERS: +! + real*8, intent(in):: TINT,T1,T2,T3, X1,X2,X3 + integer,intent(in):: L123 +! +! !OUTPUT PARAMETERS: +! + real*8,intent(out):: XINT +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + real*8 TFACT + + if (L123 .le. 1) then + XINT = X1 + elseif (L123 .eq. 2) then + TFACT = max(0.d0,min(1.d0,(TINT-T1)/(T2-T1) )) + XINT = X1 + TFACT*(X2 - X1) + else + if (TINT.le. T2) then + TFACT = max(0.d0,min(1.d0,(TINT-T1)/(T2-T1) )) + XINT = X1 + TFACT*(X2 - X1) + else + TFACT = max(0.d0,min(1.d0,(TINT-T2)/(T3-T2) )) + XINT = X2 + TFACT*(X3 - X2) + endif + endif + + END SUBROUTINE X_interp_FJX +!EOC + END MODULE FJX_ACET_MOD + diff --git a/code/future_emissions_mod.f b/code/future_emissions_mod.f new file mode 100644 index 0000000..12b245e --- /dev/null +++ b/code/future_emissions_mod.f @@ -0,0 +1,1449 @@ +! $Id: future_emissions_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE FUTURE_EMISSIONS_MOD +! +!****************************************************************************** +! Module FUTURE_EMISSIONS_MOD contains variables and routines for returning +! scale factors for IPCC A1 & B1 emissions scenarios for future years +! such as 2030, 2050, etc. (swu, bmy, 5/30/06) +! +! The baseline year for the IPCC scale factors is 1995. In other words, we +! compute 1995 emissions in GEOS-Chem and then multiply e.g. 2030/1995 scale +! factors to compute the emissions for the future year. +! +! Module Variables: +! ============================================================================ +! (1 ) FUTURE_YEAR : Year of future emissions (e.g. 2030, 2050) +! (2 ) SCENARIO : IPCC emissions scenario (e.g. A1, B1) +! (3 ) ALK4ff : Future scale factor array for fos-fuel ALK4 +! (4 ) BCbb : Future scale factor array for biomass BC +! (5 ) BCbf : Future scale factor array for biofuel BC +! (6 ) BCff : Future scale factor array for fos-fuel BC +! (7 ) C2H6ff : Future scale factor array for fos-fuel C2H6 +! (8 ) C3H8ff : Future scale factor array for fos-fuel C3H8 +! (9 ) CObb : Future scale factor array for biomass CO +! (10) CObf : Future scale factor array for biofuel CO +! (11) COff : Future scale factor array for fos-fuel CO +! (12) NH3an : Future scale factor array for anthro NH3 +! (13) NH3bb : Future scale factor array for biomass NH3 +! (14) NH3bf : Future scale factor array for biofuel NH3 +! (15) NOxbb : Future scale factor array for biomass NOx +! (16) NOxbf : Future scale factor array for biofuel NOx +! (17) NOxff : Future scale factor array for fos-fuel NOx +! (18) NOxft : Future scale factor array for fertiliz NOx +! (19) OCbb : Future scale factor array for biomass OC +! (20) OCbf : Future scale factor array for biofuel OC +! (21) OCff : Future scale factor array for fos-fuel OC +! (22) PRPEff : Future scale factor array for fossil PRPE +! (23) SO2bb : Future scale factor array for biomass SO2 +! (24) SO2bf : Future scale factor array for biofuel SO2 +! (25) SO2ff : Future scale factor array for fos-fuel SO2 +! (26) TONEff : Future scale factor array for fos-fuel TONE +! (27) VOCbb : Future scale factor array for biomass VOC +! (28) VOCbf : Future scale factor array for biofuel VOC +! (29) VOCff : Future scale factor array for fos-fuel VOC +! +! Module Routines: +! ============================================================================ +! (1 ) DO_FUTURE_EMISSIONS : Driver routine +! (2 ) READ_GROWTH_FACTORS : Reads future scale factors from disk +! (3 ) GET_FUTURE_YEAR : Returns the future emissions year +! (4 ) GET_FUTURE_SCENARIO : Returns the future emissions scenario +! (5 ) GET_FUTURE_SCALE_ALK4ff : Returns future fos-fuel ALK4 scale factors +! (6 ) GET_FUTURE_SCALE_BCbb : Returns future biomass BC scale factors +! (7 ) GET_FUTURE_SCALE_BCbf : Returns future biofuel BC scale factors +! (8 ) GET_FUTURE_SCALE_BCff : Returns future fos-fuel BC scale factors +! (9 ) GET_FUTURE_SCALE_C2H6ff : Returns future fos-fuel C2H6 scale factors +! (10) GET_FUTURE_SCALE_C3H8ff : Returns future fos-fuel C3H8 scale factors +! (11) GET_FUTURE_SCALE_CObb : Returns future biomass CO scale factors +! (12) GET_FUTURE_SCALE_CObf : Returns future biofuel CO scale factors +! (13) GET_FUTURE_SCALE_COff : Returns future fos-fuel CO scale factors +! (14) GET_FUTURE_SCALE_NH3an : Returns future anthro NH3 scale factors +! (15) GET_FUTURE_SCALE_NH3bb : Returns future biomass NH3 scale factors +! (16) GET_FUTURE_SCALE_NH3bf : Returns future biofuel NH3 scale factors +! (17) GET_FUTURE_SCALE_NOxbb : Returns future biomass NOx scale factors +! (18) GET_FUTURE_SCALE_NOxbf : Returns future biofuel NOx scale factors +! (19) GET_FUTURE_SCALE_NOxff : Returns future fos-fuel NOx scale factors +! (20) GET_FUTURE_SCALE_NOxft : Returns future fertiliz NOx scale factors +! (21) GET_FUTURE_SCALE_OCbb : Returns future biomass OC scale factors +! (22) GET_FUTURE_SCALE_OCbf : Returns future biofuel OC scale factors +! (23) GET_FUTURE_SCALE_OCff : Returns future fos-fuel OC scale factors +! (24) GET_FUTURE_SCALE_PRPEff : Returns future fos-fuel PRPE scale factors +! (25) GET_FUTURE_SCALE_SO2bb : Returns future biomass SO2 scale factors +! (26) GET_FUTURE_SCALE_SO2bf : Returns future biofuel SO2 scale factors +! (27) GET_FUTURE_SCALE_SO2ff : Returns future fos-fuel SO2 scale factors +! (28) GET_FUTURE_SCALE_TONEff : Returns future fos-fuel TONE scale factors +! (29) GET_FUTURE_SCALE_VOCbb : Returns future biomass VOC scale factors +! (30) GET_FUTURE_SCALE_VOCbf : Returns future biofuel VOC scale factors +! (31) GET_FUTURE_SCALE_VOCff : Returns future fos-fuel VOC scale factors +! (32) INIT_FUTURE_EMISSIONS : Initializes and allocates module arrays +! (33) CLEANUP_FUTURE_EMISSIONS : Deallocates all module arrays +! +! GEOS-Chem modules referenced by "future_emissions_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) directory_mod.f : Module w/ GEOS-CHEM met field and data dirs +! (3 ) error_mod.f : Module w/ I/O error and NaN check routines +! (4 ) file_mod.f : Module w/ file unit numbers & error checks +! (5 ) transfer_mod.f : Module w/ routines to cast & resize arrays +! +! References: +! ============================================================================ +! +! NOTES: +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "future_emissions_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these routines + PUBLIC :: CLEANUP_FUTURE_EMISSIONS + PUBLIC :: DO_FUTURE_EMISSIONS + PUBLIC :: GET_FUTURE_YEAR + PUBLIC :: GET_FUTURE_SCENARIO + PUBLIC :: GET_FUTURE_SCALE_ALK4ff + PUBLIC :: GET_FUTURE_SCALE_BCbb + PUBLIC :: GET_FUTURE_SCALE_BCbf + PUBLIC :: GET_FUTURE_SCALE_BCff + PUBLIC :: GET_FUTURE_SCALE_C2H6ff + PUBLIC :: GET_FUTURE_SCALE_C3H8ff + PUBLIC :: GET_FUTURE_SCALE_CObb + PUBLIC :: GET_FUTURE_SCALE_CObf + PUBLIC :: GET_FUTURE_SCALE_COff + PUBLIC :: GET_FUTURE_SCALE_NH3an + PUBLIC :: GET_FUTURE_SCALE_NH3bb + PUBLIC :: GET_FUTURE_SCALE_NH3bf + PUBLIC :: GET_FUTURE_SCALE_NOxbb + PUBLIC :: GET_FUTURE_SCALE_NOxbf + PUBLIC :: GET_FUTURE_SCALE_NOxff + PUBLIC :: GET_FUTURE_SCALE_NOxft + PUBLIC :: GET_FUTURE_SCALE_OCbb + PUBLIC :: GET_FUTURE_SCALE_OCbf + PUBLIC :: GET_FUTURE_SCALE_OCff + PUBLIC :: GET_FUTURE_SCALE_PRPEff + PUBLIC :: GET_FUTURE_SCALE_SO2bb + PUBLIC :: GET_FUTURE_SCALE_SO2bf + PUBLIC :: GET_FUTURE_SCALE_SO2ff + PUBLIC :: GET_FUTURE_SCALE_TONEff + PUBLIC :: GET_FUTURE_SCALE_VOCbb + PUBLIC :: GET_FUTURE_SCALE_VOCbf + PUBLIC :: GET_FUTURE_SCALE_VOCff + PUBLIC :: INIT_FUTURE_EMISSIONS + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Scalars + INTEGER :: FUTURE_YEAR + CHARACTER(LEN=2) :: SCENARIO + + ! Arrays + REAL*8, ALLOCATABLE :: ALK4ff(:,:) + REAL*8, ALLOCATABLE :: BCbb(:,:) + REAL*8, ALLOCATABLE :: BCbf(:,:) + REAL*8, ALLOCATABLE :: BCff(:,:) + REAL*8, ALLOCATABLE :: C2H6ff(:,:) + REAL*8, ALLOCATABLE :: C3H8ff(:,:) + REAL*8, ALLOCATABLE :: CObb(:,:) + REAL*8, ALLOCATABLE :: CObf(:,:) + REAL*8, ALLOCATABLE :: COff(:,:) + REAL*8, ALLOCATABLE :: NH3an(:,:) + REAL*8, ALLOCATABLE :: NH3bb(:,:) + REAL*8, ALLOCATABLE :: NH3bf(:,:) + REAL*8, ALLOCATABLE :: NOxbb(:,:) + REAL*8, ALLOCATABLE :: NOxbf(:,:) + REAL*8, ALLOCATABLE :: NOxff(:,:) + REAL*8, ALLOCATABLE :: NOxft(:,:) + REAL*8, ALLOCATABLE :: OCbb(:,:) + REAL*8, ALLOCATABLE :: OCbf(:,:) + REAL*8, ALLOCATABLE :: OCff(:,:) + REAL*8, ALLOCATABLE :: PRPEff(:,:) + REAL*8, ALLOCATABLE :: TONEff(:,:) + REAL*8, ALLOCATABLE :: SO2bb(:,:) + REAL*8, ALLOCATABLE :: SO2bf(:,:) + REAL*8, ALLOCATABLE :: SO2ff(:,:) + REAL*8, ALLOCATABLE :: VOCbb(:,:) + REAL*8, ALLOCATABLE :: VOCbf(:,:) + REAL*8, ALLOCATABLE :: VOCff(:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE DO_FUTURE_EMISSIONS( THIS_YEAR, THIS_SCEN ) +! +!****************************************************************************** +! Subroutine DO_FUTURE_EMISSIONS reads future emission growth factors +! into module arrays. This can be done once at the beginning of the +! GEOS-Chem simulation. (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) THIS_FY (INTEGER) : Year for future emission growth factors +! (2 ) THIS_SCEN (CHARACTER) : Emissions scenario (e.g. "A1", "B1", etc.) +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: THIS_YEAR + CHARACTER(LEN=*), INTENT(IN) :: THIS_SCEN + + ! Local variables + LOGICAL :: FIRST = .TRUE. + + !================================================================= + ! DO_FUTURE_EMISSIONS begins here! + !================================================================= + + ! Save module variables + FUTURE_YEAR = THIS_YEAR + SCENARIO = TRIM( THIS_SCEN ) + + ! First-time initialization + IF ( FIRST ) THEN + CALL INIT_FUTURE_EMISSIONS + FIRST = .FALSE. + ENDIF + + !---------------------- + ! Read growth factors + !---------------------- + + ! ALK4 + CALL READ_GROWTH_FACTORS( 'ALK4FF', 5, ALK4ff ) + + ! BC + CALL READ_GROWTH_FACTORS( 'BCBB', 34, BCbb ) + CALL READ_GROWTH_FACTORS( 'BCBF', 34, BCbf ) + CALL READ_GROWTH_FACTORS( 'BCFF', 34, BCff ) + + ! C2H6 + CALL READ_GROWTH_FACTORS( 'C2H6FF', 21, C2H6ff ) + + ! C3H8 + CALL READ_GROWTH_FACTORS( 'C3H8FF', 19, C3H8ff ) + + ! CO + CALL READ_GROWTH_FACTORS( 'COBB', 4, CObb ) + CALL READ_GROWTH_FACTORS( 'COBF', 4, CObf ) + CALL READ_GROWTH_FACTORS( 'COFF', 4, COff ) + + ! NH3 + CALL READ_GROWTH_FACTORS( 'NH3AN', 30, NH3an ) + CALL READ_GROWTH_FACTORS( 'NH3BB', 30, NH3bb ) + CALL READ_GROWTH_FACTORS( 'NH3BF', 30, NH3bf ) + + ! NOx + CALL READ_GROWTH_FACTORS( 'NOxBB', 1, NOxbb ) + CALL READ_GROWTH_FACTORS( 'NOxBF', 1, NOxbf ) + CALL READ_GROWTH_FACTORS( 'NOxFF', 1, NOxff ) + CALL READ_GROWTH_FACTORS( 'NOxFT', 1, NOxft ) + + ! OC + CALL READ_GROWTH_FACTORS( 'OCBB', 35, OCbb ) + CALL READ_GROWTH_FACTORS( 'OCBF', 35, OCbf ) + CALL READ_GROWTH_FACTORS( 'OCFF', 35, OCff ) + + ! PRPE + CALL READ_GROWTH_FACTORS( 'PRPEFF', 18, PRPEff ) + + ! TONE (Ketones > C3; use for ACET, MEK) + CALL READ_GROWTH_FACTORS( 'TONEFF', 9, TONEff ) + + ! SO2 + CALL READ_GROWTH_FACTORS( 'SO2BB', 26, SO2bb ) + CALL READ_GROWTH_FACTORS( 'SO2BF', 26, SO2bf ) + CALL READ_GROWTH_FACTORS( 'SO2FF', 26, SO2ff ) + + ! VOC + CALL READ_GROWTH_FACTORS( 'VOCBB', 90, VOCbb ) + CALL READ_GROWTH_FACTORS( 'VOCBF', 90, VOCbf ) + CALL READ_GROWTH_FACTORS( 'VOCFF', 90, VOCff ) + + !---------------------- + ! Print ranges + !---------------------- + + ! Write header + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a,/)' ) 'F U T U R E E M I S S I O N ' // + & 'G R O W T H F A C T O R S' + + ! Write year and scenario + WRITE( 6, 100 ) FUTURE_YEAR, SCENARIO + + ! Write totals + WRITE( 6, 110 ) 'ALK4ff', MINVAL( ALK4ff ), MAXVAL( ALK4ff ) + WRITE( 6, 110 ) 'BCbb', MINVAL( BCbb ), MAXVAL( BCbb ) + WRITE( 6, 110 ) 'BCbf', MINVAL( BCbf ), MAXVAL( BCbf ) + WRITE( 6, 110 ) 'BCff', MINVAL( BCff ), MAXVAL( BCff ) + WRITE( 6, 110 ) 'C2H6ff', MINVAL( C2H6ff ), MAXVAL( C2H6ff ) + WRITE( 6, 110 ) 'C3H8ff', MINVAL( C3H8ff ), MAXVAL( C3H8ff ) + WRITE( 6, 110 ) 'CObb', MINVAL( CObb ), MAXVAL( CObb ) + WRITE( 6, 110 ) 'CObf', MINVAL( CObf ), MAXVAL( CObf ) + WRITE( 6, 110 ) 'COff', MINVAL( COff ), MAXVAL( COff ) + WRITE( 6, 110 ) 'NH3an', MINVAL( NH3an ), MAXVAL( NH3an ) + WRITE( 6, 110 ) 'NH3bb', MINVAL( NH3bb ), MAXVAL( NH3bb ) + WRITE( 6, 110 ) 'NH3bf', MINVAL( NH3bf ), MAXVAL( NH3bf ) + WRITE( 6, 110 ) 'NOxbb', MINVAL( NOxbb ), MAXVAL( NOxbb ) + WRITE( 6, 110 ) 'NOxbf', MINVAL( NOxbf ), MAXVAL( NOxbf ) + WRITE( 6, 110 ) 'NOxff', MINVAL( NOxff ), MAXVAL( NOxff ) + WRITE( 6, 110 ) 'NOxft', MINVAL( NOxft ), MAXVAL( NOxft ) + WRITE( 6, 110 ) 'OCbb', MINVAL( OCbb ), MAXVAL( OCbb ) + WRITE( 6, 110 ) 'OCbf', MINVAL( OCbf ), MAXVAL( OCbf ) + WRITE( 6, 110 ) 'OCff', MINVAL( OCff ), MAXVAL( OCff ) + WRITE( 6, 110 ) 'PRPEff', MINVAL( PRPEff ), MAXVAL( PRPEff ) + WRITE( 6, 110 ) 'TONEff', MINVAL( TONEff ), MAXVAL( TONEff ) + WRITE( 6, 110 ) 'SO2bb', MINVAL( SO2bb ), MAXVAL( SO2bb ) + WRITE( 6, 110 ) 'SO2bf', MINVAL( SO2bf ), MAXVAL( SO2bf ) + WRITE( 6, 110 ) 'SO2ff', MINVAL( SO2ff ), MAXVAL( SO2ff ) + WRITE( 6, 110 ) 'VOCbb', MINVAL( VOCbb ), MAXVAL( VOCbb ) + WRITE( 6, 110 ) 'VOCbf', MINVAL( VOCbf ), MAXVAL( VOCbf ) + WRITE( 6, 110 ) 'VOCff', MINVAL( VOCff ), MAXVAL( VOCff ) + + ! Write footer + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! FORMAT statements + 100 FORMAT( 'for year ', i4, ' and emissions scenario ', a2, / ) + 110 FORMAT( a6, ' growth factors range from ', f8.3, ' to ', f8.3 ) + + ! Return to calling program + END SUBROUTINE DO_FUTURE_EMISSIONS + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_GROWTH_FACTORS( SPECIES, TRACER, GRFACTORS ) +! +!****************************************************************************** +! Subroutine READ_GROWTH_FACTORS reads the future growth factors for one +! species, future year, and scenario from disk. (swu, bmy, 5/30/06) +! +! If growth factors for a particular species do not exist for a given future +! year and scenario, then the READ_GROWTH_FACTORS will return and the +! GRFACTORS array will be set to 1 everywhere. +! +! The baseline year for the IPCC scale factors is 1995. In other words, we +! compute 1995 emissions in GEOS-Chem and then multiply e.g. 2030/1995 scale +! factors to compute the emissions for the future year. +! +! Arguments as Input: +! ============================================================================ +! (1 ) SPECIES (CHARACTER) : Species name to read (e.g. "NOxbb, CObb", etc) +! (2 ) TRACER (INTEGER ) : Tracer number +! +! Arguments as Output: +! ============================================================================ +! (3 ) GRFACTORS (REAL*8 ) : Array of growth factors +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_RES_EXT, GET_NAME_EXT + USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : FILE_EXISTS + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters + + INTEGER, INTENT(IN) :: TRACER + CHARACTER(LEN=*), INTENT(IN) :: SPECIES + REAL*8, INTENT(OUT) :: GRFACTORS(IIPAR,JJPAR) + + ! Local variables + INTEGER :: IOS, IUNIT + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*8 :: TAU0 + CHARACTER(LEN=4) :: YSTR + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_GROWTH_FACTORS begins here! + !================================================================= + + ! Initialize + GRFACTORS(:,:) = 1d0 + + ! Create a string for the 4-digit year + WRITE( YSTR, '(i4)' ) FUTURE_YEAR + + ! File name + FILENAME = TRIM( DATA_DIR ) // + & 'future_emissions_200605/' // YSTR // + & '/' // SCENARIO // + & '/' // SPECIES // + & '_' // SCENARIO // + & '.' // GET_NAME_EXT() // + & '.' // GET_RES_EXT() // + & '.' // YSTR + + ! Return if file is not found (growth factors array = 1) + IF ( .not. FILE_EXISTS( FILENAME ) ) RETURN + + ! TAU0 value for the future year + TAU0 = GET_TAU0( 1, 1, FUTURE_YEAR ) + + ! ACET is stored in the biomass file as tracer #9 + CALL READ_BPCH2( FILENAME, 'FUTURE-E', TRACER, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 + CALL TRANSFER_2D( ARRAY(:,:,1), GRFACTORS ) + + ! Return to calling program + END SUBROUTINE READ_GROWTH_FACTORS + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_YEAR() RESULT( THIS_YEAR ) +! +!****************************************************************************** +! Function GET_FUTURE_YEAR returns the year for future emissions +! to the calling program. (swu, bmy, 5/30/06) +! +! NOTES: +!****************************************************************************** +! + ! Function value + REAL*8 :: THIS_YEAR + + !================================================================= + ! GET_FUTURE_YEAR begins here! + !================================================================= + THIS_YEAR = FUTURE_YEAR + + ! Return to calling program + END FUNCTION GET_FUTURE_YEAR + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCENARIO() RESULT( THIS_SCEN ) +! +!****************************************************************************** +! Function GET_FUTURE_SCENARIO returns the IPCC future emissions scenario +! (e.g. A1, B1) for future emissions to the calling program. +! (swu, bmy, 5/30/06) +! +! NOTES: +!****************************************************************************** +! + ! Function value + CHARACTER(LEN=255) :: THIS_SCEN + + !================================================================= + ! GET_FUTURE_SCENARIO begins here! + !================================================================= + THIS_SCEN = TRIM( SCENARIO ) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCENARIO + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_ALK4ff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_ALK4ff returns the future scale factor for +! Fossil Fuel ALK4 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_ALK4ff begins here! + !================================================================= + SCALEFAC = ALK4ff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_ALK4ff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_BCbb( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_BCbb returns the future scale factor for +! biomass burning BC for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_BCbb begins here! + !================================================================= + SCALEFAC = BCbb(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_BCbb + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_BCbf( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_BCbf returns the future scale factor for +! biofuel BC for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_BCbf begins here! + !================================================================= + SCALEFAC = BCbf(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_BCbf + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_BCff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_BCff returns the future scale factor for +! Fossil Fuel BC for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_BCff begins here! + !================================================================= + SCALEFAC = BCff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_BCff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_C2H6ff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_C2H6ff returns the future scale factor for +! Fossil Fuel C2H6 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_C2H6ff begins here! + !================================================================= + SCALEFAC = C2H6ff( I, J ) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_C2H6ff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_C3H8ff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_C3H8ff returns the future scale factor for +! Fossil Fuel C3H8 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_C3H8ff begins here! + !================================================================= + SCALEFAC = C3H8ff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_C3H8ff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_CObb( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_CObb returns the future scale factor for +! biomass burning CO for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_CObb begins here! + !================================================================= + SCALEFAC = CObb(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_CObb + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_CObf( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_CObf returns the future scale factor for +! biofuel CO for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_CObf begins here! + !================================================================= + SCALEFAC = CObf(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_CObf + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_COff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_COff returns the future scale factor for +! Fossil Fuel CO for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_COff begins here! + !================================================================= + SCALEFAC = COff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_COff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_NH3an( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_NH3an returns the future scale factor for +! anthropogenic NH3 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_NH3an begins here! + !================================================================= + SCALEFAC = NH3an(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_NH3an + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_NH3bb( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_NH3bb returns the future scale factor for +! biomass burning NH3 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_NH3bb begins here! + !================================================================= + SCALEFAC = NH3bb(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_NH3bb + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_NH3bf( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_NH3bf returns the future scale factor for +! biofuel NH3 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_NH3bf begins here! + !================================================================= + SCALEFAC = NH3bf(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_NH3bf + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_NOxbb( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_NOxbb returns the future scale factor for +! biomass burning NOx for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_NOxbb begins here! + !================================================================= + SCALEFAC = NOXbb(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_NOxbb + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_NOxbf( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_NOXbf returns the future scale factor for +! biofuel NOx for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_NOxbf begins here! + !================================================================= + SCALEFAC = NOxbf(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_NOxbf + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_NOxff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_NOxff returns the future scale factor for +! Fossil Fuel NOx for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_NOxff begins here! + !================================================================= + SCALEFAC = NOxff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_NOxff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_NOxft( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_NOxft returns the future scale factor +! for NOx from the free tropoposphere the GEOS-Chem grid box (I,J) +! (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_NOxft begins here! + !================================================================= + SCALEFAC = NOxft(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_NOxft + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_OCbb( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_OCbb returns the future scale factor for +! biomass burning OC for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_OCbb begins here! + !================================================================= + SCALEFAC = OCbb(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_OCbb + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_OCbf( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_OCbf returns the future scale factor for +! biofuel OC for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_OCbf begins here! + !================================================================= + SCALEFAC = OCbf(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_OCbf + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_OCff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_OCff returns the future scale factor for +! Fossil Fuel ACET for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_OCff begins here! + !================================================================= + SCALEFAC = OCff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_OCff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_PRPEff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_PRPEff returns the future scale factor for +! Fossil Fuel PRPE for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_PRPEff begins here! + !================================================================= + SCALEFAC = PRPEff( I, J ) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_PRPEff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_TONEff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_TONEff returns the future scale factor for +! Fossil Fuel TONE (Ketones > C3, such as ACET, MEK) for the GEOS-Chem grid +! box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_TONEff begins here! + !================================================================= + SCALEFAC = TONEff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_TONEff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_SO2bb( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_SO2bb returns the future scale factor for +! Fossil Fuel ACET for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_SO2bb begins here! + !================================================================= + SCALEFAC = SO2bb(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_SO2bb + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_SO2bf( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_SO2bf returns the future scale factor for +! biofuel SO2 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_SO2bf begins here! + !================================================================= + SCALEFAC = SO2bf(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_SO2bf + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_SO2ff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_SO2ff returns the future scale factor for +! Fossil Fuel SO2 for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_SO2ff begins here! + !================================================================= + SCALEFAC = SO2ff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_SO2ff + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_VOCbb( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_VOCbb returns the future scale factor for +! biomass burning VOC's for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_VOCbb begins here! + !================================================================= + SCALEFAC = VOCbb(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_VOCbb + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_VOCbf( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_VOCbf returns the future scale factor for +! biofuel VOC's for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_VOCbf begins here! + !================================================================= + SCALEFAC = VOCbf(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_VOCbf + +!------------------------------------------------------------------------------ + + FUNCTION GET_FUTURE_SCALE_VOCff( I, J ) RESULT( SCALEFAC ) +! +!****************************************************************************** +! Function GET_FUTURE_SCALE_VOCff returns the future scale factor for +! Fossil Fuel VOC's for the GEOS-Chem grid box (I,J) (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) :: GEOS-Chem longitude index +! (2 ) J (INTEGER) :: GEOS-Chem latitude index +! +! NOTES: +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: I, J + + ! Function variable + REAL*8 :: SCALEFAC + + !================================================================= + ! GET_FUTURE_SCALE_VOCff begins here! + !================================================================= + SCALEFAC = VOCff(I,J) + + ! Return to calling program + END FUNCTION GET_FUTURE_SCALE_VOCff + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_FUTURE_EMISSIONS +! +!****************************************************************************** +! Subroutine CLEANUP_FUTURE_EMISSIONS allocates and initializes all module +! arrays. (swu, bmy, 5/30/06) +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : ALLOC_ERR + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: AS + + !================================================================= + ! INIT_FUTURE_EMISSIONS begins here! + !================================================================= + + ALLOCATE( ALK4ff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'ALK4ff' ) + ALK4ff = 1d0 + + ALLOCATE( BCbb( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'BCbb' ) + BCbb = 1d0 + + ALLOCATE( BCbf( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( '' ) + BCbf = 1d0 + + ALLOCATE( BCff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'BCff' ) + BCff = 1d0 + + ALLOCATE( C2H6ff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'C2H6ff' ) + C2H6ff = 1d0 + + ALLOCATE( C3H8ff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'CH38ff' ) + C3H8ff = 1d0 + + ALLOCATE( CObb( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'CObb' ) + CObb = 1d0 + + ALLOCATE( CObf( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'CObf' ) + CObf = 1d0 + + ALLOCATE( COff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'COff' ) + COff = 1d0 + + ALLOCATE( NH3an( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'NH3an' ) + NH3an = 1d0 + + ALLOCATE( NH3bb( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'NH3bb' ) + NH3bb = 1d0 + + ALLOCATE( NH3bf( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'NH3bf' ) + NH3bf = 1d0 + + ALLOCATE( NOxbb( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'NOxbb' ) + NOXbb = 1d0 + + ALLOCATE( NOxbf( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'NOxbf' ) + NOxbf = 1d0 + + ALLOCATE( NOxff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'NOxff' ) + NOxff = 1d0 + + ALLOCATE( NOxft ( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'NOxft' ) + NOxft = 1d0 + + ALLOCATE( OCbb( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'OCbb' ) + OCbb = 1d0 + + ALLOCATE( OCbf( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'OCbf' ) + OCbf = 1d0 + + ALLOCATE( OCff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'OCff' ) + OCff = 1d0 + + ALLOCATE( PRPEff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'PRPEff' ) + PRPEff = 1d0 + + ALLOCATE( TONEff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'TONEff' ) + TONEff = 1d0 + + ALLOCATE( SO2bb( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'SO2bb' ) + SO2bb = 1d0 + + ALLOCATE( SO2bf( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'SO2bf' ) + SO2bf = 1d0 + + ALLOCATE( SO2ff( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'SO2ff' ) + SO2ff = 1d0 + + ALLOCATE( VOCbb( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'VOCbb' ) + VOCbb = 1d0 + + ALLOCATE( VOCbf ( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'VOCbf' ) + VOCbf = 1d0 + + ALLOCATE( VOCff ( IIPAR, JJPAR ), STAT=AS ) + IF ( AS /=0 ) CALL ALLOC_ERR( 'VOCff' ) + VOCff = 1d0 + + ! Return to calling program + END SUBROUTINE INIT_FUTURE_EMISSIONS + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_FUTURE_EMISSIONS +! +!****************************************************************************** +! Subroutine CLEANUP_FUTURE_EMISSIONS deallocates all module arrays. +! (swu, bmy, 5/30/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_FUTURE_EMISSIONS begins here! + !================================================================= + IF ( ALLOCATED( ALK4ff ) ) DEALLOCATE( ALK4ff ) + IF ( ALLOCATED( BCbb ) ) DEALLOCATE( BCbb ) + IF ( ALLOCATED( BCbf ) ) DEALLOCATE( BCbf ) + IF ( ALLOCATED( BCff ) ) DEALLOCATE( BCff ) + IF ( ALLOCATED( C2H6ff ) ) DEALLOCATE( C2H6ff ) + IF ( ALLOCATED( C3H8ff ) ) DEALLOCATE( C3H8ff ) + IF ( ALLOCATED( CObb ) ) DEALLOCATE( CObb ) + IF ( ALLOCATED( CObf ) ) DEALLOCATE( CObf ) + IF ( ALLOCATED( COff ) ) DEALLOCATE( COff ) + IF ( ALLOCATED( NH3an ) ) DEALLOCATE( NH3an ) + IF ( ALLOCATED( NH3bb ) ) DEALLOCATE( NH3bb ) + IF ( ALLOCATED( NH3bf ) ) DEALLOCATE( NH3bf ) + IF ( ALLOCATED( NOxbb ) ) DEALLOCATE( NOxbb ) + IF ( ALLOCATED( NOxbf ) ) DEALLOCATE( NOxbf ) + IF ( ALLOCATED( NOxff ) ) DEALLOCATE( NOxff ) + IF ( ALLOCATED( NOxft ) ) DEALLOCATE( NOxft ) + IF ( ALLOCATED( OCbb ) ) DEALLOCATE( OCbb ) + IF ( ALLOCATED( OCbf ) ) DEALLOCATE( OCbf ) + IF ( ALLOCATED( OCff ) ) DEALLOCATE( OCff ) + IF ( ALLOCATED( PRPEff ) ) DEALLOCATE( PRPEff ) + IF ( ALLOCATED( TONEff ) ) DEALLOCATE( TONEff ) + IF ( ALLOCATED( SO2bb ) ) DEALLOCATE( SO2bb ) + IF ( ALLOCATED( SO2bf ) ) DEALLOCATE( SO2bf ) + IF ( ALLOCATED( SO2ff ) ) DEALLOCATE( SO2ff ) + IF ( ALLOCATED( VOCbb ) ) DEALLOCATE( VOCbb ) + IF ( ALLOCATED( VOCbf ) ) DEALLOCATE( VOCbf ) + IF ( ALLOCATED( VOCff ) ) DEALLOCATE( VOCff ) + + ! Return to calling program + END SUBROUTINE CLEANUP_FUTURE_EMISSIONS + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE FUTURE_EMISSIONS_MOD diff --git a/code/fvdas_convect_mod.f b/code/fvdas_convect_mod.f new file mode 100644 index 0000000..13687b6 --- /dev/null +++ b/code/fvdas_convect_mod.f @@ -0,0 +1,1329 @@ +! $Id: fvdas_convect_mod.f,v 1.1 2009/06/09 21:51:54 daven Exp $ + MODULE FVDAS_CONVECT_MOD +! +!****************************************************************************** +! Module FVDAS_CONVECT_MOD contains routines (originally from NCAR) which +! perform shallow and deep convection for the GEOS-4/fvDAS met fields. +! These routines account for shallow and deep convection, plus updrafts +! and downdrafts. (pjr, dsa, bmy, 6/26/03, 12/19/06) +! +! Module Variables: +! ============================================================================ +! (1 ) RLXCLM (LOGICAL) : Logical to relax column versus cloud triplet +! (2 ) LIMCNV (INTEGER) : Maximum CTM level for HACK convection +! (3 ) CMFTAU (REAL*8 ) : Characteristic adjustment time scale for HACK [s] +! (4 ) EPS (REAL*8 ) : A very small number [unitless] +! (5 ) GRAV (REAL*8 ) : Gravitational constant [m/s2] +! (6 ) SMALLEST (REAL*8 ) : The smallest double-precision number +! (7 ) TINYNUM (REAL*8 ) : 2 times EPS +! (8 ) TINYALT (REAL*8 ) : arbitrary small num used in transport estimates +! +! Module Routines: +! ============================================================================ +! (1 ) INIT_FVDAS_CONVECT : Initializes fvDAS convection scheme +! (2 ) FVDAS_CONVECT : fvDAS convection routine, called from MAIN +! (3 ) HACK_CONV : HACK convection scheme routine +! (4 ) ARCCONVTRAN : Sets up fields for ZHANG/MCFARLANE convection +! (5 ) CONVTRAN : ZHANG/MCFARLANE convection scheme routine +! (6 ) WHENFGT : Returns index array of points > a reference value +! +! GEOS-CHEM modules referenced by fvdas_convect_mod.f: +! ============================================================================ +! (1 ) pressure_mod.f : Module containing routines to compute P(I,J,L) +! +! NOTES: +! (1 ) Contains new updates for GEOS-4/fvDAS convection. Also added OpenMP +! parallel loop over latitudes in FVDAS_CONVECT. (swu, bmy, 1/21/04) +! (2 ) Now prevent FTMP, QTMP arrays from being held PRIVATE w/in the +! parallel loop in routine DO_CONVECTION (bmy, 7/20/04) +! (3 ) Now pass wet-scavenged Hg2 to "ocean_mercury_mod.f" (sas, bmy, 1/21/05) +! (4 ) Rewrote parallel loops to avoid problems w/ OpenMP. Also modified +! for updated Hg simulation. (cdh, bmy, 2/1/06) +! (5 ) Rewrote DO loops in HACK_CONV for better optmization (bmy, 3/28/06) +! (6 ) Split up Hg2 IF statement into 2 separate statements (bmy, 4/17/06) +! (7 ) Minor fix in ND38 diagnostic: replace 1 w/ 1d0 (bmy, 5/24/06) +! (8 ) Updated for ND14 diagnostic. Now treat "negative" detrainment as +! entrainment, which will better conserve mixing ratio in convection. +! (swu, bmy, 6/27/06) +! (9 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (10) Bug fix in CONVTRAN to avoid div potential div by zero. Make SMALLEST +! = 1d-60 to avoid problems (bmy, 12/19/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "fvdas_convect_mod.f" + !================================================================= + + ! Declare everything PRIVATE ... + PRIVATE + + ! ... except these routines + PUBLIC :: INIT_FVDAS_CONVECT + PUBLIC :: FVDAS_CONVECT + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Variables + INTEGER :: LIMCNV + + ! Constants + LOGICAL, PARAMETER :: RLXCLM = .TRUE. + REAL*8, PARAMETER :: CMFTAU = 3600.d0 + REAL*8, PARAMETER :: EPS = 1.0d-13 + REAL*8, PARAMETER :: GRAV = 9.8d0 + REAL*8, PARAMETER :: SMALLEST = 1.0d-60 + REAL*8, PARAMETER :: TINYALT = 1.0d-36 + REAL*8, PARAMETER :: TINYNUM = 2*SMALLEST + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE INIT_FVDAS_CONVECT +! +!****************************************************************************** +! Subroutine INIT_FVDAS_CONVECT initializes the HACK and +! ZHANG/MCFARLANE convection schemes for GEOS-4/fvDAS met fields. +! (dsa, swu, bmy, 6/26/03, 12/17/03) +! +! NOTES: +! (1 ) Now compute HYPI in a more efficient way (bmy, 12/17/03) +!****************************************************************************** +! + ! References to F90 modules + USE PRESSURE_MOD, ONLY : GET_PEDGE + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + INTEGER :: I, J, L, L2 + REAL*8 :: HYPI(LLPAR+1) + + !================================================================= + ! INIT_FVDAS_CONVECT begins here! + ! + ! Find the model level that roughly corresponds to 40 hPa and + ! only let convection take place below that level (LIMCNV) + !================================================================= + + ! Take I, J at midpt of region + ! (For global grids, this should be the equatorial box) + I = IIPAR / 2 + J = JJPAR / 2 + + ! Construct array of pressure edges [hPa] for column (I,J) + DO L = 1, LLPAR+1 + L2 = (LLPAR+1) - L + 1 + HYPI(L2) = GET_PEDGE(I,J,L) + ENDDO + + ! Limit convection to regions below 40 hPa + IF ( HYPI(1) >= 40d0 ) THEN + LIMCNV = 1 + ELSE + DO L = 1, LLPAR + IF ( HYPI(L) < 40d0 .AND. HYPI(L+1) >= 40d0 ) THEN + LIMCNV = L + GOTO 10 + ENDIF + ENDDO + LIMCNV = LLPAR + 1 + ENDIF + + ! Exit loop + 10 CONTINUE + + !================================================================= + ! Echo output + !================================================================= + + WRITE( 6, 100 ) LIMCNV, HYPI(LIMCNV) + 100 FORMAT( ' - GEOS-4 convection is capped at L = ', i3, + & ', or approx ', f6.1, ' hPa' ) + + ! Return to calling program + END SUBROUTINE INIT_FVDAS_CONVECT + +!------------------------------------------------------------------------------ + + SUBROUTINE FVDAS_CONVECT( TDT, NTRACE, Q, RPDEL, ETA, + & BETA, MU, MD, EU, DP, + & NSTEP, FRACIS, TCVV, INDEXSOL ) +! +!****************************************************************************** +! Subroutine FVDAS_CONVECT is the convection driver routine for GEOS-4/fvDAS +! met fields. It calls both HACK and ZHANG/MCFARLANE convection schemes. +! (pjr, dsa, bmy, 6/26/03, 12/13/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TDT (REAL*8 ) : 2 * delta-T [s] +! (2 ) NTRACE (INTEGER) : Number of tracers to transport [unitless] +! (3 ) Q (REAL*8 ) : Array of transported tracers [v/v] +! (4 ) RPDEL (REAL*8 ) : 1 / DP [1/hPa] +! (5 ) ETA (REAL*8 ) : GMAO Hack convective mass flux [kg/m2/s] +! (6 ) BETA (REAL*8 ) : GMAO Hack overshoot parameter [unitless] +! (7 ) MU (REAL*8 ) : GMAO updraft mass flux (ZMMU) [Pa/s] +! (8 ) MD (REAL*8 ) : GMAO downdraft mass flux (ZMMD) [Pa/s] +! (9 ) EU (REAL*8 ) : GMAO updraft entrainment (ZMEU) [Pa/s] +! (10) DP (REAL*8 ) : Delta-pressure between level edges [Pa] +! (11) NSTEP (INTEGER) : Time step index [unitless] +! (12) FRACIS (REAL*8 ) : Fraction of tracer that is insoluble [unitless] +! (13) TCVV (REAL*8 ) : Array of Molwt(AIR)/molwt(Tracer) [unitless] +! (14) INDEXSOL(INTEGER) : Index array of soluble tracers [unitless] +! +! Arguments as Output: +! ============================================================================ +! (3 ) Q (REAL*8 ) : Modified tracer array [v/v] +! +! Important Local Variables: +! ============================================================================ +! (1 ) LENGATH (INTEGER) : Number of lons where deep conv. happens at lat=J +! (2 ) IDEEP (INTEGER) : Lon indices where deep convection happens at lat=J +! (3 ) JT (INTEGER) : Cloud top layer for columns undergoing conv. +! (4 ) MX (INTEGER) : Cloud bottom layer for columns undergoing conv. +! (5 ) DSUBCLD (REAL*8 ) : Delta pressure from cloud base to sfc +! (6 ) DU (REAL*8 ) : Mass detraining from updraft (lon-alt array) +! (7 ) ED (REAL*8 ) : Mass entraining from downdraft (lon-alt array) +! (8 ) DPG (REAL*8 ) : gathered .01*dp (lon-alt array) +! (8 ) EUG (REAL*8 ) : gathered eu (lon-alt array) +! (9 ) MUG (REAL*8 ) : gathered mu (lon-alt array) +! (10) MDG (REAL*8 ) : gathered md (lon-alt array) +! +! NOTES: +! (1 ) Added TCVV and INDEXSOL to the arg list and in the call to CONVTRAN. +! Now perform convection in a loop over NSTEP iterations. Added +! an OpenMP parallel loop over latitude. Removed IL1G and IL2G, +! since these are no longer needed in this routine. Now put NTRACE +! before Q on the arg list. (bmy, 1/21/04) +! (2 ) Handle parallel loops differently for Intel Fortran Compilers, since +! for some reason the code dies if large arrays (QTMP, FTMP) are held +! PRIVATE in parallel loops. (bmy, 7/20/04) +! (3 ) Added LINUX_IFORT switch for Intel v8/v9 compilers (bmy, 10/18/05) +! (4 ) Rewrote parallel loops so that we pass entire arrays to the various +! subroutines instead of array slices such as (:,J,:). This can cause +! problems with OpenMP for some compilers. (bmy, 12/13/05) +!****************************************************************************** + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: NSTEP, NTRACE + INTEGER, INTENT(IN) :: INDEXSOL(NTRACE) + REAL*8, INTENT(IN) :: TDT + REAL*8, INTENT(INOUT) :: Q(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: RPDEL(IIPAR,JJPAR,LLPAR) + REAL*8, INTENT(IN) :: ETA (:,:,:) + REAL*8, INTENT(IN) :: BETA(:,:,:) + REAL*8, INTENT(IN) :: MU (:,:,:) + REAL*8, INTENT(IN) :: MD (:,:,:) + REAL*8, INTENT(IN) :: EU (:,:,:) + REAL*8, INTENT(IN) :: DP(IIPAR,JJPAR,LLPAR) + REAL*8, INTENT(IN) :: FRACIS(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: TCVV(NTRACE) + + ! Local variables + INTEGER :: I, J, L, N, LENGATH, ISTEP + INTEGER :: JT(IIPAR) + INTEGER :: MX(IIPAR) + INTEGER :: IDEEP(IIPAR) + REAL*8 :: DSUBCLD(IIPAR) + REAL*8 :: DPG(IIPAR,LLPAR) + REAL*8 :: DUG(IIPAR,LLPAR) + REAL*8 :: EDG(IIPAR,LLPAR) + REAL*8 :: EUG(IIPAR,LLPAR) + REAL*8 :: MDG(IIPAR,LLPAR) + REAL*8 :: MUG(IIPAR,LLPAR) + + !================================================================= + ! FVDAS_CONVECT begins here! + !================================================================= + + ! Loop over latitudes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( J, MUG, MDG, DUG, EUG, EDG, DPG ) +!$OMP+PRIVATE( DSUBCLD, JT, MX, IDEEP, LENGATH, ISTEP ) +!$OMP+SCHEDULE( DYNAMIC ) + DO J = 1, JJPAR + + ! Gather mass flux arrays, compute mass fluxes, and determine top + ! and bottom of Z&M convection. LENGATH = # of longitudes in the + ! band I=1,IIPAR where deep convection happens at latitude J. + CALL ARCONVTRAN( J, DP, MU, MD, + & EU, MUG, MDG, DUG, + & EUG, EDG, DPG, DSUBCLD, + & JT, MX, IDEEP, LENGATH ) + + ! Loop over internal convection timestep + DO ISTEP = 1, NSTEP + + !----------------------------------- + ! ZHANG/MCFARLANE (deep) convection + !----------------------------------- + + ! Only call CONVTRAN where convection happens + ! (i.e. at latitudes where LENGATH > 0) + IF ( LENGATH > 0 ) THEN + CALL CONVTRAN( J, NTRACE, Q, MUG, MDG, + & DUG, EUG, EDG, DPG, DSUBCLD, + & JT, MX, IDEEP, 1, LENGATH, + & NSTEP, 0.5D0*TDT, FRACIS, TCVV, INDEXSOL ) + ENDIF + + !----------------------------------- + ! HACK (shallow) convection + !----------------------------------- + CALL HACK_CONV( J, TDT, RPDEL, ETA, BETA, NTRACE, Q ) + + ENDDO + + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE FVDAS_CONVECT + +!------------------------------------------------------------------------------ + + SUBROUTINE HACK_CONV( J, TDT, RPDEL, ETA, BETA, NTRACE, Q ) +! +!****************************************************************************** +! Subroutine HACK_CONV computes the convective mass flux adjustment to all +! tracers using the convective mass fluxes and overshoot parameters for the +! Hack scheme. (pjr, dsa, bmy, 6/26/03, 3/28/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : GEOS-CHEM Latitude index [unitless] +! (2 ) TDT (REAL*8 ) : 2 delta-t [s ] +! (3 ) RPDEL (REAL*8 ) : Reciprocal of pressure-thickness array [1/hPa ] +! (4 ) ETA (REAL*8 ) : GMAO Hack convective mass flux (HKETA) [kg/m2/s ] +! (5 ) BETA (REAL*8 ) : GMAO Hack overshoot parameter (HKBETA) [unitless] +! (6 ) NTRACE (INTEGER) : Number of tracers in the Q array [unitless] +! (7 ) Q (REAL*8 ) : Tracer concentrations [v/v ] +! +! Arguments as Output: +! ============================================================================ +! (7 ) Q (REAL*8 ) : Modified tracer concentrations [v/v ] +! +! Important Local Variables: +! ============================================================================ +! (1 ) ADJFAC (REAL*8 ) : Adjustment factor (relaxation related) +! (2 ) BOTFLX (REAL*8 ) : Bottom constituent mixing ratio flux +! (3 ) CMRC (REAL*8 ) : Constituent mixing ratio ("in-cloud") +! (4 ) CMRH (REAL*8 ) : Interface constituent mixing ratio +! (5 ) DCMR1 (REAL*8 ) : Q convective change (lower level) +! (6 ) DCMR2 (REAL*8 ) : Q convective change (mid level) +! (7 ) DCMR3 (REAL*8 ) : Q convective change (upper level) +! (8 ) EFAC1 (REAL*8 ) : Ratio q to convectively induced change (bot level) +! (9 ) EFAC2 (REAL*8 ) : Ratio q to convectively induced change (mid level) +! (10) EFAC3 (REAL*8 ) : Ratio q to convectively induced change (top level) +! (11) ETAGDT (REAL*8 ) : ETA * GRAV * DT +! (12) TOPFLX (REAL*8 ) : Top constituent mixing ratio flux +! +! NOTES: +! (1 ) Updated comments. Added NTRACE as an argument. Now also force +! double-precision with the "D" exponents. (bmy, 6/26/03) +! (2 ) Now pass J via the arg list. Now dimension RPDEL, ETA, BETA, and Q +! with and make all input arrays dimensioned +! with (IIPAR,JJPAR,LLPAR,...) to avoid seg fault error in OpenMP +! on certain platforms. +! (3 ) Rewrote DO loops and changed 1-D arrays into scalars in order to +! improve optimization, particularly for the Intel IFORT v9 compiler. +! (bmy, 3/28/06) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: J, NTRACE + REAL*8, INTENT(IN) :: TDT + REAL*8, INTENT(IN) :: RPDEL(IIPAR,JJPAR,LLPAR) + REAL*8, INTENT(IN) :: ETA (:,:,:) + REAL*8, INTENT(IN) :: BETA(:,:,:) + REAL*8, INTENT(INOUT) :: Q(IIPAR,JJPAR,LLPAR,NTRACE) + + ! Local variables + INTEGER :: I, K, M + REAL*8 :: ADJFAC, BOTFLX, TOPFLX + REAL*8 :: EFAC1, EFAC2, EFAC3 + REAL*8 :: CMRC, DCMR1, DCMR2 + REAL*8 :: DCMR3, ETAGDT, CMRH(IIPAR,LLPAR+1) + + !================================================================= + ! HACK_CONV begins here! + ! + ! Ensure that characteristic adjustment time scale (cmftau) + ! assumed in estimate of eta isn't smaller than model time scale + ! (tdt). The time over which the convection is assumed to act + ! (the adjustment time scale) can be applied with each application + ! of the three-level cloud model, or applied to the column + ! tendencies after a "hard" adjustment (i.e., on a 2-delta t + ! time scale) is evaluated + !================================================================= + IF ( RLXCLM ) THEN + ADJFAC = TDT / ( MAX( TDT, CMFTAU ) ) + ELSE + ADJFAC = 1d0 + ENDIF + + !================================================================= + ! Begin moist convective mass flux adjustment procedure. + ! The formalism ensures that negative cloud liquid water can + ! never occur. + ! + ! Rewrote DO loops and changed 1-D arrays into scalars in order + ! to optimization, esp. for Intel IFORT compiler. (bmy, 3/28/06) + !================================================================= + + ! Loop over tracers + DO M = 1, NTRACE + + ! Initialize + CMRH(:,:) = 0d0 + + ! Loop over levels and longitudes + DO K = LLPAR-1, LIMCNV+1, -1 + DO I = 1, IIPAR + + ! Initialize + ETAGDT = 0d0 + CMRC = 0d0 + BOTFLX = 0d0 + TOPFLX = 0d0 + EFAC1 = 0d0 + EFAC2 = 0d0 + EFAC3 = 0d0 + DCMR1 = 0d0 + DCMR2 = 0d0 + DCMR3 = 0d0 + + ! Only proceed for boxes with nonzero mass flux + IF ( ETA(I,J,K) > 0d0 ) THEN + ETAGDT = ETA(I,J,K) * GRAV * TDT * 0.01d0 ![hPa] + ELSE + CYCLE + ENDIF + + !============================================================== + ! Next, convectively modify passive constituents. For now, + ! when applying relaxation time scale to thermal fields after + ! entire column has undergone convective overturning, + ! constituents will be mixed using a "relaxed" value of the mass + ! flux determined above. Although this will be inconsistent + ! with the treatment of the thermal fields, it's computationally + ! much cheaper, no more-or-less justifiable, and consistent with + ! how the history tape mass fluxes would be used in an off-line + ! mode (i.e., using an off-line transport model) + !============================================================== + + ! If any of the reported values of the constituent is + ! negative in the three adjacent levels, nothing will + ! be done to the profile. Skip to next longitude. + IF ( ( Q(I,J,K+1,M) < 0d0 ) .OR. + & ( Q(I,J,K, M) < 0d0 ) .OR. + & ( Q(I,J,K-1,M) < 0d0 ) ) CYCLE + + ! Specify constituent interface values (linear interpolation) + CMRH(I,K ) = 0.5d0 *( Q(I,J,K-1,M) + Q(I,J,K ,M) ) + CMRH(I,K+1) = 0.5d0 *( Q(I,J,K ,M) + Q(I,J,K+1,M) ) + + ! In-cloud mixing ratio + CMRC = Q(I,J,K+1,M) + + ! Determine fluxes, flux divergence => changes due to convection. + ! Logic must be included to avoid producing negative values. + ! A bit messy since there are no a priori assumptions about profiles. + ! Tendency is modified (reduced) when pending disaster detected. + BOTFLX = ETAGDT * ( CMRC - CMRH(I,K+1) ) * ADJFAC + TOPFLX = BETA(I,J,K) * ETAGDT * ( CMRC - CMRH(I,K) ) * ADJFAC + DCMR1 = -BOTFLX * RPDEL(I,J,K+1) + EFAC1 = 1.0d0 + EFAC2 = 1.0d0 + EFAC3 = 1.0d0 + + ! K+1th level + IF ( Q(I,J,K+1,M) + DCMR1 < 0d0 ) THEN + EFAC1 = MAX( TINYALT, ABS( Q(I,J,K+1,M) / DCMR1 ) - EPS ) + ENDIF + + IF ( EFAC1 == TINYALT .or. EFAC1 > 1d0 ) EFAC1 = 0d0 + DCMR1 = -EFAC1 * BOTFLX * RPDEL(I,J,K+1) + DCMR2 = ( EFAC1 * BOTFLX - TOPFLX ) * RPDEL(I,J,K) + + ! Kth level + IF ( Q(I,J,K,M) + DCMR2 < 0d0 ) THEN + EFAC2 = MAX( TINYALT, ABS( Q(I,J,K,M) / DCMR2 ) - EPS ) + ENDIF + + IF ( EFAC2 == TINYALT .or. EFAC2 > 1d0 ) EFAC2 = 0d0 + DCMR2 = ( EFAC1 * BOTFLX - EFAC2 * TOPFLX ) * RPDEL(I,J,K) + DCMR3 = EFAC2 * TOPFLX * RPDEL(I,J,K-1) + + ! K-1th level + IF ( Q(I,J,K-1,M) + DCMR3 < 0d0 ) THEN + EFAC3 = MAX( TINYALT, ABS( Q(I,J,K-1,M) / DCMR3 ) - EPS ) + ENDIF + + IF ( EFAC3 == TINYALT .or. EFAC3 > 1d0 ) EFAC3 = 0d0 + EFAC3 = MIN( EFAC2, EFAC3 ) + DCMR2 = ( EFAC1 * BOTFLX - EFAC3 * TOPFLX ) * RPDEL(I,J,K) + DCMR3 = EFAC3 * TOPFLX * RPDEL(I,J,K-1) + + ! Save back into tracer array (levels K+1, K, K-1) + Q(I,J,K+1,M) = Q(I,J,K+1,M) + DCMR1 + Q(I,J,K ,M) = Q(I,J,K ,M) + DCMR2 + Q(I,J,K-1,M) = Q(I,J,K-1,M) + DCMR3 + ENDDO + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE HACK_CONV + +!------------------------------------------------------------------------------ + + SUBROUTINE ARCONVTRAN( J, DP, MU, MD, + & EU, MUG, MDG, DUG, + & EUG, EDG, DPG, DSUBCLD, + & JTG, JBG, IDEEP, LENGATH ) +! +!****************************************************************************** +! Subroutine ARCONVTRAN sets up the convective transport using archived mass +! fluxes from the ZHANG/MCFARLANE convection scheme. The setup involves: +! (1) Gather mass flux arrays. +! (2) Calc the mass fluxes that are determined by mass balance. +! (3) Determine top and bottom of convection. +! (pjr, dsa, swu, bmy, 6/26/03, 6/27/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : GEOS-CHEM latitude index [unitless] +! (2 ) DP (REAL*8 ) : Delta pressure between interfaces [Pa ] +! (3 ) MU (REAL*8 ) : Mass flux up [kg/m2/s ] +! (4 ) MD (REAL*8 ) : Mass flux down [kg/m2/s ] +! (5 ) EU (REAL*8 ) : Mass entraining from updraft [1/s ] +! +! Arguments as Output: +! ============================================================================ +! (6 ) MUG (REAL*8 ) : Gathered mu (lon-alt array) +! (7 ) MDG (REAL*8 ) : Gathered md (lon-alt array) +! (8 ) DUG (REAL*8 ) : Mass detraining from updraft (lon-alt array) +! (9 ) EUG (REAL*8 ) : Gathered eu (lon-alt array) +! (10) EDG (REAL*8 ) : Mass entraining from downdraft (lon-alt array) +! (11) DPG (REAL*8 ) : Gathered .01*dp (lon-alt array) +! (12) DSUBCLD (REAL*8 ) : Delta pressure from cloud base to sfc (lon-alt arr) +! (13) JTG (INTEGER) : Cloud top layer for columns undergoing conv. +! (14) JBG (INTEGER) : Cloud bottom layer for columns undergoing conv. +! (15) IDEEP (INTEGER) : Index of longitudes where deep conv. happens +! (16) LENGATH (INTEGER) : Length of gathered arrays +! +! NOTES: +! (1 ) Removed NSTEP from arg list; it's not used. Also zero arrays in order +! to prevent them from being filled with compiler junk for latitudes +! where no convection occurs at all. (bmy, 1/21/04) +! (2 ) Now dimension DP, MU, MD, EU as (IIPAR,JJPAR,LLPAR) to avoid seg fault +! error in OpenMP. Also now pass the GEOS-CHEM latitude index J via +! the argument list. (bmy, 12/13/05) +! (3 ) Now treat "negative detrainment" as entrainment, which will better +! conserve mixing ratio (swu, bmy, 6/27/06) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: J + REAL*8, INTENT(IN) :: DP(IIPAR,JJPAR,LLPAR) + REAL*8, INTENT(IN) :: MU(:,:,:) + REAL*8, INTENT(IN) :: MD(:,:,:) + REAL*8, INTENT(IN) :: EU(:,:,:) + REAL*8, INTENT(OUT) :: MUG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: MDG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: DUG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: EUG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: EDG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: DPG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: DSUBCLD(IIPAR) + INTEGER, INTENT(OUT) :: JTG(IIPAR) + INTEGER, INTENT(OUT) :: JBG(IIPAR) + INTEGER, INTENT(OUT) :: IDEEP(IIPAR) + INTEGER, INTENT(OUT) :: LENGATH + + ! Local variables + INTEGER :: I, K, LENPOS + INTEGER :: INDEX(IIPAR) + REAL*8 :: SUM(IIPAR) + REAL*8 :: RDPG(IIPAR,LLPAR) + + !================================================================= + ! ARCONVTRAN begins here! + !================================================================= + + ! Initialize arrays + DPG = 0d0 + DSUBCLD = 0d0 + DUG = 0d0 + EDG = 0d0 + EUG = 0d0 + JTG = LLPAR + JBG = 1 + MDG = 0d0 + MUG = 0d0 + RDPG = 0d0 + SUM = 0d0 + + !================================================================= + ! First test if convection exists in the lon band I=1,IIPAR + !================================================================= + + ! Sum all upward mass fluxes in the longitude band I=1,IIPAR + DO K = 1, LLPAR + DO I = 1, IIPAR + SUM(I) = SUM(I) + MU(I,J,K) + ENDDO + ENDDO + + ! IDEEP is the index of longitudes where SUM( up mass flux ) > 0 + ! LENGATH is the # of values where SUM( up mass flux ) > 0 + CALL WHENFGT( IIPAR, SUM, 1, 0d0, IDEEP, LENGATH ) + + ! Return if there is no convection the longitude band + IF ( LENGATH == 0 ) RETURN + + !================================================================= + ! Gather input mass fluxes in places where there is convection + !================================================================= + DO K = 1, LLPAR + DO I = 1, LENGATH + + ! Convert Pa->hPa + DPG(I,K) = 0.01d0 * DP(IDEEP(I),J,K) + RDPG(I,K) = 1.d0 / DPG(I,K) + + ! Convert Pa/s->hPa/s + MUG(I,K) = MU(IDEEP(I),J,K) * 0.01d0 + MDG(I,K) = MD(IDEEP(I),J,K) * 0.01d0 + + ! Convert Pa/s->1/s + EUG(I,K) = EU(IDEEP(I),J,K) * 0.01d0 * RDPG(I,K) + ENDDO + ENDDO + + !================================================================= + ! Calc DU and ED in places where there is convection + !================================================================= + DO K = 1, LLPAR-1 + DO I = 1, LENGATH + DUG(I,K) = EUG(I,K) - ( MUG(I,K) - MUG(I,K+1) ) * RDPG(I,K) + EDG(I,K) = ( MDG(I,K) - MDG(I,K+1) ) * RDPG(I,K) + ENDDO + ENDDO + + DO I = 1, LENGATH + DUG(I,LLPAR) = EUG(I,LLPAR) - MUG(I,LLPAR) * RDPG(I,LLPAR) + EDG(I,LLPAR) = 0.0d0 + ENDDO + + !================================================================= + ! Find top and bottom layers with updrafts. + !================================================================= + DO I = 1, LENGATH + JTG(I) = LLPAR + JBG(I) = 1 + ENDDO + + ! Loop over altitudes + DO K = 2, LLPAR + + ! Find places in the gathered array where MUG > 0 + CALL WHENFGT( LENGATH, MUG(:,K), 1, 0D0, INDEX, LENPOS ) + + ! Compute top & bottom layers + DO I = 1, LENPOS + JTG(INDEX(I)) = MIN( K-1, JTG(INDEX(I)) ) + JBG(INDEX(I)) = MAX( K, JBG(INDEX(I)) ) + ENDDO + ENDDO + + !================================================================= + ! Calc delta p between srfc and cloud base. + !================================================================= + DO I = 1, LENGATH + DSUBCLD(I) = DPG(I,LLPAR) + ENDDO + + DO K = LLPAR-1, 2, -1 + DO I = 1, LENGATH + IF ( JBG(I) <= K ) THEN + DSUBCLD(I) = DSUBCLD(I) + DPG(I,K) + ENDIF + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE ARCONVTRAN + +!------------------------------------------------------------------------------ + + SUBROUTINE CONVTRAN( J, NTRACE, Q, MU, MD, + & DU, EU, ED, DP, DSUBCLD, + & JT, MX, IDEEP, IL1G, IL2G, + & NSTEP, DELT, FRACIS, TCVV, INDEXSOL ) +! +!****************************************************************************** +! Subroutine CONVTRAN applies the convective transport of trace species +! (assuming moist mixing ratio) using the ZHANG/MCFARLANE convection scheme. +! (pjr, dsa, bmy, 6/26/03, 12/19/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : GEOS-CHEM latitude index [unitless] +! (2 ) NTRACE (INTEGER) : Number of tracers to transport [unitless] +! (3 ) Q (REAL*8 ) : Tracer conc. including moisture [v/v ] +! (4 ) MU (REAL*8 ) : Mass flux up [hPa/s ] +! (5 ) MD (REAL*8 ) : Mass flux down [hPa/s ] +! (6 ) DU (REAL*8 ) : Mass detraining from updraft [1/s ] +! (7 ) EU (REAL*8 ) : Mass entraining from updraft [1/s ] +! (8 ) ED (REAL*8 ) : Mass entraining from downdraft [1/s ] +! (9 ) DP (REAL*8 ) : Delta pressure between interfaces +! (10) DSUBCLD (REAL*8 ) : Delta pressure from cloud base to sfc +! (11) JT (INTEGER) : Index of cloud top for each column +! (12) MX (INTEGER) : Index of cloud top for each column +! (13) IDEEP (INTEGER) : Gathering array +! (14) IL1G (INTEGER) : Gathered min lon indices over which to operate +! (15) IL2G (INTEGER) : Gathered max lon indices over which to operate +! (16) NSTEP (INTEGER) : Time step index +! (17) DELT (REAL*8 ) : Time step +! (18) FRACIS (REAL*8 ) : Fraction of tracer that is insoluble +! (19) TCVV (REAL*8 ) : Ratio of air mass / tracer mass +! (20) INDEXSOL (INTEGER) : Index array of soluble tracer numbers +! +! Arguments as Output: +! ============================================================================ +! (3 ) Q (REAL*8 ) : Contains modified tracer mixing ratios [v/v] +! +! Important Local Variables: +! ============================================================================ +! (1 ) CABV (REAL*8 ) : Mixing ratio of constituent above +! (2 ) CBEL (REAL*8 ) : Mix ratio of constituent beloqw +! (3 ) CDIFR (REAL*8 ) : Normalized diff between cabv and cbel +! (4 ) CHAT (REAL*8 ) : Mix ratio in env at interfaces +! (5 ) CMIX (REAL*8 ) : Gathered tracer array +! (6 ) COND (REAL*8 ) : Mix ratio in downdraft at interfaces +! (7 ) CONU (REAL*8 ) : Mix ratio in updraft at interfaces +! (8 ) DCONDT (REAL*8 ) : Gathered tend array +! (9 ) FISG (REAL*8 ) : gathered insoluble fraction of tracer +! (10) KBM (INTEGER) : Highest altitude index of cloud base [unitless] +! (11) KTM (INTEGER) : Hightet altitude index of cloud top [unitless] +! (12) MBSTH (REAL*8 ) : Threshold for mass fluxes +! (13) SMALL (REAL*8 ) : A small number +! +! NOTES: +! (1 ) Added references to "diag_mod.f", "grid_mod.f", and "CMN_DIAG. +! Also added TCVV and INDEXSOL as arguments. Now only save LD38 +! levels of the ND38 diagnostic. Now place NTRACE before Q in the +! arg list. (swu, bmy, 1/21/04) +! (2 ) Now pass Hg2 that is wet scavenged to "ocean_mercury_mod.f" for +! computation of mercury fluxes (sas, bmy, 1/21/05) +! (3 ) Now dimension Q and FRACIS of size (IIPAR,JJPAR,LLPAR,NTRACE), in +! order to avoid seg faults with OpenMP. Also renamed GEOS-CHEM +! latitude index LATI_INDEX to J. Now references ITS_A_MERCURY_SIM +! from "tracer_mod.f". Now references IS_Hg2 from "tracerid_mod.f. +! Now do not call ADD_Hg2_WD if we are not using the dynamic online +! ocean model. Now references LDYNOCEAN from "logical_mod.f". +! (cdh, bmy, 2/27/06) +! (4 ) Split Hg2 IF statement into 2 IF statements so as to avoid seg faults. +! (bmy, 4/17/06) +! (5 ) Replace 1 with 1d0 in ND38 diagnostic (bmy, 5/24/06) +! (6 ) Updated for ND14 diagnostic (swu, bmy, 6/12/06) +! (7 ) Now treat "negative detrainment" as entrainment, which will better +! conserve mixing ratio (swu, bmy, 6/27/06) +! (8 ) Bug fix: avoid div by zero in formula for CHAT (bmy, 12/19/06) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : AD38, CONVFLUP + USE GRID_MOD, ONLY : GET_AREA_M2 + USE LOGICAL_MOD, ONLY : LDYNOCEAN + USE OCEAN_MERCURY_MOD, ONLY : ADD_Hg2_WD + USE TRACER_MOD, ONLY : ITS_A_MERCURY_SIM + USE TRACERID_MOD, ONLY : IS_Hg2 + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" ! ND38, LD38, ND14, LD14 + + ! Arguments + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: NTRACE + REAL*8, INTENT(INOUT) :: Q(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: MU(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: MD(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: DU(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: EU(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: ED(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: DP(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: DSUBCLD(IIPAR) + INTEGER, INTENT(IN) :: JT(IIPAR) + INTEGER, INTENT(IN) :: MX(IIPAR) + INTEGER, INTENT(IN) :: IDEEP(IIPAR) + INTEGER, INTENT(IN) :: IL1G + INTEGER, INTENT(IN) :: IL2G + INTEGER, INTENT(IN) :: NSTEP + REAL*8, INTENT(IN) :: DELT + REAL*8, INTENT(IN) :: FRACIS(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: TCVV(NTRACE) + INTEGER, INTENT(IN) :: INDEXSOL(NTRACE) + + ! Local variables + LOGICAL :: IS_Hg + INTEGER :: II, JJ, LL, NN + INTEGER :: I, K, KBM, KK + INTEGER :: KKP1, KM1, KP1, KTM + INTEGER :: M, ISTEP + REAL*8 :: CABV, CBEL, CDIFR, CD2 + REAL*8 :: DENOM, SMALL, MBSTH, MUPDUDP + REAL*8 :: MINC, MAXC, QN, FLUXIN + REAL*8 :: D_NSTEP, FLUXOUT, NETFLUX, AREA_M2 + REAL*8 :: WET_Hg2, PLUMEIN + REAL*8 :: CHAT(IIPAR,LLPAR) + REAL*8 :: COND(IIPAR,LLPAR) + REAL*8 :: CMIX(IIPAR,LLPAR) + REAL*8 :: FISG(IIPAR,LLPAR) + REAL*8 :: CONU(IIPAR,LLPAR) + REAL*8 :: DCONDT(IIPAR,LLPAR) + + !================================================================= + ! CONVTRAN begins here! + !================================================================= + + ! Is this a mercury simulation with dynamic ocean model? + IS_Hg = ( ITS_A_MERCURY_SIM() .and. LDYNOCEAN ) + + ! A small number + SMALL = 1.d-36 + + ! Threshold below which we treat the mass fluxes as zero (in mb/s) + MBSTH = 1.d-15 + + ! Convert NSTEP to REAL*8 for use below + D_NSTEP = NSTEP + + !================================================================= + ! Find the highest level top and bottom levels of convection + !================================================================= + KTM = LLPAR + KBM = LLPAR + DO I = IL1G, IL2G + KTM = MIN( KTM, JT(I) ) + KBM = MIN( KBM, MX(I) ) + ENDDO + + ! Loop ever each tracer + DO M = 1, NTRACE + + ! Gather up the tracer and set tend to zero + DO K = 1, LLPAR + DO I = IL1G, IL2G + CMIX(I,K) = Q(IDEEP(I),J,K,M) + IF ( CMIX(I,K) < 4.d0*SMALLEST ) CMIX(I,K) = 0D0 + FISG(I,K) = FRACIS(IDEEP(I),J,K,M) + ENDDO + ENDDO + + !============================================================== + ! From now on work only with gathered data + ! Interpolate environment tracer values to interfaces + !============================================================== + DO K = 1, LLPAR + KM1 = MAX( 1, K-1 ) + + DO I = IL1G, IL2G + MINC = MIN( CMIX(I,KM1), CMIX(I,K) ) + MAXC = MAX( CMIX(I,KM1), CMIX(I,K) ) + + IF ( MINC < 0d0 ) THEN + CDIFR = 0.d0 + ELSE + CDIFR = ABS( CMIX(I,K)-CMIX(I,KM1) ) / MAX(MAXC,SMALL) + ENDIF + + !------------------------------------------------------------ + ! The following 2 variables are actually NOT used + ! (swu, 12/17/03) + !DENOM = MAX( MAXC, SMALL ) + !CD2 = ABS( CMIX(I,K) - CMIX(I,KM1) ) / DENOM + !------------------------------------------------------------ + + IF ( CDIFR > 1.d-6 ) THEN + + ! If the two layers differ significantly. + ! use a geometric averaging procedure + CABV = MAX( CMIX(I,KM1), MAXC*TINYNUM, SMALLEST ) + CBEL = MAX( CMIX(I,K), MAXC*TINYNUM, SMALLEST ) + + ! If CABV-CBEL is zero then set CHAT=SMALLEST + ! so that we avoid div by zero (bmy, 12/19/06) + IF ( ABS( CABV - CBEL ) > 0d0 ) THEN + CHAT(I,K) = LOG( CABV / CBEL ) + & / ( CABV - CBEL ) + & * CABV * CBEL + ELSE + CHAT(I,K) = SMALLEST + ENDIF + + ELSE + + ! Small diff, so just arithmetic mean + CHAT(I,K) = 0.5d0 * ( CMIX(I,K) + CMIX(I,KM1) ) + ENDIF + + ! Provisional up and down draft values + CONU(I,K) = CHAT(I,K) + COND(I,K) = CHAT(I,K) + + ! Provisional tends + DCONDT(I,K) = 0.d0 + ENDDO + ENDDO + + !============================================================== + ! Do levels adjacent to top and bottom + !============================================================== + K = 2 + KM1 = 1 + KK = LLPAR + + DO I = IL1G, IL2G + MUPDUDP = MU(I,KK) + DU(I,KK) * DP(I,KK) + + ! Layer LLPAR (ground layer) CLOUD does not have updraft + ! entering, so assume tracer mixing ratio is same as + ! the environment (swu, bmy, 6/27/06) + IF ( MUPDUDP > MBSTH ) THEN + CONU(I,KK) = CMIX(I,KK) + ENDIF + + ! MD(I,2) is the downdraft entering from layer 2 from + ! layer 1 (model top layer); assumed to have the same + ! mixing ratio as the environment (swu, bmy, 6/27/06) + IF ( MD(I,K) < -MBSTH ) THEN + COND(I,K) = CMIX(I,KM1) + ENDIF + ENDDO + + !============================================================== + ! Updraft from bottom to top + !============================================================== + DO KK = LLPAR-1,1,-1 + KKP1 = MIN( LLPAR, KK+1 ) + + DO I = IL1G, IL2G + + ! Test for "negative detrainment" + IF ( DU(I,KK) < 0d0 ) THEN + + !----------------------------------------------------- + ! If negative DU (detrainment) happens, which implies + ! that the input metfields are not well constrained + ! and EU is inaccurate, we apply the correction by + ! treating the negative detrainment as extra + ! entrainment. (swu, bmy, 06/27/06) + !----------------------------------------------------- + + ! Air mass flux going into layer KK of the CLOUD + PLUMEIN = MU(I,KKP1) + ( EU(I,KK) * DP(I,KK) ) + & - ( DU(I,KK) * DP(I,KK) ) + + ! Compute concentration + IF ( PLUMEIN > MBSTH ) THEN + CONU(I,KK) = ( MU(I,KKP1)*CONU(I,KKP1)*FISG(I,KK) + & + EU(I,KK) *CMIX(I,KK) *DP(I,KK) + & - DU(I,KK) *CMIX(I,KK) *DP(I,KK) ) + & / PLUMEIN + ENDIF + + ELSE + + !----------------------------------------------------- + ! Normal condition; so just mix up EU and MU + !----------------------------------------------------- + + ! Air mass flux going into layer KK of the CLOUD + PLUMEIN = MU(I,KKP1) + ( EU(I,KK) * DP(I,KK) ) + + ! Compute concentration + IF ( PLUMEIN > MBSTH ) THEN + CONU(I,KK) = ( MU(I,KKP1)*CONU(I,KKP1)*FISG(I,KK) + & + EU(I,KK) *CMIX(I,KK) *DP(I,KK) ) + & / PLUMEIN + ENDIF + ENDIF + ENDDO + ENDDO + + !============================================================== + ! Downdraft from top to bottom + !============================================================== + DO K = 3, LLPAR + KM1 = MAX( 1, K-1 ) + + DO I = IL1G, IL2G + IF ( MD(I,K) < -MBSTH ) THEN + COND(I,K) = ( MD(I,KM1)*COND(I,KM1) + $ -ED(I,KM1)*CMIX(I,KM1) + $ *DP(I,KM1))/MD(I,K) + ENDIF + ENDDO + ENDDO + + DO K = KTM, LLPAR + KM1 = MAX( 1, K-1 ) + KP1 = MIN( LLPAR, K+1 ) + + DO I = IL1G, IL2G + + ! Version 3 limit fluxes outside convection to mass in + ! appropriate layer. These limiters are probably only safe + ! for positive definite quantitities. It assumes that mu + ! and md already satify a courant number limit of 1 + + FLUXIN = MU(I,KP1)* CONU(I,KP1) * FISG(I,K) + $ + (MU(I,K)+MD(I,K)) * CMIX(I,KM1) + $ - MD(I,K) * COND(I,K) + + FLUXOUT = MU(I,K) * CONU(I,K) + $ +(MU(I,KP1)+MD(I,KP1)) * CMIX(I,K) + $ - MD(I,KP1) * COND(I,KP1) + +!------------------------------------------------------------------------------ +! !!!!!!! backup: also works OK !!!!!!!!! (swu, 12/17/03) +! FLUXIN = MU(I,KP1)* CONU(I,KP1) +! $ + MU(I,K) * 0.5d0*(CHAT(I,K)+CMIX(I,KM1)) +! $ - MD(I,K) * COND(I,K) +! $ - MD(I,KP1)* 0.5d0*(CHAT(I,KP1)+CMIX(I,KP1)) +! +! FLUXOUT = MU(I,K) * CONU(I,K) +! $ + MU(I,KP1) * 0.5d0*(CHAT(I,KP1)+CMIX(I,K)) +! $ - MD(I,KP1) * COND(I,KP1) +! $ - MD(I,K) * 0.5d0*(CHAT(I,K)+CMIX(I,K)) +! +! FLUXIN = MU(I,KP1)* CONU(I,KP1) +! $ + MU(I,K) * CHAT(I,K) +! $ - MD(I,K) * COND(I,K) +! $ - MD(I,KP1)* CHAT(I,KP1) +! +! FLUXOUT = MU(I,K) * CONU(I,K) +! $ + MU(I,KP1) * CHAT(I,KP1) +! $ - MD(I,KP1) * COND(I,KP1) +! $ - MD(I,K) * CHAT(I,K) +!------------------------------------------------------------------------------ + + !======================================================== + ! ND14 Diagnostic: net upward flux of tracer [kg/s] in + ! cloud convection ("CV-FLX-$") (swu, bmy, 6/12/06) + ! + ! The ND14 diagnostic consists of 4 terms (T1..T4): + ! ------------------------------------------------------- + ! + ! T1: + Mass flux going upward from level K --> K-1 + ! (notice that the vertical levels are flipped) + ! + ! T2: - Mass flux going downward from level K-1 --> K + ! due to large scale subsidence + ! + ! T3: - Mass flux going downward from level K-1 --> K + ! associated with the downdraft plume + ! + ! T4: + Mass flux going up from level K --> K-1 due + ! to enviromental compensation for the downdraft. + ! + ! These terms are computed as follows: + ! ------------------------------------------------------- + ! + ! AIRFLUX: MU(I,K) * AREA_M2 * 100 / GRAV + ! = air mass (upward) flux in kg/s + ! + ! T1: +AIRFLUX * CONU(I,K) * TCVV(M) + ! = tracer mass upward flux [kg/s] + ! + ! T2: -AIRFLUX * CMIX(I,K-1) * TCVV(M) + ! = subsidence of tracer [kg/s] + ! + ! T3: -AIRFLUX * CMIX(I,K) * TCVV(M) + ! = downdraft flux of tracer [kg/s] + ! + ! T4: +AIRFLUX * COND(I,K-1) * TCVV(M) + ! = compensatory upward tracer flux [kg/s] + ! + ! Where: + ! + ! MU = Grid box surface area [hPa/s ] + ! AREA_M2 = Mixing ratio in updraft [m2 ] + ! CONU = Mixing ratio in updraft [v/v ] + ! COND = Mixing ratio in downdraft [v/v ] + ! CMIX = Gathered tracer array [v/v ] + ! GRAV = Acceleration due to gravity [m/s2 ] + ! TCVV = Ratio: MW air / MW tracer [unitless] + ! D_NSTEP = # of convection timesteps [unitless] + ! + ! Dividing by the number of time steps within each + ! convection step is simply accounting for the scale + ! factors (SCALECONV) in diag3.f. + !======================================================== + + ! Only save ND14 if it's turned on + IF ( ND14 > 0 ) THEN + + ! GEOS-Chem lon, lat, alt indices + II = IDEEP(I) + JJ = J + LL = LLPAR - K + 1 + + ! Grid box surface area [m] + AREA_M2 = GET_AREA_M2( JJ ) + + ! Only save from levels 1..LD14 + IF ( LL < LD14 ) THEN + + ! Net upward convective flux [kg/s] + CONVFLUP(II,JJ,LL,M) = CONVFLUP(II,JJ,LL,M) + + ! Terms T1 + T2 + & + MU(I,K) * ( AREA_M2 * 100d0 ) + & * ( CONU(I,K) - CMIX(I,KM1) ) + & / ( GRAV * TCVV(M) * D_NSTEP ) + + ! Terms T3 + T4 + & - MD(I,KM1) * ( AREA_M2 * 100d0 ) + & * ( CMIX(I,K) - COND(I,KM1) ) + & / ( GRAV * TCVV(M) * D_NSTEP ) + ENDIF + ENDIF + + !======================================================== + ! ND38 Diagnostic: loss of soluble tracer [kg/s] to + ! convective rainout ("WETDCV-$") (swu, bmy, 12/17/03) + ! + ! The loss of soluble tracer is given by (cf ND14): + ! + ! MU(I,K+1) * AREA_M2 * 100 / GRAV + ! = Air mass (upward) flux from level K+1 -> K + ! (Note that vertical levels are reversed) + ! + ! * CONU(I,K+1) * TCVV(M) * ( 1 - FISG(I,K ) + ! = Tracer mass upward from level K+1 -> K [kg/s] + ! + ! Where: + ! + ! CONU(I,K+1) = Tracer in mass flux from K+1 -> K + ! 1 - FISG(I,K) = Fraction of tracer lost in convective + ! updraft going from level K+1 -> K + !======================================================== + + ! Soluble tracer index + NN = INDEXSOL(M) + + ! Only save to ND38 if it's turned on, if there are soluble + ! tracers, and if we are below the LD38 level limit + IF ( ND38 > 0 .and. NN > 0 ) THEN + + ! GEOS-CHEM lon, lat, alt indices + II = IDEEP(I) + JJ = J + LL = LLPAR - K + 1 + + ! Only save up to LD38 vertical levels + IF ( LL <= LD38 ) THEN + + ! Grid box surface area [m2] + AREA_M2 = GET_AREA_M2( JJ ) + + ! Save loss in [kg/s] + AD38(II,JJ,LL,NN) = AD38(II,JJ,LL,NN) + + & MU(I,KP1) * AREA_M2 * 100d0 / + & GRAV * CONU(I,KP1) * (1d0-FISG(I,K)) / + & TCVV(M) / D_NSTEP + ENDIF + ENDIF + + !======================================================== + ! Pass the amount of Hg2 lost in wet scavenging [kg] + ! to "ocean_mercury_mod.f" w/ ADD_Hg2_WET. + ! + ! NOTE: DELT is already divided by NSTEP (as passed from + ! the calling program) so we don't have to divide by + ! it here, as is done above for ND38. (sas, bmy, 1/21/05) + ! + ! ALSO NOTE: Do not do this computation if we are not + ! using the online dynamic ocean (i.e. if LDYNOCEAN=F). + ! (bmy, 2/27/06) + !======================================================== + + ! If this is a Hg simulation ... + IF ( IS_Hg ) THEN + + ! ... and if this is one of the Hg2 tracers + IF ( IS_Hg2( M ) ) THEN + + ! GEOS-CHEM lon & lat indices + II = IDEEP(I) + JJ = J + + ! Grid box surface area [m2] + AREA_M2 = GET_AREA_M2( JJ ) + + ! Hg2 wet-scavenged out of the column [kg] + WET_Hg2 = MU(I,KP1) * AREA_M2 * 100d0 / + & GRAV * CONU(I,KP1) *(1d0-FISG(I,K))/ + & TCVV(M) * DELT + + ! Pass to "ocean_mercury_mod.f" + CALL ADD_Hg2_WD( II, J, M, WET_Hg2 ) + ENDIF + ENDIF + + NETFLUX = FLUXIN - FLUXOUT + + IF ( ABS(NETFLUX) < MAX(FLUXIN,FLUXOUT)*TINYNUM) THEN + NETFLUX = 0.D0 + ENDIF + + DCONDT(I,K) = NETFLUX / DP(I,K) + ENDDO + ENDDO + + DO K = KBM, LLPAR + KM1 = MAX( 1, K-1 ) + + DO I = IL1G, IL2G + + IF ( K == MX(I) ) THEN + + FLUXIN =(MU(I,K)+MD(I,K))* CMIX(I,KM1) + $ - MD(I,K)*COND(I,K) + + FLUXOUT = MU(I,K)*CONU(I,K) + +!---------------------------------------------------------------------------- +! !!!!!! BACK UP; also works well !!!!!!!! (swu, 12/17/03) +! FLUXIN = MU(I,K)*0.5d0*(CHAT(I,K)+CMIX(I,KM1)) +! $ - MD(I,K)*COND(I,K) +! +! FLUXOUT = MU(I,K)*CONU(I,K) +! $ - MD(I,K)*0.5d0*(CHAT(I,K)+CMIX(I,K)) +!---------------------------------------------------------------------------- + + NETFLUX = FLUXIN - FLUXOUT + + IF (ABS(NETFLUX).LT.MAX(FLUXIN,FLUXOUT)*TINYNUM) THEN + NETFLUX = 0.d0 + ENDIF + + DCONDT(I,K) = NETFLUX / DP(I,K) + + ELSE IF ( K > MX(I) ) THEN + + DCONDT(I,K) = 0.D0 + + ENDIF + + ENDDO + ENDDO + + !============================================================== + ! Update and scatter data back to full arrays + !============================================================== + DO K = 1, LLPAR + KP1 = MIN( LLPAR, K+1 ) + DO I = IL1G, IL2G + + QN = CMIX(I,K) + DCONDT(I,K) * DELT + + ! Do not make Q negative!!! (swu, 12/17/03) + IF ( QN < 0d0 ) THEN + QN = 0d0 + ENDIF + + Q(IDEEP(I),J,K,M) = QN + ENDDO + ENDDO + + ENDDO !M ; End of tracer loop + + ! Return to calling program + END SUBROUTINE CONVTRAN + +!----------------------------------------------------------------------------- + + SUBROUTINE WHENFGT( N, ARRAY, INC, TARGET, INDEX, NVAL ) +! +!****************************************************************************** +! Subroutine WHENFGT examines a 1-D vector and returns both an index array +! of elements and the number of elements which are greater than a certain +! target value. This routine came with the fvDAS convection code, we just +! cleaned it up and added comments. (swu, bmy, 1/21/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) N (INTEGER) : Number of elements in ARRAY +! (2 ) ARRAY (REAL*8 ) : 1-D vector to be examined +! (3 ) INC (INTEGER) : Increment for stepping thru ARRAY +! (4 ) TARGET (REAL*8 ) : Value that ARRAY will be tested against +! +! Arguments as Output: +! ============================================================================ +! (5 ) INDEX (INTEGER) : Array of places where ARRAY(I) > TARGET +! (6 ) NVAL (INTEGER) : Number of places where ARRAY(I) > TARGET +! +! NOTES: +! (1 ) Updated comments. Now use F90 style declarations. (bmy, 1/21/04) +!****************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: N, INC + REAL*8, INTENT(IN) :: ARRAY(N), TARGET + INTEGER, INTENT(OUT) :: INDEX(N), NVAL + + ! Local variables + INTEGER :: I, INA + + !================================================================= + ! WHENFGT begins here! + !================================================================= + + ! Initialize + INA = 1 + NVAL = 0 + INDEX(:) = 0 + + ! Loop thru the array + DO I = 1, N + + ! If the current element of ARRAY is greater than TARGET, + ! then increment NVAL and save the element # in INDEX + IF ( ARRAY(INA) > TARGET ) THEN + NVAL = NVAL + 1 + INDEX(NVAL) = I + ENDIF + + ! Skip ahead by INC elements + INA = INA + INC + ENDDO + + ! Return to calling program + END SUBROUTINE WHENFGT + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE FVDAS_CONVECT_MOD diff --git a/code/fyhoro.f b/code/fyhoro.f new file mode 100644 index 0000000..2315275 --- /dev/null +++ b/code/fyhoro.f @@ -0,0 +1,64 @@ +! $Id: fyhoro.f,v 1.1 2009/06/09 21:51:53 daven Exp $ +!------------------------------------------------------------------------------ +! Harvard University Atmospheric Chemistry Modeling Group ! +!------------------------------------------------------------------------------ +!BOP +! +! !FUNCTION: FYHORO +! +! !DESCRIPTION: \subsection*{Overview} +! Function FYHORO returns returns the branching ratio between +! HOC2H4O oxidation and dissociation: +! (1) HOC2H4 --O2--> HO2 + GLYC +! (2) HOC2H4 ------> HO2 + 2CH2O + +!\subsection*{References} +! \begin{enumerate} +! \item Orlando et al., 1998: \emph{Laboratory and theoretical study of the +! oxyradicals in the OH- and Cl-initiated oxidation of ethene}, +! \underline{J. Phys. Chem. A}, \textbf{102}, 8116-8123. +! \item Orlando et al., 2003: \emph{The atmospheric chemistry of alkoxy +! radicals}, \underline{Chem. Rev.}, \textbf{103}, 4657-4689. +! \end{enumerate} +! +!\\ +!\\ +! !INTERFACE: +! + REAL*8 FUNCTION FYHORO( ZDNUM, TT ) +! +! !USES: +! + IMPLICIT NONE +! +! !INPUT PARAMETERS: +! + ! Air density [molec/cm3 ] + REAL*8, INTENT(IN) :: ZDNUM + + ! Temperature [K ] + REAL*8, INTENT(IN) :: TT + +! +! !REVISION HISTORY: +! (1 ) Branching ratio calculation (tmf, 2/6/05). +!EOP +!------------------------------------------------------------------------------ +!BOC +! +! !LOCAL VARIABLES: +! + REAL*8 :: K1, K2, O2DNUM + + !================================================================= + ! FYHORO begins here! + !================================================================= + O2DNUM = ZDNUM * 0.21D0 + K1 = 6.0D-14 * EXP(-550.D0/TT) * O2DNUM + K2 = 9.5D+13 * EXP(-5988.D0/TT) + + FYHORO = K1 / (K1 + K2) + + ! Return to calling program + END FUNCTION FYHORO +!EOC diff --git a/code/fyrno3.f b/code/fyrno3.f new file mode 100644 index 0000000..5483c7f --- /dev/null +++ b/code/fyrno3.f @@ -0,0 +1,48 @@ +! $Id: fyrno3.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + REAL*8 FUNCTION FYRNO3( XCARBN, ZDNUM, TT ) +! +!****************************************************************************** +! Function FYRNO3 returns organic nitrate yields YN = RKA/(RKA+RKB) +! from RO2+NO reactions as a function of the number N of carbon atoms. +! (lwh, jyl, gmg, djj, bmy, 1/1/89, 6/26/03) +! +! Arguments as Input: +! ============================================================================ +! (1 ) XCARBN (REAL*8) : Number of C atoms in RO2 +! (2 ) ZDNUM (REAL*8) : Air density [molec/cm3 ] +! (3 ) TT (REAL*8) : Temperature [K ] +! +! NOTES: +! (1 ) Original code from Larry Horowitz, Jinyou Liang, Gerry Gardner, +! and Daniel Jacob circa 1989/1990. +! (2 ) Updated following Atkinson 1990. +! (3 ) Change yield from Isoprene Nitrate (ISN2) from 0.44% to 12%, +! according to Sprengnether et al., 2002. (amf, bmy, 1/7/02) +! (4 ) Eliminate obsolete code from 1/02 (bmy, 2/27/02) +! (5 ) Updated comment description of XCARBN (bmy, 6/26/03) +!****************************************************************************** +! + IMPLICIT NONE + + ! Arguments + REAL*8, INTENT(IN) :: XCARBN, ZDNUM, TT + + ! Local variables + REAL*8 :: YYYN, XXYN, AAA, RARB, ZZYN + REAL*8 :: XF, ALPHA, Y300, BETA, XMINF, XM0 + + ! Initialize static variables + DATA Y300,ALPHA,BETA,XM0,XMINF,XF/.826,1.94E-22,.97,0.,8.1,.411/ + + !================================================================= + ! FYRNO3 begins here! + !================================================================= + XXYN = ALPHA*EXP(BETA*XCARBN)*ZDNUM*((300./TT)**XM0) + YYYN = Y300*((300./TT)**XMINF) + AAA = LOG10(XXYN/YYYN) + ZZYN = 1./(1.+ AAA*AAA ) + RARB = (XXYN/(1.+ (XXYN/YYYN)))*(XF**ZZYN) + FYRNO3 = RARB/(1. + RARB) + + ! Return to calling program + END FUNCTION FYRNO3 diff --git a/code/gc_biomass_mod.f b/code/gc_biomass_mod.f new file mode 100644 index 0000000..c0d4a42 --- /dev/null +++ b/code/gc_biomass_mod.f @@ -0,0 +1,2249 @@ +! $Id: gc_biomass_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE GC_BIOMASS_MOD +! +!****************************************************************************** +! Module GC_BIOMASS_MOD contains arrays and routines to compute monthly +! biomass burning emissions for NOx, CO, ALK4, ACET, MEK, ALD2, PRPE, +! C3H8, CH2O, C2H6, CH4, and CH3I. (bmy, 9/11/00, 9/28/06) +! +! NOTE: These biomass emissions are based on Bryan Duncan (Duncan et al 2001) +! +! Module Variables: +! ============================================================================ +! (1 ) NBIOMAX : maximum # of biomass burning tracers +! (2 ) BIOTRCE : index array of biomass burning tracers +! (4 ) BIOMASS : array of biomass burning emissions [molec/cm3/s] +! (5 ) BIOMASS_SAVE : array of biomass burning emissions [molec/cm2/s] +! (6 ) TOMSAISCALE : array for TOMS aerosol index values +! +! Module Routines: +! ============================================================================ +! (1 ) GC_COMPUTE_BIOMASS : reads data, computes gas-phase biomass emissions +! (2 ) GC_READ_BIOMASS_BCOC : reads biomass emissions of BC & OC +! (3 ) GC_READ_BIOMASS_CO2 : reads biomass emissions of CO2 +! (4 ) GC_READ_BIOMASS_NH3 : reads biomass emissions of NH3 +! (5 ) GC_READ_BIOMASS_SO2 : reads biomass emissions of SO2 +! (6 ) READ_BIOMASS : reads gas-phase biomass burning data from disk +! (7 ) SCALE_BIOMASS_ACET : applies scale factors to ACET +! (8 ) SCALE_FUTURE : applies future scale factors to emissions +! (9 ) TOTAL_BIOMASS_TG : prints monthly emission totals in [Tg (C)] +! (10) ADJUST_TO_TOMSAI : wrapper for subroutine TOMSAI +! (11) TOMSAI : adjusts BB for int'annual var'bilty w/ TOMS data +! (12) CLEANUP_BIOMASS : deallocates BURNEMIS, BIOTRCE +! +! GEOS-CHEM modules referenced by "gc_biomass_mod.f" +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) diag_mod.f : Module w/ GEOS-CHEM diagnostic arrays +! (4 ) directory_mod.f : Module w/ GEOS-CHEM data & met field dirs +! (5 ) error_mod.f : Module w/ I/O error and NaN check routines +! (6 ) grid_mod.f : Module w/ horizontal grid information +! (7 ) logical_mod.f : Module w/ GEOS-CHEM logical switches +! (8 ) time_mod.f : Module w/ routines for computing time & date +! (9 ) transfer_mod.f : Module w/ routines to cast & resize arrays +! +! Decision Tree for Biomass Burning Emissions: +! ============================================================================ +! +! The cases below are described in "Interannual and Seasonal Variability of +! Biomass Burning Emissions Constrained by Remote-Sensed Observations" +! by Duncan et al. +! +! Case LBBSEA LTOMSAI (LBBSEA and LTOMSAI are flags in "input.geos") +! +! (1) T F Average monthly BB emissions +! ------------------------------------------------------ +! Read average monthly BB emissions. The mean monthly +! emissions from biomass burning were estimated from +! about four years of ATSR & AVHRR data. See +! Sections 3.1 and 4 of Duncan et al. +! +! +! (2) T T Interannual varying monthly BB emissions +! ------------------------------------------------------ +! (a) Read annual BB emissions (i.e., inventory of +! Jennifer Logan & Rose Yevich) and impose +! time-dependency by scaling to TOMS AI data for +! those regions where TOMS AI was used. This option +! allows the user to account for the interannual +! variability of BB. +! +! (b) Read average monthly BB emissions for Africa and +! areas where TOMS AI is not used. +! +! See Sections 3.2 and 5 of Duncan et al. +! +! +! (3) F T Same as Case 2, except with higher spatial resolution +! ------------------------------------------------------ +! (a) Same as Case 2 prior to 8/1/1996. +! +! (b) After 8/1/1996, read monthly BB emissions from +! disk. The emissions are time-dependent as in Case 2 +! and account for interannual variation. The spatial +! resolution of emissions is greater than in Case 2 +! due to ATSR fire-counts. +! +! See Section 3.3 of Duncan et al. +! +! +! (4) F F Same as Case 3b +! ------------------------------------------------------ +! Read interannual variability BB emissions from disk. +! +! See Section 3.3 of Duncan et al. +! +! NOTES: +! (1 ) Now treat BURNEMIS as a true global array of size (IGLOB,JGLOB); +! use offsets IREF = I + I0 and JREF = J + J0 to index it (bmy, 9/12/00) +! (2 ) Added subroutines READ_BIOMASS and TOMSAI (bmy, 9/25/00) +! (3 ) Bug fixes in routines BIOBURN and READ_BIOMASS. Added new decision +! tree in BIOBURN. Added routine ADJUST_TO_TOMSAI. (bmy, 10/12/00) +! (4 ) Updated boundaries of geographic regions in TOMSAI (bnd, bmy, 10/16/00) +! (5 ) Bug fix for CTM_LAT in TOMSAI (bnd, bmy, 11/28/00) +! (6 ) Removed obsolete code in BIOBURN (bmy, 12/21/00) +! (7 ) Now account for extra production of CO from VOC's for Tagged CO +! and CO-OH simulations (bmy, 1/3/01) +! (8 ) Now use routines from "error_mod.f" for trapping NaN's (bmy, 3/8/01) +! (9 ) Moved NBIOMAX here from "CMN_SIZE" (bmy, 3/16/01) +! (10) Now dimension BIOTRCE and to be of size NBIOMAX, instead of having +! them be allocatable. Also change NBIOMAX from 9 to 10, since we +! will be adding ALK4 soon. Elminate LDOBIOEMIT, since that is now +! confusing and unnecessary. (bmy, 4/17/01) +! (11) Bug fix: For option 2 in the decision tree above, scale annual +! BB emissions to the TOMS aerosol index instead of seasonal. This +! will give the correct results. Updated routines ADJUST_TO_TOMSAI +! and TOMSAI accordingly. (bnd, bmy, 6/6/01) +! (12) PRPE is already in molec C, so don't multiply it by 3 as we have +! been doing before. (bmy, 6/29/01) +! (13) Update comments for BB decision tree (bnd, bmy, 7/2/01) +! (14) Now use correct scale factors for CO (bnd, bmy, 8/21/01) +! (15) Bug fix: Make sure to read data from the biomass burning punch file +! with the correct index for runs that have less than NBIOMAX species +! turned on. (bmy, 8/24/01) +! (16) Add new routine: SCALE_BIOMASS_ACET. Also updated comments. +! (bmy, 9/6/01) +! (17) Removed obsolete code (bmy, 9/18/01) +! (18) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (19) Removed duplicate variable definitions. Also now can specify +! biomass burning subdirectory via a variable in BIOBURN (bmy, 11/15/01) +! (20) Now point to new biomass burning files from 10/2001 (bmy, 12/4/01) +! (21) Updated comments (1/15/02) +! (22) Fixed incorrect value for IPICK in "adjust_to_tomsai" (bmy, 2/27/02) +! (23) Bug fix: convert from [molec/cm2/s] to [molec/cm3/s] every timestep. +! Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Updated comments. Renamed INIT_BURNEMIS +! to INIT_BIOMASS. BIOMASS is now an allocatable module array +! instead of a SAVEd array within routine BIOBURN. (bmy, 5/30/02) +! (24) Now reference BXHEIGHT from "dao_mod.f". Now references "error_mod.f". +! Also deleted obsolete code from various routines. Now references +! "tracerid_mod.f". (bmy, 11/6/02) +! (25) Now references "grid_mod.f" and the new "time_mod.f". Also suppresses +! printing when calling routine READ_BPCH2. Bug fix in routine TOMSAI. +! Fixed bug in BIOBURN when passing arrays BIOMASS_SEA and BIOMASS_ANN +! to routine READ_BIOMASS. (bmy, 4/28/03) +! (26) Now references "directory_mod.f" & "logical_mod.f" (bmy, 7/20/04) +! (27) Bug fix in BIOBURN for TAU w/ interannual emissions (bmy, 3/18/05) +! (28) Now can read data for both GEOS and GCAP grids (bmy, 3/18/05) +! (29) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (30) Renamed to "gc_biomass_mod.f", so that we can use either these +! "default" biomass emissions or GFED2 biomass emissions. Cleaned up +! a lot of obsolete stuff. (bmy, 4/5/06) +! (31) Modified for IPCC future emissions scale factors. Added private +! routine SCALE_FUTURE. (swu, bmy, 5/30/06) +! (32) Added routines for reading BC, OC, SO2, NH3, CO2 biomass emissions. +! (bmy, 9/28/06) +! (33) Add 9 gaseous biomass burning emissions using emission ratios +! w.r.t. CO. Details in Fu et al. [2008] (tmf, 1/7/09) +! (34) CO scaling for VOC production is transfered to biomass_mod.f. +! (jaf, 2/6/09) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "gc_biomass_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except for these routines + PUBLIC :: CLEANUP_GC_BIOMASS + PUBLIC :: GC_COMPUTE_BIOMASS + PUBLIC :: GC_READ_BIOMASS_BCOC + PUBLIC :: GC_READ_BIOMASS_CO2 + PUBLIC :: GC_READ_BIOMASS_NH3 + PUBLIC :: GC_READ_BIOMASS_SO2 + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Parameters + ! NOTE: This is an internal declaration for the + ! gas-phase species only (bmy, 9/28/06) + INTEGER, PARAMETER :: NBIOMAX = 19 + + ! TOMS AI interannual variability in biomass burning emissions + INTEGER, PARAMETER :: NAIREGIONS = 8 + INTEGER, PARAMETER :: NAIYEARS = 21 + INTEGER, PARAMETER :: NMONTHSAI = NAIYEARS * 12 + + ! Arrays + REAL*8, ALLOCATABLE :: TOMSAISCALE(:,:,:) + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE GC_COMPUTE_BIOMASS( YEAR, MONTH, BIOMASS ) +! +!****************************************************************************** +! Subroutine GC_COMPUTE_BIOMASS computes the biomass burning emissions for +! several species for the given month (jal, acs, rvm, bmy, 9/11/00, 4/5/06) +! +! NOTES: +! (1 ) Incorporated original functionality of "bioburn.f" and "biomass.h" +! in F90 module "bioburn_mod.f". Biomass burning arrays now are only +! allocated if biomass burning is turned on. (bmy, 9/11/00) +! (2 ) Split off calls to READ_BPCH2 into separate subroutine READ_BIOMASS +! for clarity. Also now use logical switches LBBSEA and LTOMSAI to +! switch between seasonal or interannual variability. (bmy, 9/28/00) +! (3 ) Bug fixes: (a) Acetone is BIOMASS(5,:,:), not BIOMASS(9,:,:). +! (b) Make sure to read in all biomass burning tracers from the +! binary punch file, regardless of which tracers are actually emitted. +! (bmy, 10/11/00) +! (4 ) Added new decision tree (see comments above) (bmy, 10/12/00) +! (5 ) Removed obsolete code from 10/12/00 (bmy, 12/21/00) +! (6 ) Enhance CO from biomass burning by 10% for Tagged CO and CO-OH +! simulations, to account for extra production of CO from VOC's. +! (bnd, bmy, 1/3/01) +! (7 ) Now use interface IT_IS_NAN (from "error_mod.f") to trap NaN's. +! This will work on DEC/Compaq and SGI platforms. (bmy, 3/8/01) +! (8 ) Now call INIT_BURNEMIS on the very first call to BIOBURN. Also +! read biomass burning species w/o using LDOBIOEMIT, which is +! now unnecessary. Call SCALE_BIOMASS_CO to multiply CO biomass +! burning emissions by jal/bnd scale factors, to account for +! oxidation of VOC's not carried (bmy, 4/17/01) +! (9 ) Now read new biomass burning files (Apr 2001) from the +! "biomass_200104/" subdirectory of DATA_DIR. (bmy, 4/18/01) +! (10) Added BIOMASS_SEA and BIOMASS_ANN arrays for the scaling for Case #2 +! in the decision tree above. This will scale the annual BB emissions +! using TOMSAI in selected regions, but use the seasonal emissions +! elsewhere. (bnd, bmy, 6/6/01) +! (11) Now call SCALE_BIOMASS_ACET in order to enhance biomass burning ACET +! by 77%, to match results from Jacob et al 2001. (bdf, bmy, 9/4/01) +! (12) BURNEMIS, BIOMASS, BIOMASS_SEA, and BIOMASS_ANN are now dimensioned +! (NBIOTRCE,IIPAR,JJPAR). BURNEMIS(:,IREF,JREF) is now +! BURNEMIS(:,I,J) and BIOMASS(:,IREF,JREF) is now BIOMASS(:,I,J). +! Remove IREF, JREF, IOFF, JOFF -- these are obsolete. (bmy, 9/28/01) +! (13) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (14) Removed duplicate definition of BOXVL. Also added BIOMASS_DIR +! string to specify the sub-directory of DATA_DIR where biomass +! emissions are kept. (bmy, 11/15/01) +! (15) Now set BIOMASS_MOD = 'biomass_200110/' as the default. This points +! to newer biomass burning emissions from Randall Martin (bmy, 11/30/01 +! (16) Now set BIOMASS_DIR = 'biomass_200010/' in order to take advantage of +! new biomass burning files from Randall Martin (w/ firecounts thru +! 2000). +! (17) Bug fix: convert from [molec/cm2/s] to [molec/cm3/s] every timestep. +! Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and +! MODULE ROUTINES sections. Now call INIT_BIOMASS instead of +! INIT_BURNEMIS. Added parallel DO-loops for unit conversion. Now +! archive diagnostics w/ in the parallel loop section. (bmy, 5/31/02) +! (18) Now reference BXHEIGHT from "dao_mod.f". Also call GEOS_CHEM_STOP +! to free memory when stopping with an error. Now call GET_TAU0 with +! 3 arguments instead of 2. Now references IDTNOX, IDBNOX, etc. from +! "tracerid_mod.f". (bmy, 11/6/02) +! (19) Now remove IMONTH from the arg list. Now use functions GET_MONTH, +! GET_TAU, GET_YEAR, and ITS_A_LEAPYEAR from "time_mod.f". +! (bmy, 2/10/03) +! (20) Bug fix: make sure only to pass BIOMASS_SEA(1:NBIOTRCE,:,:) and +! BIOMASS_ANN(1:NBIOTRCE,:,:) to READ_BIOMASS. (bnd, bmy, 5/16/03) +! (21) Added fancy output (bmy, 4/26/04) +! (22) Removed reference to CMN, it's obsolete. Now reference DATA_DIR from +! "directory_mod.f". Now references LBBSEA and LTOMSAI from +! "logical_mod.f". (bmy, 7/20/04) +! (23) Bug fix: if using interannual biomass emissions then get the TAU value +! for the first of the current month & year. This will make sure that +! runs which start mid-month will access the biomass data correctly. +! (bmy, 3/18/05) +! (24) Now can read data from both GEOS and GCAP grids (bmy, 8/16/05) +! (25) Renamed to GC_COMPUTE_BIOMASS. Now takes YEAR, MONTH, BIOMASS +! arguments. (bmy, 4/5/06) +! (26) Add 9 biomass burning species (ccc, 1/7/09) +!****************************************************************************** +! + ! 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 + USE LOGICAL_MOD, ONLY : LBBSEA, LTOMSAI + USE LOGICAL_MOD, ONLY : LFUTURE + USE TIME_MOD, ONLY : ITS_A_LEAPYEAR, GET_TAU + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + REAL*8, INTENT(OUT) :: BIOMASS(IIPAR,JJPAR,NBIOMAX) + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + INTEGER :: I, J, N + INTEGER, SAVE :: MONTHSAVE = -99 + REAL*8 :: TIME, XTAU + REAL*8 :: BIOMASS_SEA(IIPAR,JJPAR,NBIOMAX) + REAL*8 :: BIOMASS_ANN(IIPAR,JJPAR,NBIOMAX) + CHARACTER(LEN=4 ) :: CYEAR + CHARACTER(LEN=255) :: FILENAME + CHARACTER(LEN=255) :: BIOMASS_DIR + + ! MONTHDATES = number of days per month + INTEGER :: MONTHDATES(12) = (/ 31, 28, 31, 30, + & 31, 30, 31, 31, + & 30, 31, 30, 31 /) + + ! External functions + REAL*8, EXTERNAL :: BOXVL + + !================================================================= + ! B i o m a s s B u r n i n g B e g i n s H e r e !! + ! + ! GEOS-CHEM has the following biomass burning species: + ! + ! Species Index CTM Tracer # Units as read from file + ! --------------------------------------------------------- + ! NOX 1 1 [molec NOx /cm2/month] + ! CO 2 4 [molec CO /cm2/month] + ! ALK4 3 5 [molec C /cm2/month] + ! ACET 4 9 [molec ACET/cm2/month] + ! MEK 5 10 [molec C /cm2/month] + ! ALD2 6 11 [molec C /cm2/month] + ! PRPE 7 18 [molec C /cm2/month] + ! C3H8 8 19 [molec C3H8/cm2/month] + ! CH2O 9 20 [molec CH2O/cm2/month] + ! C2H6 10 21 [molec C2H6/cm2/month] + ! GLYX 15 55 [molec GLYX/cm2/month] + ! MGLY 16 56 [molec MGLY/cm2/month] + ! BENZ 17 57 [molec C /cm2/month] + ! TOLU 18 58 [molec C /cm2/month] + ! XYLE 19 59 [molec C /cm2/month] + ! C2H4 20 63 [molec C /cm2/month] + ! C2H2 21 64 [molec C /cm2/month] + ! GLYC 22 66 [molec GLYC/cm2/month] + ! HAC 23 67 [molec HAC /cm2/month] + ! + ! Subsequent unit conversion is done on the following species: + ! [molec ACET/cm2/month] --> [molec C/cm2/month] + ! [molec C3H8/cm2/month] --> [molec C/cm2/month] + ! [molec C2H6/cm2/month] --> [molec C/cm2/month] + ! + ! There are NBIOMAX=19 biomass burning species in this module. + ! + ! Biomass burning emissions are first read from disk into the + ! BIOMASS array. After unit conversion to [molec/cm3/s] ( or + ! [atoms C/cm3/s] for hydrocarbons), the emissions are stored + ! in BIOMASS and passed back to the calling program. + ! + ! Biomass burning data is monthly, so we only have to read + ! emissions from disk once each month. + !================================================================= + + ! Do the following on the first day of a new month... + IF ( MONTH /= MONTHSAVE ) THEN + + ! Save the current month + MONTHSAVE = MONTH + + ! Set MONTHDATES(2) = 29 for leapyears, = 28 otherwise (bmy, 4/19/99) + IF ( MONTH == 2 ) THEN + IF( ITS_A_LEAPYEAR() ) THEN + MONTHDATES(2) = 29 + ELSE + MONTHDATES(2) = 28 + ENDIF + ENDIF + + ! TIME = conversion from [molec/cm2/month] to [molec/cm2/s] + TIME = ( DBLE( MONTHDATES( MONTH ) ) * 86400d0 ) + + ! Create a string for the 4-digit year + WRITE( CYEAR, '(i4)' ) YEAR + + ! Fancy output... + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a,/)' ) + & 'B I O M A S S B U R N I N G E M I S S I O N S' + + !============================================================== + ! Set BIOMASS_DIR to the subdirectory where the current + ! biomass burning files are stored + !============================================================== + !BIOMASS_DIR = 'biomass_200104/' + BIOMASS_DIR = 'biomass_200110/' + + !============================================================== + ! Case 1: LBBSEA = T and LTOMSAI = F + ! + ! Read seasonal biomass burning emissions from disk. + !============================================================== + IF ( LBBSEA .and. ( .not. LTOMSAI ) ) THEN + + ! Get TAU0 value to index the punch file -- use generic year 1985 + XTAU = GET_TAU0( MONTH, 1, 1985 ) + + ! Filename for seasonal biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // TRIM( BIOMASS_DIR ) // + & 'bioburn.seasonal.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Read the seasonal biomass burning emissions from disk + CALL READ_BIOMASS( FILENAME, XTAU, BIOMASS ) + + !============================================================== + ! Case 2: LBBSEA = T and LTOMSAI = T + ! + ! + ! Read annual biomass burning emissions from disk, but use + ! TOMS aerosol index data to impose interannual variability. + ! Read in seasonal biomass buring emissions for Africa and + ! regions outside the regions adjusted by TOMS AI. + !============================================================== + ELSE IF ( LBBSEA .and. LTOMSAI ) THEN + + ! Get TAU0 value to index the punch file -- use generic year 1985 + XTAU = GET_TAU0( MONTH, 1, 1985 ) + + ! Filename for seasonal biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // TRIM( BIOMASS_DIR ) // + & 'bioburn.seasonal.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Read the seasonal biomass burning emissions into BIOMASS_SEA + CALL READ_BIOMASS( FILENAME, XTAU, BIOMASS_SEA ) + + ! Get TAU0 value to index the punch file -- use generic year 1985 + XTAU = GET_TAU0( 1, 1, 1985 ) + + ! Filename for annual biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // TRIM( BIOMASS_DIR ) // + & 'bioburn.annual.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Read the annual biomass burning emissions into BIOMASS_ANN + CALL READ_BIOMASS( FILENAME, XTAU, BIOMASS_ANN ) + + ! Adjust the annual biomass burning to the TOMS Aerosol + ! Index data where necessary. Otherwise, overwrite + ! with seasonal data. Save result in the BIOMASS array. + BIOMASS = 0d0 + CALL ADJUST_TO_TOMSAI( BIOMASS_ANN, BIOMASS_SEA, BIOMASS ) + + !============================================================== + ! Case 3: LBBSEA = F and LTOMSAI = T + ! + ! (1) Prior to 8/1/1996, read seasonal biomass burning + ! emissions, and use TOMS AI data to impose int. var. + ! + ! (2) On or after 8/1/1996, read the interannual variability + ! biomass burning emissions (computed by Randall Martin: + ! rvm@io.harvard.edu) directly from disk. + !============================================================== + ELSE IF ( ( .not. LBBSEA ) .and. LTOMSAI ) THEN + + ! 8/1/1996 is TAU value 101520 + IF ( GET_TAU() < 101520d0 ) THEN + + ! Get TAU0 value to index the punch file -- + ! use generic year 1985 + XTAU = GET_TAU0( MONTH, 1, 1985 ) + + ! Filename for seasonal biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // TRIM( BIOMASS_DIR ) // + & 'bioburn.seasonal.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Read the seasonal biomass burning emissions into BIOMASS_SEA + CALL READ_BIOMASS( FILENAME, XTAU, BIOMASS_SEA ) + + ! Get TAU0 value to index the punch file -- + ! use generic year 1985 + XTAU = GET_TAU0( 1, 1, 1985 ) + + ! Filename for annual biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // TRIM( BIOMASS_DIR ) // + & 'bioburn.annual.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() + + ! Read the annual biomass burning emissions from disk + CALL READ_BIOMASS( FILENAME, XTAU, BIOMASS_ANN ) + + ! Adjust the annual biomass burning to the TOMS Aerosol + ! Index data where necessary. Otherwise, overwrite + ! with seasonal data. Save result in the BIOMASS array. + BIOMASS = 0d0 + CALL ADJUST_TO_TOMSAI( BIOMASS_ANN, BIOMASS_SEA, BIOMASS) + + ELSE + + ! Use actual TAU0 value to index punch file + XTAU = GET_TAU() + + ! Filename for interannual variability biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // + & TRIM( BIOMASS_DIR ) // + & 'bioburn.interannual.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() // + & '.' // CYEAR + + ! Read interannual variability biomass burning + CALL READ_BIOMASS( FILENAME, XTAU, BIOMASS ) + + ENDIF + + !============================================================== + ! Case 4: LBBSEA = F and LTOMSAI = F + ! + ! Read the interannual variability biomass burning emissions + ! (computed by Randall Martin: rvm@io.harvard.edu) from disk. + !============================================================== + ELSE IF ( ( .not. LBBSEA ) .and. ( .not. LTOMSAI ) ) THEN + + ! TAU0 value for 0 GMT on the first day of this month & year + XTAU = GET_TAU0( MONTH, 1, YEAR ) + + ! Filename for interannual variability biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // + & TRIM( BIOMASS_DIR ) // + & 'bioburn.interannual.' // GET_NAME_EXT_2D() // + & '.' // GET_RES_EXT() // + & '.' // CYEAR + + ! Read interannual variability biomass burning + CALL READ_BIOMASS( FILENAME, XTAU, BIOMASS ) + + ENDIF + + ! Convert to [molec/cm2/s] or [atoms C/cm2/s] + BIOMASS = BIOMASS / TIME + + ! Fancy output... + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + ENDIF + + ! Return to calling program + END SUBROUTINE GC_COMPUTE_BIOMASS + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_BIOMASS( FILENAME, TAU0, BIOMASS ) +! +!****************************************************************************** +! Subroutine READ_BIOMASS reads the biomass burning emissions from disk +! in units of [molec/cm2/month] (or [atoms C/cm2/month] for hydrocarbons). +! (bmy, 9/25/00, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FILENAME (CHARACTER) : Name of the biomass burning file to read +! (2 ) TAU0 (REAL*8 ) : TAU0 value used to index the BB data +! +! Arguments as Output: +! ============================================================================ +! (3 ) BIOMASS (REAL*8 ) : Biomass burning emissions (for NBIOMAX tracers) +! +! NOTES: +! (1 ) Split off from "bioburn.f" to reduce code duplication (bmy, 9/25/00) +! (2 ) Now read in all biomass burning tracers from the punch file, +! regardless of whether or not they are actually emitted. +! (bmy, 10/11/00) +! (3 ) Now only read in the NBIOTRCE biomass burning tracers that +! are actually emitted (bmy, 4/17/01) +! (4 ) PRPE is already in molec C, so don't multiply it by 3 as we have +! been doing before. (bmy, 6/29/01) +! (5 ) Bug fix: make sure that tracers get read from the biomass burning +! file w/ the right index number. This was a bug for runs that had +! less than NBIOMAX species specified. (bmy, 8/24/01) +! (6 ) Removed obsolete code from 8/24/01 (bmy, 9/18/01) +! (7 ) BIOMASS is now of size (NBIOMAX,IIPAR,JJPAR). Now call TRANSFER_2D +! to copy data from REAL*4 to REAL*8 and also to resize from +! (IGLOB,JGLOB) to (IIPAR,JJPAR). (bmy, 9/28/01) +! (8 ) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (9 ) BIOMASS needs to be of size (NBIOTRCE,IIPAR,JJPAR) (bmy, 5/31/02) +! (10) Now references IDTNOX, etc. from "tracerid_mod.f" (bmy, 11/6/02) +! (11) Now call READ_BPCH2 with QUIET=.TRUE. flag to suppress extra info +! from being printed (bmy, 3/14/03) +! (12) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (13) Now make BIOMASS array argument (I,J,N) ordered instead of (N,I,J). +! Also now read all NBIOMAX species. (bmy, 4/5/06) +! (14) Now refrerences LFUTURE from "logical_mod.f". Also now calls private +! routine SCALE_FUTURE to compute the future biomass emissions. +! (swu, bmy, 5/30/06) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : READ_BPCH2 + USE LOGICAL_MOD, ONLY : LFUTURE + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + CHARACTER(LEN=*), INTENT(IN) :: FILENAME + REAL*8, INTENT(IN) :: TAU0 + REAL*8, INTENT(OUT) :: BIOMASS(IIPAR,JJPAR,NBIOMAX) + + ! Local variables + INTEGER :: N + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + + ! Add storage of CO emissions to calculate emissions + ! of the 9 new species (tmf, 12/18/06) + REAL*8 :: COEMIS(IIPAR, JJPAR) ! CO emissions before scaling + REAL*8 :: TRCEMIS(IIPAR, JJPAR) ! Tracer emissions scaled from CO + + !================================================================= + ! READ_BIOMASS begins here! + !================================================================= + + ! Echo info + WRITE( 6, 110 ) TRIM( FILENAME ) + 110 FORMAT( 'GC_COMPUTE_BIOMASS: Reading ', a ) + + ! Initialize the BIOMASS array + BIOMASS = 0d0 + + ! Loop over only the emitted biomass tracers + DO N = 1, NBIOMAX + + ! Do scaling if necessary and print totals in Tg + IF ( N == 1 ) THEN + + !---------- + ! NOx + !---------- + + ! NOx is stored in the biomass file as tracer #1 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 1, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! Compute future NOx emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'NOxbb', BIOMASS(:,:,N) ) + ENDIF + + ! NOX -- print totals in [Tg/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 14d-3, 'NOx' ) + + ELSE IF ( N == 2 ) THEN + + !---------- + ! CO + !---------- + + ! CO is stored in the biomass file as tracer #4 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 4, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! Store CO emissions before scaling + ! for new gaseous emissions (tmf, 1/7/09) + CALL TRANSFER_2D( ARRAY(:,:,1), COEMIS(:,:) ) + +!------------------------------------------------------------------ +! Prior to 2/25/09, ccc +! ! CO -- scale to account for oxidation of extra VOC's +! CALL SCALE_BIOMASS_CO( BIOMASS(:,:,N) ) +!------------------------------------------------------------------ + + ! Compute future NOx emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'CObb', BIOMASS(:,:,N) ) + ENDIF + + ! Print totals in [Tg/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 28d-3, 'CO' ) + + ELSE IF ( N == 3 ) THEN + + !---------- + ! ALK4 + !---------- + + ! ALK4 is stored in the biomass file as tracer #5 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 5, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! Compute future ALK4 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! ALK4 -- print totals in [Tg C/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'ALK4' ) + + ELSE IF ( N == 4 ) THEN + + !---------- + ! ACET + !---------- + + ! ACET is stored in the biomass file as tracer #9 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 9, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! ACET -- Convert from [molec/cm2/month] to [molec C/cm2/month] + BIOMASS(:,:,N) = BIOMASS(:,:,N) * 3d0 + + ! Scale to yearly value for biogenic acetone (bdf, bmy, 7/23/01) + CALL SCALE_BIOMASS_ACET( BIOMASS(:,:,N) ) + + ! Compute future ACET emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! Print totals in [Tg C/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'ACET' ) + + ELSE IF ( N == 5 ) THEN + + !---------- + ! MEK + !---------- + + ! MEK is stored in the biomass file as tracer #10 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 10, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! Compute future MEK emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! MEK -- print totals in [Tg C/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'MEK' ) + + ELSE IF ( N == 6 ) THEN + + !---------- + ! ALD2 + !---------- + + ! ALD2 is stored in the biomass file as tracer #11 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 11, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! Compute future ALD2 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! ALD2 -- print totals in [Tg C/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'ALD2' ) + + ELSE IF ( N == 7 ) THEN + + !---------- + ! PRPE + !---------- + + ! PRPE is stored in the biomass file as tracer #18 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 18, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! Compute future PRPE emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! PRPE -- convert from [molec/cm2/month] to [molec C/cm2/month] + ! Print totals in [Tg C/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'PRPE' ) + + ELSE IF ( N == 8 ) THEN + + !---------- + ! C3H8 + !---------- + + ! C3H8 is stored in the biomass file as tracer #19 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 19, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! C3H8 -- convert from [molec/cm2/month] to [molec C/cm2/month] + BIOMASS(:,:,N) = BIOMASS(:,:,N) * 3d0 + + ! Compute future C3H8 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! Print totals in [Tg C] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'C3H8' ) + + ELSE IF ( N == 9 ) THEN + + !---------- + ! CH2O + !---------- + + ! CH2O is stored in the biomass file as tracer #20 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 20, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! Compute future CH2O emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! CH2O -- print totals in [Tg C/month] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 30d-3, 'CH2O' ) + + ELSE IF ( N == 10 ) THEN + + !---------- + ! C2H6 + !---------- + + ! C2H6 is stored in the biomass file as tracer #21 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 21, + & TAU0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS(:,:,N) ) + + ! C2H6 --convert from [molec/cm2/month] to [molec C/cm2/month] + BIOMASS(:,:,N) = BIOMASS(:,:,N) * 2d0 + + ! Compute future C2H6 emissions (if necessary) + IF ( LFUTURE ) THEN + CALL SCALE_FUTURE( 'VOCbb', BIOMASS(:,:,N) ) + ENDIF + + ! Print totals in [Tg C] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'C2H6' ) + +!------------------------------------------------------------------------- +! Add 9 gaseous BB emissions (tmf, 1/7/09) +!------------------------------------------------------------------------- + ELSE IF ( N == 15 ) THEN + + !---------- + ! GLYX + !---------- + + ! Estimate GLYC emission by scaling CO emission + ! GLYX [mole] / CO [mole] = 0.00662 (from Andreae 2005 update) + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.00662d0 ! [molecule GLYX/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! GLYX -- [molecule GLYX/cm2/month] + ! Print totals in [Tg GLYX] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 58d-3, 'GLYX' ) + + ELSE IF ( N == 16 ) THEN + + !---------- + ! MGLY + !---------- + + ! Estimate MGLY emission by scaling CO emission + ! MGLY [mole] / CO [mole] = 0.00347 (from Andreae 2005 update) + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.00347d0 ! [molecule MGLY/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! MGLY -- [molecule MGLY/cm2/month] + ! Print totals in [Tg MGLY] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 72d-3, 'MGLY' ) + + ELSE IF ( N == 17 ) THEN + + !---------- + ! BENZ + !---------- + ! Estimate BENZ emission by scaling CO emission + ! BENZ [mole] / CO [mole] = 0.00233 + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.00233d0 * 6.0d0 ! [molec C/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! BENZ -- [molec C/cm2/month] + ! Print totals in [Tg C] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'BENZ' ) + + + ELSE IF ( N == 18 ) THEN + + !---------- + ! TOLU + !---------- + ! Estimate TOLU emission by scaling CO emission + ! TOLU [mole] / CO [mole] = 0.00124 + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.00124d0 * 7.0d0 ! [molec C/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! TOLU -- [molec C/cm2/month] + ! Print totals in [Tg C] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'TOLU' ) + + ELSE IF ( N == 19 ) THEN + + !---------- + ! XYLE + !---------- + ! Estimate XYLE emission by scaling CO emission + ! XYLE [mole] / CO [mole] = 0.00048 + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.00048d0 * 8.0d0 ! [molec C/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! XYLE -- [molec C/cm2/month] + ! Print totals in [Tg C] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'XYLE' ) + + ELSE IF ( N == 20 ) THEN + + !---------- + ! C2H4 + !---------- + ! Estimate C2H4 emission by scaling CO emission + ! C2H4 [mole] / CO [mole] = 0.01381 + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.01381d0 * 2.0d0 ! [molec C/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! C2H4 -- [molec C/cm2/month] + ! Print totals in [Tg C] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'C2H4' ) + + ELSE IF ( N == 21 ) THEN + + !---------- + ! C2H2 + !---------- + ! Estimate C2H2 emission by scaling CO emission + ! C2H2 [mole] / CO [mole] = 0.004d0 from Xiao et al. [2007] + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.004d0 * 2.0d0 ! [molec C/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! C2H2 -- [molec C/cm2/month] + ! Print totals in [Tg C] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 12d-3, 'C2H2' ) + + ELSE IF ( N == 22 ) THEN + + !---------- + ! GLYC + !---------- + ! Estimate GLYC emission by scaling CO emission + ! GLYC [mole] / CO [mole] = 0.00477 (from Andreae 2005 update) + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.00477d0 ! [molecule GLYC/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! GLYC -- [molecule GLYC/cm2/month] + ! Print totals in [Tg GLYC] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 60d-3, 'GLYC' ) + + ELSE IF ( N == 23 ) THEN + + !---------- + ! HAC + !---------- + ! Estimate HAC emission by scaling CO emission + ! HAC [mole] / CO [mole] = 0.00331d0 (from Christian et al. [2003] for African biomass) + TRCEMIS(:,:) = + & COEMIS(:,:) * 0.00331d0 ! [molecule HAC/cm2/month] + + BIOMASS(:,:,N) = TRCEMIS(:,:) + + ! HAC -- [molecule HAC/cm2/month] + ! Print totals in [Tg HAC] + CALL TOTAL_BIOMASS_TG( BIOMASS(:,:,N), 74d-3, 'HAC' ) + + ENDIF + ENDDO + + ! Return to calling program + END SUBROUTINE READ_BIOMASS + +!------------------------------------------------------------------------------ + + SUBROUTINE SCALE_BIOMASS_ACET( BBARRAY ) +! +!****************************************************************************** +! Subroutine SCALE_BIOMASS_ACET scales the seasonal acetone biomass +! burning emissions (Case 1 in the decision tree above) to a given +! yearly value. This is needed for the new biogenic emission fluxes. +! (bdf, bmy, 9/4/01, 7/20/04) +! +! Arguments as Input: +! ============================================================================ +! (1 ) BBARRAY (REAL*8) : Array containing biomass burning CO emissions +! +! Reference: +! ============================================================================ +! Jacob, D.J., B.D. Field, E. Jin, I. Bey, Q. Li, J.A. Logan, and +! R.M. Yantosca, Atmospheric budget of acetone, submitted to +! Geophys. Res. Lett., 2001. +! +! NOTES: +! (1 ) Scale factors determined by Brendan Field, in order to match that +! of the acetone paper: Jacob et al, 2001. (bdf, bmy, 9/4/01) +! (2 ) BBARRAY is now dimensioned (IIPAR,JJPAR) (bmy, 9/28/01) +! (3 ) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (4 ) Now reference LBBSEA, LTOMSAI, from "directory_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE LOGICAL_MOD, ONLY : LBBSEA, LTOMSAI + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: BBARRAY(IIPAR,JJPAR) + + !================================================================= + ! SCALE_BIOMASS_ACET begins here! + ! + ! Apply scale factor from Jacob et al 2001 (bdf) + !================================================================= + IF ( LBBSEA .and. .not. LTOMSAI ) THEN + BBARRAY = BBARRAY * 1.77d0 + ENDIF + + ! Return to calling program + END SUBROUTINE SCALE_BIOMASS_ACET + +!------------------------------------------------------------------------------ + + SUBROUTINE SCALE_FUTURE( NAME, BB ) +! +!****************************************************************************** +! Subroutine SCALE_FUTURE applies the IPCC future emissions scale factors +! to the biomass burning emisisons to compute the future emissions of biomass +! burning for NOx, CO, and VOC's. (swu, bmy, 5/30/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) NAME (CHARACTER) : Denotes type of scale factor to use (e.g. NOx) +! (2 ) BB (REAL*8 ) : Array w/ biomass burning emissions [molec/cm2] +! +! NOTES: +!****************************************************************************** +! + ! References to F90 modules + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_CObb + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NOxbb + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_VOCbb + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(INOUT) :: BB(IIPAR,JJPAR) + CHARACTER(LEN=*), INTENT(IN) :: NAME + + ! Local variables + INTEGER :: I, J + + !================================================================= + ! SCALE_FUTURE begins here! + !================================================================= + + IF ( NAME == 'NOxbb' ) THEN + + ! Compute future NOx emissions +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + BB(I,J) = BB(I,J) * GET_FUTURE_SCALE_NOxbb( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE IF ( NAME == 'CObb' ) THEN + + ! Compute future CO emissions +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + BB(I,J) = BB(I,J) * GET_FUTURE_SCALE_CObb( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ELSE + + ! Compute future hydrocarbon emissions +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J ) + DO J = 1, JJPAR + DO I = 1, IIPAR + BB(I,J) = BB(I,J) * GET_FUTURE_SCALE_VOCbb( I, J ) + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ENDIF + + ! Return to calling program + END SUBROUTINE SCALE_FUTURE + +!------------------------------------------------------------------------------ + + SUBROUTINE TOTAL_BIOMASS_TG( BBARRAY, MOLWT, NAME ) +! +!****************************************************************************** +! Subroutine TOTAL_BIOMASS_TG prints the amount of biomass burning emissions +! that are emitted each month in Tg or Tg C. (bmy, 3/20/01, 4/5/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) BBARRAY (REAL*8) : Biomass burning CO emissions [molec/cm2/month] +! +! NOTES: +! (1 ) BBARRAY is now dimensioned (IIPAR,JJPAR). Also, DXYP is dimensioned +! as JGLOB, so use J+J0 to reference it. (bmy, 9/28/01) +! (2 ) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (3 ) Now use function GET_AREA_CM2 from "grid_mod.f" to compute grid +! box surface area in cm2. Removed reference to CMN header file. +! Cosmetic changes. (bmy, 3/14/03) +! (4 ) Now report sums of NOx as Tg N instead of Tg NOx (bmy, 4/5/06) +! (5 ) Add unit choice for GLYX, MGLY, GLYC, HAC (tmf, 1/7/09) +!****************************************************************************** +! + ! References to F90 modules + USE GRID_MOD, ONLY : GET_AREA_CM2 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(IN) :: BBARRAY(IIPAR,JJPAR) + REAL*8, INTENT(IN) :: MOLWT + CHARACTER(LEN=*), INTENT(IN) :: NAME + + ! Local variables + INTEGER :: I, J + REAL*8 :: TOTAL, CONV + CHARACTER(LEN=6) :: UNIT + + !================================================================= + ! TOTAL_BIOMASS_TG begins here! + !================================================================= + + ! Initialize summing variable + TOTAL = 0d0 + + ! Convert to [Tg/month] (or [Tg C/month] for hydrocarbons) + DO J = 1, JJPAR + + ! Conversion factor to [Tg/month] (or [Tg C/month] for HC's) + CONV = GET_AREA_CM2( J ) * ( MOLWT / 6.023d23 ) * 1d-9 + + ! Sum the emissions + DO I = 1, IIPAR + TOTAL = TOTAL + ( BBARRAY(I,J) * CONV ) + ENDDO + ENDDO + + ! Define unit string + SELECT CASE( NAME ) + CASE( 'NOx' ) + UNIT = '[Tg N]' + CASE( 'CO', 'CH2O', 'GLYX', 'MGLY', 'GLYC', 'HAC' ) + UNIT = '[Tg ]' + CASE DEFAULT + UNIT = '[Tg C]' + END SELECT + + ! Write totals + WRITE( 6, 100 ) NAME, TOTAL, UNIT + 100 FORMAT( 'Sum Biomass ', a4, 1x, ': ', f9.3, 1x, a9 ) + + ! Return to calling program + END SUBROUTINE TOTAL_BIOMASS_TG + +!------------------------------------------------------------------------------ + + SUBROUTINE GC_READ_BIOMASS_BCOC( YEAR, MONTH, + & BIOMASS_BC, BIOMASS_OC ) +! +!****************************************************************************** +! Subroutine GC_READ_BIOMASS_BC_OC reads the GEOS-Chem default biomass +! emissions for black carbon and organic carbon. (bmy, 9/28/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) YEAR (INTEGER) : Current year +! (2 ) MONTH (INTEGER) : Current month +! +! Arguments as Output: +! ============================================================================ +! (3 ) BIOMASS_BC (REAL*8 ) : Array for biomass BC emissions [atoms C/cm2/s] +! (4 ) BIOMASS_OC (REAL*8 ) : Array for biomass OC emissions [atoms C/cm2/s] +! +! NOTES: +! (1 ) Took the code that reads the emissions from disk from +! BIOMASS_CARB_GEOS in "carbon_mod.f". (bmy, 9/28/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 + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_BCbb + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_OCbb + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE LOGICAL_MOD, ONLY : LBBSEA, LFUTURE + USE TIME_MOD, ONLY : ITS_A_LEAPYEAR + USE TRACER_MOD, ONLY : XNUMOL + USE TRACERID_MOD, ONLY : IDTBCPO, IDTOCPO + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER :: YEAR, MONTH + REAL*8 :: BIOMASS_BC(IIPAR,JJPAR) + REAL*8 :: BIOMASS_OC(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*8 :: CONV, XTAU, SEC_PER_MONTH + CHARACTER(LEN=4) :: CYEAR + CHARACTER(LEN=255) :: BC_FILE, OC_FILE + + ! Days per month (based on 1998) + REAL*8 :: NDAYS(12) = (/ 31d0, 28d0, 31d0, 30d0, 31d0, 30d0, + & 31d0, 31d0, 30d0, 31d0, 30d0, 31d0 /) + + !================================================================= + ! GC_READ_BIOMASS_BC_OC begins here! + !================================================================= + + ! Make sure BCPO, OCPO tracers are defined + IF ( IDTBCPO == 0 .and. IDTOCPO == 0 ) THEN + BIOMASS_BC = 0d0 + BIOMASS_OC = 0d0 + RETURN + ENDIF + + ! Test for leap year + IF ( MONTH == 2 ) THEN + IF( ITS_A_LEAPYEAR( YEAR ) ) THEN + NDAYS(2) = 29d0 + ELSE + NDAYS(2) = 28d0 + ENDIF + ENDIF + + ! Number of seconds in this month + SEC_PER_MONTH = 86400d0 * NDAYS(MONTH) + + ! Year string + WRITE( CYEAR, '(i4)' ) YEAR + + !================================================================= + ! Read BC/OC biomass burning [kg C/month] as tracers #34, 35 + !================================================================= + + ! Use seasonal or interannual emissions? + IF ( LBBSEA ) THEN + + !------------------------------------ + ! Use seasonal biomass emissions + !------------------------------------ + + ! File name for seasonal BCPO biomass emissions + BC_FILE = TRIM( DATA_DIR ) // + & 'biomass_200110/BCPO.bioburn.seasonal.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! File name for seasonal OCPO biomass emissions + OC_FILE = TRIM( DATA_DIR ) // + & 'biomass_200110/OCPO.bioburn.seasonal.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! Get TAU0 value (use generic year 1985) + XTAU = GET_TAU0( MONTH, 1, 1985 ) + + ELSE + + !------------------------------------ + ! Use interannual biomass emissions + ! for years between 1996 and 2002 + !------------------------------------ + + ! File name for interannual BCPO biomass burning emissions` + BC_FILE = TRIM( DATA_DIR ) // + & 'biomass_200110/BCPO.bioburn.interannual.' // + & GET_NAME_EXT_2D() // '.' // + & GET_RES_EXT() // '.' // CYEAR + + ! File name for interannual BCPO biomass burning emissions + OC_FILE = TRIM( DATA_DIR ) // + & 'biomass_200110/OCPO.bioburn.interannual.' // + & GET_NAME_EXT_2D() // '.' // + & GET_RES_EXT() // '.' // CYEAR + + ! Use TAU0 value on the 1st of this month to index bpch file + XTAU = GET_TAU0( MONTH, 1, YEAR ) + + ENDIF + + !------------------ + ! Read BC biomass + !------------------ + + ! Echo info + WRITE( 6, 100 ) TRIM( BC_FILE ) + 100 FORMAT( ' - GC_READ_BIOMASS_BC_OC: Reading ', a ) + + ! Read BC emission data [kg/mon] + CALL READ_BPCH2( BC_FILE, 'BIOBSRCE', 34, + & XTAU, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 and resize + CALL TRANSFER_2D ( ARRAY(:,:,1), BIOMASS_BC ) + + !------------------ + ! Read OC biomass + !------------------ + + ! Echo info + WRITE( 6, 100 ) TRIM( OC_FILE ) + + ! Read OC emission data [kg/mon] + CALL READ_BPCH2( OC_FILE, 'BIOBSRCE', 35, + & XTAU, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast to REAL*8 and resize + CALL TRANSFER_2D ( ARRAY(:,:,1), BIOMASS_OC ) + + !================================================================= + ! Convert from [kg C/mon] to [atoms C/cm2/s] + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, CONV ) + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Conversion factor for [1/cm2/s] + CONV = 1d0 / ( GET_AREA_CM2( J ) * SEC_PER_MONTH ) + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Convert [kg C/month] -> [atoms C/cm2/s] + BIOMASS_BC(I,J) = BIOMASS_BC(I,J) * XNUMOL(IDTBCPO) * CONV + BIOMASS_OC(I,J) = BIOMASS_OC(I,J) * XNUMOL(IDTOCPO) * CONV + + ! Scale to IPCC future scenario (if necessary) + IF ( LFUTURE ) THEN + + ! Future scale BC biomass + BIOMASS_BC(I,J) = BIOMASS_BC(I,J) * + & GET_FUTURE_SCALE_BCbb( I, J ) + + ! Future scale OC biomass + BIOMASS_OC(I,J) = BIOMASS_OC(I,J) * + & GET_FUTURE_SCALE_OCbb( I, J ) + ENDIF + + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE GC_READ_BIOMASS_BCOC + +!------------------------------------------------------------------------------ + + SUBROUTINE GC_READ_BIOMASS_SO2( YEAR, MONTH, BIOMASS_SO2 ) +! +!****************************************************************************** +! Subroutine GC_READ_BIOMASS_SO2 reads monthly mean biomass burning SO2 +! emissions. (bmy, 9/28/06) +! +! Arguments as Input: +! =========================================================================== +! (1 ) YEAR (INTEGER) : Current year +! (2 ) MONTH (INTEGER) : Current month +! +! Arguments as Input: +! =========================================================================== +! (3 ) BIOMASS_SO2 (REAL*8 ) : Array for biomass SO2 [molec SO2/cm2/s] +! +! NOTES: +! (1 ) Took file reading code out of READ_BIOMASS_SO2 of "sulfate_mod.f" +! and inserted here (bmy, 9/28/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 + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_SO2bb + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE LOGICAL_MOD, ONLY : LBBSEA, LFUTURE + USE TIME_MOD, ONLY : ITS_A_LEAPYEAR + USE TRACER_MOD, ONLY : XNUMOL + USE TRACERID_MOD, ONLY : IDTSO2 + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + REAL*8, INTENT(OUT) :: BIOMASS_SO2(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J, THISYEAR + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*8 :: CONV, XTAU, SEC_PER_MONTH + CHARACTER(LEN=4 ) :: CYEAR + CHARACTER(LEN=255) :: FILENAME + + ! Days per month + REAL*8 :: NDAYS(12) = (/ 31d0, 28d0, 31d0, 30d0, 31d0, 30d0, + & 31d0, 31d0, 30d0, 31d0, 30d0, 31d0 /) + + !================================================================= + ! GC_READ_BIOMASS_SO2 begins here! + !================================================================= + + ! Make sure BCPO, OCPO tracers are defined + IF ( IDTSO2 == 0 ) THEN + BIOMASS_SO2 = 0d0 + RETURN + ENDIF + + ! Test for leap year + IF ( MONTH == 2 ) THEN + IF( ITS_A_LEAPYEAR( YEAR ) ) THEN + NDAYS(2) = 29d0 + ELSE + NDAYS(2) = 28d0 + ENDIF + ENDIF + + ! Seconds in this month + SEC_PER_MONTH = ( 86400d0 * NDAYS(MONTH) ) + + ! Create a string for the 4-digit year + WRITE( CYEAR, '(i4)' ) YEAR + + !================================================================= + ! Read SO2 biomass emissions [kg SO2/month] + !================================================================= + + ! Use seasonal or interannual emisisons? + IF ( LBBSEA ) THEN + + !------------------------------------ + ! Use seasonal biomass emissions + !------------------------------------ + + ! File name for seasonal BB emissions + FILENAME = TRIM( DATA_DIR ) // + & 'biomass_200110/SO2.bioburn.seasonal.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! Get TAU0 value (use generic year 1985) + XTAU = GET_TAU0( MONTH, 1, 1985 ) + + ELSE + + !------------------------------------ + ! Use interannual biomass emissions + ! for years between 1996 and 2002 + !------------------------------------ + + ! File name for interannual biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // + & 'biomass_200110/SO2.bioburn.interannual.' // + & GET_NAME_EXT_2D() // '.' // + & GET_RES_EXT() // '.' // CYEAR + + ! Use TAU0 value at start of this month to index punch file + XTAU = GET_TAU0( MONTH, 1, YEAR ) + + ENDIF + + !--------------------------------------- + ! Read biomass SO2 [kg SO2/month] + !--------------------------------------- + + ! Echo info + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - GC_READ_BIOMASS_SO2: Reading ', a ) + + ! Read SO2 emission data [kg/month] + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 26, + & XTAU, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + ! Cast to REAL*8 and resize + CALL TRANSFER_2D ( ARRAY(:,:,1), BIOMASS_SO2 ) + + !================================================================= + ! Convert units [kg SO2/month] -> [molec SO2/cm2/s] + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, CONV ) + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Conversion factor for [kg/month] -> [molec/cm2/s] + CONV = XNUMOL(IDTSO2) / ( GET_AREA_CM2( J ) * SEC_PER_MONTH ) + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Convert [kg SO2/month] -> [molec SO2/cm2/s] + BIOMASS_SO2(I,J) = BIOMASS_SO2(I,J) * CONV + + ! Scale to IPCC future scenario (if necessary) + IF ( LFUTURE ) THEN + BIOMASS_SO2(I,J) = BIOMASS_SO2(I,J) * + & GET_FUTURE_SCALE_SO2bb( I, J ) + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE GC_READ_BIOMASS_SO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE GC_READ_BIOMASS_NH3( YEAR, MONTH, BIOMASS_NH3 ) +! +!****************************************************************************** +! Subroutine GC_READ_BIOMASS_NH3 reads the monthly mean biomass NH3 +! and biofuel emissions from disk and converts to [molec NH3/cm2/s]. +! (bmy, 9/28/06) +! +! Arguments as Input: +! =========================================================================== +! (1 ) YEAR (INTEGER) : Current year +! (2 ) MONTH (INTEGER) : Current month +! +! Arguments as Input: +! =========================================================================== +! (3 ) BIOMASS_NH3 (REAL*8 ) : Array for biomass NH3 [molec SO2/cm2/s] +! +! NOTES: +! (1 ) Took file reading code out of READ_BIOMASS_NH3 of "sulfate_mod.f" +! and inserted here (bmy, 9/28/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 + USE FUTURE_EMISSIONS_MOD, ONLY : GET_FUTURE_SCALE_NH3bb + USE LOGICAL_MOD, ONLY : LBBSEA, LFUTURE + USE GRID_MOD, ONLY : GET_AREA_CM2 + USE TIME_MOD, ONLY : ITS_A_LEAPYEAR + USE TRACER_MOD, ONLY : XNUMOL + USE TRACERID_MOD, ONLY : IDTNH3 + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + REAL*8, INTENT(OUT) :: BIOMASS_NH3(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*8 :: CONV, SEC_PER_MONTH, XTAU + CHARACTER(LEN=4 ) :: CYEAR + CHARACTER(LEN=255) :: FILENAME + + ! Number of days in the month + REAL*8 :: NDAYS(12) = (/ 31d0, 28d0, 31d0, 30d0, 31d0, 30d0, + & 31d0, 31d0, 30d0, 31d0, 30d0, 31d0 /) + + !================================================================= + ! READ_BIOMASS_NH3 begins here! + !================================================================= + + ! Make sure BCPO, OCPO tracers are defined + IF ( IDTNH3 == 0 ) THEN + BIOMASS_NH3 = 0d0 + RETURN + ENDIF + + ! Test for leap year + IF ( MONTH == 2 ) THEN + IF( ITS_A_LEAPYEAR( YEAR ) ) THEN + NDAYS(2) = 29d0 + ELSE + NDAYS(2) = 28d0 + ENDIF + ENDIF + + ! Number of seconds in this month + SEC_PER_MONTH = 86400d0 * NDAYS(MONTH) + + ! Create a string for the 4-digit year + WRITE( CYEAR, '(i4)' ) YEAR + + !================================================================= + ! Read biomass NH3 emissions [kg NH3/month] + !================================================================= + + ! Use seasonal or interannual emisisons? + IF ( LBBSEA ) THEN + + !------------------------------------ + ! Use seasonal biomass emissions + !------------------------------------ + + ! File name for seasonal BB emissions + FILENAME = TRIM( DATA_DIR ) // + & 'biomass_200110/NH3.bioburn.seasonal.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! Get TAU0 value (use generic year 1985) + XTAU = GET_TAU0( MONTH, 1, 1985 ) + + ELSE + + !------------------------------------ + ! Use interannual biomass emissions + ! for years between 1996 and 2002 + !------------------------------------ + + ! File name for interannual biomass burning emissions + FILENAME = TRIM( DATA_DIR ) // + & 'biomass_200110/NH3.bioburn.interannual.' // + & GET_NAME_EXT_2D() // '.' // + & GET_RES_EXT() // '.' // CYEAR + + ! Use TAU0 value on 1st day of this month to index bpch file + XTAU = GET_TAU0( MONTH, 1, YEAR ) + + ENDIF + + !--------------------------------------- + ! Read NH3 biomass [kg NH3/month] + !--------------------------------------- + + ! Echo filename + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( ' - READ_BIOMASS_NH3: Reading ', a ) + + ! Read NH3 emission data [kg/mon] as tracer 29 + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 29, + & XTAU, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize if necessary + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS_NH3 ) + + !================================================================= + ! Compute IPCC future emissions (if necessary) + !================================================================= + +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( I, J, CONV ) + + ! Loop over latitudes + DO J = 1, JJPAR + + ! Conversion factor for [kg/month] -> [molec/cm2/s] + CONV = XNUMOL(IDTNH3) / ( GET_AREA_CM2( J ) * SEC_PER_MONTH ) + + ! Loop over longitudes + DO I = 1, IIPAR + + ! Convert [kg NH3/month] -> [molec NH3/cm2/s] + BIOMASS_NH3(I,J) = BIOMASS_NH3(I,J) * CONV + + ! Scale to IPCC future scenario (if necessary) + IF ( LFUTURE ) THEN + BIOMASS_NH3(I,J) = BIOMASS_NH3(I,J) * + & GET_FUTURE_SCALE_NH3bb( I, J ) + ENDIF + ENDDO + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE GC_READ_BIOMASS_NH3 + +!------------------------------------------------------------------------------ + + SUBROUTINE GC_READ_BIOMASS_CO2( YEAR, MONTH, BIOMASS_CO2 ) +! +!****************************************************************************** +! Subroutine GC_READ_BIOMASS_CO2 reads in monthly values of CO for +! biomass burning from a binary punch file. (pns, bmy, 8/16/05, 9/28/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) MONTH (INTEGER) : Current month of year (1-12) +! (2 ) YEAR (INTEGER) : Current year (e.g. 1990) +! +! NOTES: +! (1 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (2 ) Moved here from "co2_mod.f" (bmy, 9/28/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 + USE LOGICAL_MOD, ONLY : LBBSEA + USE TIME_MOD, ONLY : ITS_A_LEAPYEAR + USE TRACER_MOD, ONLY : ITS_A_CO2_SIM + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: YEAR, MONTH + REAL*8, INTENT(OUT) :: BIOMASS_CO2(IIPAR,JJPAR) + + ! Local variables + INTEGER :: I, J + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + REAL*8 :: EMFACTCO2CO, TAU, SEC_PER_MONTH + CHARACTER(LEN=4) :: SYEAR + CHARACTER(LEN=255) :: FILENAME + + ! Number of days in the month + REAL*8 :: NDAYS(12) = (/ 31d0, 28d0, 31d0, 30d0, 31d0, 30d0, + & 31d0, 31d0, 30d0, 31d0, 30d0, 31d0 /) + + !================================================================= + ! READ_BIOMASS_CO2 begins here! + !================================================================= + + ! Make sure it's a CO2 simulation + IF ( .not. ITS_A_CO2_SIM() ) THEN + BIOMASS_CO2 = 0d0 + RETURN + ENDIF + + ! Test for leap year + IF ( MONTH == 2 ) THEN + IF( ITS_A_LEAPYEAR( YEAR ) ) THEN + NDAYS(2) = 29d0 + ELSE + NDAYS(2) = 28d0 + ENDIF + ENDIF + + ! Seconds per month + SEC_PER_MONTH = 86400d0 * NDAYS(MONTH) + + ! Currently calculate CO2 emissions as a function of CO emissions + ! from biomass burning. Set Emission factor (CO2 to CO) + ! Calculation based on global totals of + ! 5524.7 Tg dry matter (of which 45% is carbon) + ! 438.08 Tg CO (of which 187.75 Tg is carbon), and + ! 32.6 Tg C of other species + !Refs : Staudt et al., Rose Yevich tables + !Check with Rose Yevich for most recent estimates on emission factors + EMFACTCO2CO = 12.068d0 + + ! Test for climatological or interannual emissions + IF ( LBBSEA ) THEN + + !-------------------------------------- + ! Climatological biomass emissions + !-------------------------------------- + + ! TAU value for this month of "generic" year 1985 + TAU = GET_TAU0( MONTH, 1, 1985 ) + + ! Name of climatological biomass burning file + FILENAME = TRIM( DATA_DIR ) // + & 'biomass_200110/bioburn.seasonal.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ELSE + + !-------------------------------------- + ! Interannual biomass emissions + !-------------------------------------- + + ! Make a string for YEAR + WRITE( SYEAR, '(i4)' ) YEAR + + ! TAU value for the given month of this year + TAU = GET_TAU0( MONTH, 1, YEAR ) + + ! Name of interannual biomass burning file + FILENAME = TRIM( DATA_DIR ) // + & 'biomass_200110/bioburn.interannual.' // + & GET_NAME_EXT_2D() // '.' // + & GET_RES_EXT() // '.' // SYEAR + + ENDIF + + !----------------------------------------- + ! Read data from disk + !----------------------------------------- + + ! Initialize ARRAY + ARRAY = 0e0 + + ! Read CO biomass emissions [molec CO/cm2/month] + CALL READ_BPCH2( FILENAME, 'BIOBSRCE', 4, + & TAU, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + ! Cast from REAL*4 to REAL*8 and resize to (IIPAR,JJPAR) + CALL TRANSFER_2D( ARRAY(:,:,1), BIOMASS_CO2 ) + + ! Convert from [molec CO/cm2/month] to [molec CO2/cm2/month] + BIOMASS_CO2 = BIOMASS_CO2 * EMFACTCO2CO + + ! Print total CO2 biomass in Tg + CALL TOTAL_BIOMASS_TG( BIOMASS_CO2, 44d-3, 'CO2' ) + + ! Convert from [molec CO2/cm2/month] to [molec CO2/cm2/s] + BIOMASS_CO2 = BIOMASS_CO2 / SEC_PER_MONTH + + ! Return to calling program + END SUBROUTINE GC_READ_BIOMASS_CO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE ADJUST_TO_TOMSAI( BIOMASS_ANN, BIOMASS_SEA, BIOMASS ) +! +!****************************************************************************** +! Subroutine ADJUST_TO_TOMSAI is a wrapper for subroutine TOMSAI. +! (bmy, 10/12/00, 4/5/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) BIOMASS_ANN (REAL*8 ) : Annual biomass emissions [molec/cm2/month] +! (2 ) BIOMASS_SEA (REAL*8 ) : Seasonal biomass emissions [molec/cm2/month] +! +! Arguments as Output: +! ============================================================================ +! (3 ) BIOMASS (REAL*8 ) : Adjusted biomass emisssions [molec/cm2/month] +! +! NOTES: +! (1 ) Bug fix: Now scale annual BB emissions to TOMS for selected +! regions, and overwrite w/ seasonal BB emissions elsewhere. +! (bnd, bmy, 6/6/01) +! (2 ) BIOMASS_ANN, BIOMASS_SEA, and BIOMASS are now all of size +! (NBIOMAX,IIPAR,JJPAR). (bmy, 9/28/01) +! (3 ) Removed obsolete code from 9/01 (bmy, 10/23/01) +! (4 ) Remove IMONTH from arg list. Remove IMONTH from call to TOMSAI +! (bmy, 2/11/03) +! (5 ) Now dimension arrays (I,J,N) instead of (N,I,J) (bmy, 4/5/06) +!****************************************************************************** +! +# include "CMN_SIZE" + + ! Arguments + REAL*8, INTENT(INOUT) :: BIOMASS_ANN(IIPAR,JJPAR,NBIOMAX) + REAL*8, INTENT(INOUT) :: BIOMASS_SEA(IIPAR,JJPAR,NBIOMAX) + REAL*8, INTENT(INOUT) :: BIOMASS(IIPAR,JJPAR,NBIOMAX) + + ! Local variables + INTEGER :: I, J, N + + ! ADJUST_TO_TOMSAI begins here! + WRITE( 6, '(a)' ) 'BIOBURN: Adjusting to TOMS AI data...' + + ! Loop over all tracers & boxes -- adjust to TOMS Aerosol index + DO N = 1, NBIOMAX + DO J = 1, JJPAR + DO I = 1, IIPAR + CALL TOMSAI( I, J, BIOMASS_ANN(I,J,N), + & BIOMASS_SEA(I,J,N), BIOMASS(I,J,N) ) + ENDDO + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE ADJUST_TO_TOMSAI + +!------------------------------------------------------------------------------ + + SUBROUTINE TOMSAI( I, J, VAL_ANN, VAL_SEAS, ADJUSTED_VALUE ) +! +!****************************************************************************** +! Subroutine TOMSAI uses TOMS aerosol index for the last two decades as a +! surrogate for biomass burning. The biomass burning emission climatology +! is adjusted for each month and year. For months without information, +! the climatology is used. There is no TOMS AI data for July-August 1990 +! and May 1993 - August 1996. +! +! Written by Bryan Duncan 8/2000. +! Inserted into F90 module "biomass_mod.f" (bmy, 9/25/00, 12/1/04) +! +! Subroutine TOMSAI is called from routine BIOBURN of "biomass_mod.f". +! +! Arguments as Input: +! =========================================================================== +! (1-2) I, J (INTEGER) : indices of box +! (3 ) VAL_SEAS (REAL*4 ) : Seasonal biomass value +! (4 ) VAL_ANN (REAL*4 ) : Annual biomass value +! +! Arguments as Output: +! =========================================================================== +! (5 ) ADJUSTED_VALUE (REAL*4) : CO emission for box(I,J) after adjustment. +! +! +! Other variables: +! =========================================================================== +! TOMSAISCALE = scaling factor by region for a specific month and year. +! NAIREGIONS = number of regions for which there is data. +! NAIYEARS = number of years for which there is data. +! NAIMONTHS = 12*NAIYEARS; number of months for which there is data. +! +! NOTES: +! (1 ) Remove references to "CMN_CO", "CMN_OH", and "CMN". (bmy, 9/25/00) +! (2 ) Updated lat/lon boundaries of geographic regions (bnd, bmy, 10/16/00) +! (3 ) Now references ALLOC_ERR from "error_mod.f" (bmy, 10/15/02) +! (4 ) Now use functions GET_MONTH, GET_TAU, GET_YEAR from "time_mod.f" +! Removed IMONTH from the arg list. IMONTH, JYEAR, and TAU are now +! local variables. (bmy, 2/11/03) +! (5 ) Change VAL_ANN and VAL_SEAS to INTENT(IN). (bmy, 4/28/03) +! (6 ) Now reference DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +! (7 ) Added space in #ifdef block for 1 x 1.25 grid (bmy, 12/1/04) +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE ERROR_MOD, ONLY : ALLOC_ERR + USE TIME_MOD, ONLY : GET_MONTH, GET_TAU, GET_YEAR + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: I, J + REAL*8, INTENT(INOUT) :: ADJUSTED_VALUE + REAL*8, INTENT(IN) :: VAL_ANN + REAL*8, INTENT(IN) :: VAL_SEAS + + ! Local variables + INTEGER :: THEYEAR, IPICK, CTM_lat, CTM_lon + INTEGER :: II, JJ, KK, LL, AS, IMONTH, JYEAR + INTEGER, SAVE :: IFIRSTCALL = 1 + REAL*8 :: CONVERT_lon, READINTOMS(NMONTHSAI), TAU + + !================================================================= + ! TOMSAI begins here! + !================================================================= + + ! Get time quantities + IMONTH = GET_MONTH() + JYEAR = GET_YEAR() + TAU = GET_TAU() + + !================================================================= + ! Read in scaling factors on first call to SR. + ! The scaling factors are stored in TOMSAI. + ! They run from Jan 1979 to Dec 1999 = 252 months total. + !================================================================= + IF(IFIRSTCALL.EQ.1) THEN + IFIRSTCALL = 0 + + ! Allocate TOMSAISCALE array + ALLOCATE( TOMSAISCALE( NAIREGIONS, NAIYEARS, 12 ), STAT=AS ) + IF ( AS / = 0 ) CALL ALLOC_ERR( 'TOMSAISCALE' ) + + ! Read TOMS Aerosol index data + OPEN( 199, FILE = TRIM( DATA_DIR ) // 'TOMSAI', STATUS='OLD' ) + DO JJ=1,NAIREGIONS + READ( 199, * ) readinTOMS + + II=0 + DO KK=1,NAIYEARS + DO LL=1,12 + II=II+1 + TOMSAISCALE(JJ,KK,LL)=readinTOMS(II) + ENDDO + ENDDO + + ENDDO + CLOSE(199) + ENDIF + + !================================================================= + ! The AI data is on a 1.25 x 1 degree grid (lon,lat). Therefore, + ! convert the box number from the code to the corresponding box + ! number of the AI data. + !================================================================= +#if defined( GRID4x5 ) + CONVERT_lon = ( DBLE(I) * 5.d0 ) * 1.d0 / 1.25d0 + CTM_lon = INT( CONVERT_lon ) + CTM_lat = ( J * 4 ) - 2 + + IF (J == 1 ) CTM_LAT = 2 + IF (J == JJPAR ) CTM_LAT = 88 + 90 + +#elif defined( GRID2x25 ) + CONVERT_lon = ( DBLE(I) * 2.5d0 ) * 1.d0 / 1.25d0 + CTM_LON = INT( CONVERT_LON ) + CTM_LAT = ( J * 2 ) - 1 + + IF (J == 1 ) CTM_LAT = 1 + IF (J == JJPAR ) CTM_LAT = 89 + 90 + +#elif defined( GRID1x125 ) + PRINT*, 'Need to compute CONVERT_LON for 1 x 1.25 grid!' + PRINT*, 'STOP in TOMSAI (biomass_mod.f)' + STOP + +#elif defined( GRID1x1 ) + PRINT*, 'Need to compute CONVERT_LON for 1 x 1 grid!' + PRINT*, 'STOP in TOMSAI (biomass_mod.f)' + STOP + +#endif + + !================================================================= + ! See what region the box falls in to pick the appropriate + ! regional scaling factor. + !================================================================= + IPICK=0 + + ! Indonesia + IF(CTM_lat.GE.83.and.CTM_lat.LE.99) THEN + IF(CTM_lon.GE.221.and.CTM_lon.LE.269) THEN + IPICK=1 + ENDIF + ENDIF + + ! Brazil + IF(CTM_lat.GE.59.and.CTM_lat.LE.91) THEN + IF(CTM_lon.GE.96.and.CTM_lon.LE.116) THEN + IF(IMONTH.GE.6.AND.IMONTH.LE.12) THEN + IPICK=2 + ELSE + IPICK=20 + ENDIF + ENDIF + ENDIF + + ! Southern Africa + IF(CTM_lat.GE.50.and.CTM_lat.LE.90) THEN + IF(CTM_lon.GE.128.and.CTM_lon.LE.184) THEN + IPICK=3 + ENDIF + ENDIF + + ! Northern Africa + IF(CTM_lat.GE.91.and.CTM_lat.LE.110) THEN + IF(CTM_lon.GE.128.and.CTM_lon.LE.184) THEN + IPICK=4 + ENDIF + ENDIF + + ! Central America and Mexico + IF(CTM_lat.GE.96.and.CTM_lat.LE.115) THEN + IF(CTM_lon.GE.61.and.CTM_lon.LE.85) THEN + IF(IMONTH.GE.2.AND.IMONTH.LE.5) THEN + IPICK=5 + ELSE + IPICK=20 + ENDIF + ENDIF + ENDIF + + ! Canada and Alaska + ! We have fire burn estimates for Canada, so we can use + ! this data to fill in the TOMS data gap. + IF(CTM_lat.GE.141.and.CTM_lat.LE.161) THEN + IF(CTM_lon.GE.16.and.CTM_lon.LE.96) THEN + IF(IMONTH.GE.5.AND.IMONTH.LE.9) THEN + IPICK=6 + ELSE + IPICK=20 + ENDIF + ENDIF + ENDIF + + ! Asiatic Russia + IF(CTM_lat.GE.136.and.CTM_lat.LE.161) THEN + IF(CTM_lon.GE.211.and.CTM_lon.LE.291) THEN + IF(IMONTH.GE.5.AND.IMONTH.LE.9) THEN + IPICK=7 + ELSE + IPICK=20 + ENDIF + ENDIF + ENDIF + + ! Southeast Asia + IF(CTM_lat.GE.99.and.CTM_lat.LE.119) THEN + IF(CTM_lon.GE.221.and.CTM_lon.LE.239) THEN + IF(IMONTH.GE.1.AND.IMONTH.LE.5) THEN + IPICK=8 + ELSE + IPICK=20 + ENDIF + ENDIF + ENDIF + + ! Error Check. + IF(IMONTH.LT.1.OR.IMONTH.GT.12) THEN + PRINT*,'Error in SR TOMSAI: Value of IMONTH is wrong.' + PRINT*,'IMONTH = ',IMONTH + STOP + ENDIF + + !================================================================= + ! During the TOMS data gaps, set IPICK = 0; emissions are + ! not rescaled for the box and the seasonal variation is used, + ! except for Indonesia and Canada & Alaska. + !================================================================= + + ! July - August 1990 + IF ( IPICK /= 6 ) THEN + IF ( TAU == 48168d0 ) IPICK = 0 + IF ( TAU == 48912d0 ) IPICK = 0 + ENDIF + + ! May 1993 - July 1996 + IF ( IPICK /= 6 .AND. IPICK /= 1 ) THEN + IF ( TAU >= 73008d0 .AND. TAU <= 100776d0 ) IPICK = 0 + ENDIF + + !================================================================= + ! Rescale CO emission. If IPICK = 0 then emissions are + ! not rescaled for the box and the seasonal variation is used. + !================================================================= + + ! Adjust with TOMS AI + IF( IPICK > 0 .AND. IPICK /= 3 .AND. IPICK /= 4 ) THEN + + THEYEAR = JYEAR - 1978 + + IF ( THEYEAR > NAIYEARS .OR. THEYEAR < 0 ) THEN + PRINT*,'Error in SR TOMSAI: You have picked a year less' + PRINT*,'than 1979 or greater than 1999. The data in this' + PRINT*,'SR used to scale biomass burning emissions is only' + PRINT*,'good for 1979-1999. You may need to comment out' + PRINT*,'the call to this SR in SR bioburn.' + PRINT*,'Your year is ',JYEAR,'.' + STOP + ENDIF + + ! Do not adjust Africa with TOMSAI!!!! + IF ( IPICK /= 20 ) THEN + ADJUSTED_VALUE = VAL_ANN * + & TOMSAISCALE(IPICK,THEYEAR,IMONTH) + ELSE + + ! Zero out IPICK regions when the biomass burning + ! season is not occuring. + ADJUSTED_VALUE = 0d0 + ENDIF + + ELSE ! IPICK=0; IPICK=3; IPICK=4 + + ! Use seasonal emissions instead + ADJUSTED_VALUE = VAL_SEAS + ENDIF + + ! Return to calling program + END SUBROUTINE TOMSAI + +!------------------------------------------------------------------------------ + + SUBROUTINE CLEANUP_GC_BIOMASS +! +!****************************************************************************** +! Subroutine CLEANUP_BIOMASS deallocates the BURNEMIS and +! TOMSAISCALE arrays (bmy, 4/5/06) +! +! NOTES: +!****************************************************************************** +! + !================================================================= + ! CLEANUP_GC_BIOMASS begins here! + !================================================================= + IF ( ALLOCATED( TOMSAISCALE ) ) DEALLOCATE( TOMSAISCALE ) + + ! Return to calling program + END SUBROUTINE CLEANUP_GC_BIOMASS + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE GC_BIOMASS_MOD diff --git a/code/gcap_convect_mod.f b/code/gcap_convect_mod.f new file mode 100644 index 0000000..667c5e6 --- /dev/null +++ b/code/gcap_convect_mod.f @@ -0,0 +1,854 @@ +! $Id: gcap_convect_mod.f,v 1.1 2009/06/09 21:51:53 daven Exp $ + MODULE GCAP_CONVECT_MOD +! +!****************************************************************************** +! Module GCAP_CONVECT_MOD contains routines (originally from GISS) which +! perform shallow and deep convection for the GCAP met fields. This module +! was based on FVDAS_CONVECT_MOD. (swu, bmy, 6/9/05, 12/19/06) +! +! Module Variables: +! ============================================================================ +! (1 ) GRAV (REAL*8 ) : Gravitational constant [m/s2] +! (2 ) SMALLEST (REAL*8 ) : A very small double-precision number +! (3 ) TINYNUM (REAL*8 ) : 2 times the SMALLEST +! +! Module Routines: +! ============================================================================ +! (1 ) INIT_GCAP_CONVECT : Initializes fvDAS convection scheme +! (2 ) GCAP_CONVECT : GCAP/GISS convection driver +! (4 ) ARCCONVTRAN : Sets up fields for ZHANG/MCFARLANE convection +! (5 ) CONVTRAN : ZHANG/MCFARLANE convection scheme routine +! (6 ) WHENFGT : Test funtion +! +! GEOS-CHEM modules referenced by fvdas_convect_mod.f: +! ============================================================================ +! (1 ) pressure_mod.f : Module containing routines to compute P(I,J,L) +! +! NOTES: +! (1 ) Rewrote parallel loops to avoid problems w/ OpenMP (bmy, 12/13/05) +! (2 ) Replace TINY(1d0) with 1d-32 to avoid problems on SUN 4100 platform +! (bmy, 9/5/06) +! (3 ) More bug fixes for SUN 4100 platform. Make SMALLEST = 1d-60 to avoid +! problems (bmy, 12/19/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "gcap_convect_mod.f" + !================================================================= + + ! Declare everything PRIVATE ... + PRIVATE + + ! ... except these routines + PUBLIC :: GCAP_CONVECT + + !================================================================= + ! MODULE VARIABLES + !================================================================= + + ! Constants + REAL*8, PARAMETER :: GRAV = 9.8d0 + REAL*8, PARAMETER :: SMALLEST = 1d-60 + REAL*8, PARAMETER :: TINYNUM = 2*SMALLEST + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE GCAP_CONVECT( TDT, Q, NTRACE, DP, + & NSTEP, FRACIS, TCVV, INDEXSOL, + & UPDE, DNDE, ENTRAIN, DETRAINE, + & UPDN, DNDN, DETRAINN ) +! +!****************************************************************************** +! Subroutine GCAP_CONVECT is the convection driver routine for GEOS-4/fvDAS +! met fields. It calls the ZHANG/MCFARLANE convection scheme. +! (swu, bmy, 6/9/05, 12/19/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TDT (REAL*8 ) : 2 * delta-T [s] +! (2 ) Q (REAL*8 ) : Array of transported tracers [v/v] +! (3 ) RPDEL (REAL*8 ) : 1./pde [1/hPa] +! (4 ) ETA (REAL*8 ) : GMAO Hack convective mass flux [kg/m2/s] +! (5 ) BETA (REAL*8 ) : GMAO Hack overshoot parameter [unitless] +! (6 ) NTRACE (INTEGER) : Number of tracers to transport [unitless] +! (7 ) MU (REAL*8 ) : GMAO updraft mass flux (ZMMU) [ ]pa/s +! (8 ) MD (REAL*8 ) : GMAO downdraft mass flux (ZMMD) [ ]pa/s +! (9 ) EU (REAL*8 ) : GMAO updraft entrainment (ZMEU) [ ]pa/s +! (10) DP (REAL*8 ) : Delta-pressure between level edges [hPa]pa +! (11) NSTEP (INTEGER) : Time step index [unitless] +! (12) FRACIS (REAL*8 ) : Fraction of tracer that is insoluble [unitless] +! +! Arguments as Output: +! ============================================================================ +! (2 ) Q (REAL*8 ) : Modified tracer array [v/v] +! +! Important Local Variables: +! ============================================================================ +! (1 ) IDEEP (INTEGER) : Gathering array +! (2 ) IL1G (INTEGER) : Gathered min lon indices over which to operate +! (3 ) IL2G (INTEGER) : Gathered max lon indices over which to operate +! (4 ) JT (INTEGER) : Index of cloud top for each column +! (5 ) LENGATH(INTEGER) : ?? +! (6 ) DSUBCLD(REAL*8 ) : Delta pressure from cloud base to sfc +! (7 ) DPG (REAL*8 ) : gathered .01*dp +! (8 ) MX (INTEGER) : Index of cloud top for each column +! +! NOTES: +! (1 ) Rewrote parallel loops so that we pass entire arrays to the various +! subroutines instead of array slices such as (:,J,:). This can cause +! problems with OpenMP for some compilers. (bmy, 12/13/05) +! (2 ) Now don't call CONVTRAN if LENGATH=0 (bmy, 12/19/06) +!****************************************************************************** +! + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: NTRACE + REAL*8, INTENT(IN) :: TDT + REAL*8, INTENT(INOUT) :: Q(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: DP(IIPAR,JJPAR,LLPAR) + INTEGER, INTENT(IN) :: NSTEP + REAL*8, INTENT(IN) :: FRACIS(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: TCVV(NTRACE) + INTEGER, INTENT(IN) :: INDEXSOL(NTRACE) + REAL*8, INTENT(IN) :: UPDE(:,:,:) + REAL*8, INTENT(IN) :: DNDE(:,:,:) + REAL*8, INTENT(IN) :: ENTRAIN(:,:,:) + REAL*8, INTENT(IN) :: DETRAINE(:,:,:) + REAL*8, INTENT(IN) :: UPDN(:,:,:) + REAL*8, INTENT(IN) :: DNDN(:,:,:) + REAL*8, INTENT(IN) :: DETRAINN(:,:,:) + + ! Local variables + INTEGER :: I, J, L, N, LENGATH, ISTEP + INTEGER :: JT(IIPAR) + INTEGER :: MX(IIPAR) + INTEGER :: IDEEP(IIPAR) + INTEGER :: IL1G=1 + INTEGER :: IL2G=JJPAR + REAL*8 :: DPG(IIPAR,LLPAR) + REAL*8 :: ED(IIPAR,LLPAR) + REAL*8 :: UPDEG(IIPAR,LLPAR) + REAL*8 :: DNDEG(IIPAR,LLPAR) + REAL*8 :: ENTRAING(IIPAR,LLPAR) + REAL*8 :: DETRAINEG(IIPAR,LLPAR) + REAL*8 :: TOTALDNDEG(IIPAR,LLPAR) + REAL*8 :: UPDNG(IIPAR,LLPAR) + REAL*8 :: DNDNG(IIPAR,LLPAR) + REAL*8 :: DETRAINNG(IIPAR,LLPAR) + REAL*8 :: TOTALDNDNG(IIPAR,LLPAR) + REAL*8 :: ENTRAINN(IIPAR,JJPAR,LLPAR) + REAL*8 :: ENTRAINNG(IIPAR,LLPAR) + + !================================================================= + ! GCAP_CONVECT begins here! + !================================================================= + + ! Fake entrainment in non-entraining plumes (swu, bmy, 6/9/05) + ENTRAINN = 0d0 + + ! Loop over latitudes +!$OMP PARALLEL DO +!$OMP+DEFAULT( SHARED ) +!$OMP+PRIVATE( J, ISTEP, UPDEG, DNDEG, DETRAINEG ) +!$OMP+PRIVATE( ENTRAING, TOTALDNDEG, DPG, JT, MX ) +!$OMP+PRIVATE( IDEEP, LENGATH, UPDNG, DNDNG, DETRAINNG ) +!$OMP+PRIVATE( ENTRAINNG, TOTALDNDNG ) +!$OMP+SCHEDULE( DYNAMIC ) + DO J = 1, JJPAR + + !---------------------------- + ! Entraining convection + !---------------------------- + + ! Set up convection fields + CALL ARCONVTRAN( J, NSTEP, DP, UPDE, + & DNDE, DETRAINE, ENTRAIN, UPDEG, + & DNDEG, DETRAINEG, ENTRAING, TOTALDNDEG, + & DPG, JT, MX, IDEEP, + & LENGATH ) + + ! Internal convection steps + DO ISTEP = 1, NSTEP + + ! If there are nonzero fields at this J, do the convection + IF ( LENGATH > 0 ) THEN + CALL CONVTRAN( J, NTRACE, Q, + & UPDEG, DNDEG, DETRAINEG, ENTRAING, + & TOTALDNDEG, DPG, JT, MX, + & IDEEP, 1, LENGATH, NSTEP, + & 0.5D0*TDT, FRACIS, TCVV, INDEXSOL ) + ENDIF + + ENDDO + + !---------------------------- + ! Non-entraining convection + !---------------------------- + + ! Set up convection fields + CALL ARCONVTRAN( J, NSTEP, DP, UPDN, + & DNDN, DETRAINN, ENTRAINN, UPDNG, + & DNDNG, DETRAINNG, ENTRAINNG, TOTALDNDNG, + & DPG, JT, MX, IDEEP, + & LENGATH ) + + ! Loop over internal convection timesteps + DO ISTEP = 1, NSTEP + + ! If there are nonzero fields at this J, do the convection + IF ( LENGATH > 0 ) THEN + CALL CONVTRAN( J, NTRACE, Q, + & UPDNG, DNDNG, DETRAINNG, ENTRAINNG, + & TOTALDNDNG, DPG, JT, MX, + & IDEEP, 1, LENGATH, NSTEP, + & 0.5D0*TDT, FRACIS, TCVV, INDEXSOL ) + ENDIF + + ENDDO + + ENDDO +!$OMP END PARALLEL DO + + ! Return to calling program + END SUBROUTINE GCAP_CONVECT + +!------------------------------------------------------------------------------ + + SUBROUTINE ARCONVTRAN( J, NSTEP, DP, MU, MD, + & DU, EU, MUG, MDG, DUG, + & EUG, TOTALMDG, DPG, JTG, JBG, + & IDEEP, LENGATH ) +! +!****************************************************************************** +! Subroutine ARCONVTRAN sets up the convective transport using archived mass +! fluxes from the ZHANG/MCFARLANE convection scheme. The setup involves: +! (1) Gather mass flux arrays. +! (2) Calc the mass fluxes that are determined by mass balance. +! (3) Determine top and bottom of convection. +! (pjr, dsa, bmy, 6/26/03, 12/13/05) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : GEOS-CHEM latitude index [unitless] +! (2 ) NSTEP (INTEGER) : Time step index +! (3 ) DP (REAL*8 ) : Delta pressure between interfaces [Pa ] +! (4 ) MU (REAL*8 ) : Mass flux up [kg/m2/s ] +! (5 ) MD (REAL*8 ) : Mass flux down [kg/m2/s ] +! (6 ) EU (REAL*8 ) : Mass entraining from updraft [1/s ] +! +! Arguments as Output: +! ============================================================================ +! (7 ) MUG (REAL*8 ) : Gathered mu Pa/s +! (8 ) MDG (REAL*8 ) : Gathered md Pa/s +! (9 ) DUG (REAL*8 ) : Mass detraining from updraft (gathered) Pa/S +! (10) EUG (REAL*8 ) : Gathered eu Pa/S +! (11) EDG (REAL*8 ) : Mass entraining from downdraft (gathered) Pa/s +! (12) DPG (REAL*8 ) : Gathered Pa +! (13) DSUBCLD (REAL*8 ) : Delta pressure from cloud base to sfc (gathered) +! (14) JTG (INTEGER) : Cloud top layer for columns undergoing conv. +! (15) JBG (INTEGER) : Cloud bottom layer for columns undergoing conv. +! (16) IDEEP (INTEGER) : Index of longitudes where deep conv. happens +! (17) LENGATH (INTEGER) : Length of gathered arrays +! +! NOTES: +! (1 ) Now dimension DP, MU, MD, DU, EU as (IIPAR,JJPAR,LLPAR) to avoid seg +! fault error in OpenMP. Also now pass the GEOS-CHEM latitude index J +! via the argument list. Add comments. (bmy, 12/13/05) +!****************************************************************************** +! +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: NSTEP + REAL*8, INTENT(IN) :: DP(IIPAR,JJPAR,LLPAR) + REAL*8, INTENT(IN) :: MU(:,:,:) + REAL*8, INTENT(IN) :: MD(:,:,:) + REAL*8, INTENT(IN) :: DU(:,:,:) + REAL*8, INTENT(IN) :: EU(:,:,:) + REAL*8, INTENT(OUT) :: MUG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: MDG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: DUG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: EUG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: TOTALMDG(IIPAR,LLPAR) + REAL*8, INTENT(OUT) :: DPG(IIPAR,LLPAR) + INTEGER, INTENT(OUT) :: JTG(IIPAR) + INTEGER, INTENT(OUT) :: JBG(IIPAR) + INTEGER, INTENT(OUT) :: IDEEP(IIPAR) + INTEGER, INTENT(OUT) :: LENGATH + + ! Local variables + INTEGER :: I, K, LENPOS + INTEGER :: INDEX(IIPAR) + REAL*8 :: SUM(IIPAR) + REAL*8 :: RDPG(IIPAR,LLPAR) + REAL*8 :: TOTALMD(IIPAR,LLPAR) + + !================================================================= + ! ARCONVTRAN begins here! + !================================================================= + + ! Gathered array contains all columns with a updraft. + DO I = 1, IIPAR + SUM(I) = 0.d0 + ENDDO + + DO K = 1, LLPAR + DO I = 1, IIPAR + SUM(I) = SUM(I) + MU(I,J,K) + + ! Calculate totalMD --- all the downdrafts coming downstairs + IF ( K == 1 ) THEN + TOTALMD(I,K) = MD(I,J,K) + ELSE + TOTALMD(I,K) = TOTALMD(I,K-1) + MD(I,J,K) + ENDIF + + ENDDO + ENDDO + + CALL WHENFGT( IIPAR, SUM, 1, 0D0, IDEEP, LENGATH ) + + ! Return if LENGATH is zero + IF ( LENGATH == 0 ) return + + !================================================================= + ! Gather input mass fluxes + !================================================================= + DO K = 1, LLPAR + DO I = 1, LENGATH + DPG(I,K) = DP(IDEEP(I),J,K) !Pa + MUG(I,K) = MU(IDEEP(I),J,K) !Pa/s + MDG(I,K) = MD(IDEEP(I),J,K) + EUG(I,K) = EU(IDEEP(I),J,K) + DUG(I,K) = DU(IDEEP(I),J,K) + TOTALMDG(I,K) = TOTALMD(IDEEP(I),K) !!!=sum( MD(ideep(I),1:K) ) + ENDDO + ENDDO + + !================================================================= + ! Find top and bottom layers with updrafts. + !================================================================= + DO I = 1, LENGATH + JTG(I) = LLPAR + JBG(I) = 1 + ENDDO + + DO K = 2, LLPAR + + CALL WHENFGT( LENGATH, MUG(:,K), 1, 0D0, INDEX, LENPOS ) + + DO I = 1, LENPOS + JTG(INDEX(I)) = MIN( K-1, JTG(INDEX(I)) ) + JBG(INDEX(I)) = MAX( K, JBG(INDEX(I)) ) + ENDDO + ENDDO + + ! Return to calling program + END SUBROUTINE ARCONVTRAN + +!------------------------------------------------------------------------------ + + SUBROUTINE CONVTRAN( J, NTRACE, Q, MU, MD, + & DU, EU, TOTALMD, DP, JT, + & MX, IDEEP, IL1G, IL2G, NSTEP, + & DELT, FRACIS, TCVV, INDEXSOL ) +! +!****************************************************************************** +! Subroutine CONVTRAN applies the convective transport of trace species +! (assuming moist mixing ratio) using the ZHANG/MCFARLANE convection scheme. +! (swu, bmy, 6/9/05, 12/19/06) +! +! Arguments as Input: +! ============================================================================ +! (1 ) J (INTEGER) : GEOS-CHEM latitude index +! (2 ) NTRACE (INTEGER) : Number of tracers to transport [unitless] +! (3 ) Q (REAL*8 ) : Tracer conc. including moisture [v/v ] +! (4 ) MU (REAL*8 ) : Mass flux up [Pa/s ] +! (5 ) MD (REAL*8 ) : Mass flux down [Pa/s ] +! (6 ) DU (REAL*8 ) : Mass detraining from updraft [Pa/s ] +! (7 ) EU (REAL*8 ) : Mass entraining from updraft [Pa/s ] +! (8 ) ED (REAL*8 ) : Mass entraining from downdraft [Pa/s ] +! (9 ) DP (REAL*8 ) : Delta pressure between interfaces [Pa ] +! (10) DSUBCLD (REAL*8 ) : Delta pressure from cloud base to sfc +! (11) JT (INTEGER) : Index of cloud top for each column +! (12) MX (INTEGER) : Index of cloud top for each column +! (13) IDEEP (INTEGER) : Gathering array +! (14) IL1G (INTEGER) : Gathered min lon indices over which to operate +! (15) IL2G (INTEGER) : Gathered max lon indices over which to operate +! (16) NSTEP (INTEGER) : Time step index +! (17) DELT (REAL*8 ) : Time step +! (18) FRACIS (REAL*8 ) : Fraction of tracer that is insoluble +! (19) TCVV (REAL*8 ) : Ratio of air mass / tracer mass +! (20) INDEXSOL (INTEGER) : Index array of soluble tracer numbers +! +! Arguments as Output: +! ============================================================================ +! (1 ) Q (REAL*8 ) : Contains modified tracer mixing ratios [v/v] +! +! Important Local Variables: +! ============================================================================ +! (1 ) CABV (REAL*8 ) : Mixing ratio of constituent above +! (2 ) CBEL (REAL*8 ) : Mix ratio of constituent beloqw +! (3 ) CDIFR (REAL*8 ) : Normalized diff between cabv and cbel +! (4 ) CHAT (REAL*8 ) : Mix ratio in env at interfaces +! (5 ) CMIX (REAL*8 ) : Gathered tracer array +! (6 ) COND (REAL*8 ) : Mix ratio in downdraft at interfaces +! (7 ) CONU (REAL*8 ) : Mix ratio in updraft at interfaces +! (8 ) DCONDT (REAL*8 ) : Gathered tend array +! (9 ) FISG (REAL*8 ) : gathered insoluble fraction of tracer +! (10) KBM (INTEGER) : Highest altitude index of cloud base [unitless] +! (11) KTM (INTEGER) : Hightet altitude index of cloud top [unitless] +! (12) MBSTH (REAL*8 ) : Threshold for mass fluxes +! (13) SMALL (REAL*8 ) : A small number +! +! NOTES: +! (1 ) Now dimension Q and FRACIS of size (IIPAR,JJPAR,LLPAR,NTRACE), in +! order to avoid seg faults with OpenMP. Also renamed GEOS-CHEM +! latitude index LATI_INDEX to J. Added comments. (bmy, 12/13/05) +! (2 ) Bug fix: avoid div by zero in formula for CHAT (bmy, 12/19/06) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : AD38, CONVFLUP + USE GRID_MOD, ONLY : GET_AREA_M2 + USE DAO_MOD, ONLY : AD + USE PRESSURE_MOD, ONLY : GET_PEDGE + +# include "CMN_SIZE" ! Size parameters +# include "CMN_DIAG" + + ! Arguments + INTEGER, INTENT(IN) :: J + INTEGER, INTENT(IN) :: NTRACE + REAL*8, INTENT(INOUT) :: Q(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: MU(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: MD(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: DU(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: EU(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: TOTALMD(IIPAR,LLPAR) + REAL*8, INTENT(IN) :: DP(IIPAR,LLPAR) + INTEGER, INTENT(IN) :: JT(IIPAR) + INTEGER, INTENT(IN) :: MX(IIPAR) + INTEGER, INTENT(IN) :: IDEEP(IIPAR) + INTEGER, INTENT(IN) :: IL1G + INTEGER, INTENT(IN) :: IL2G + INTEGER, INTENT(IN) :: NSTEP + REAL*8, INTENT(IN) :: DELT + REAL*8, INTENT(IN) :: FRACIS(IIPAR,JJPAR,LLPAR,NTRACE) + REAL*8, INTENT(IN) :: TCVV(NTRACE) + INTEGER, INTENT(IN) :: INDEXSOL(NTRACE) + + ! Local variables + INTEGER :: I, K, KBM, KK, KKP1 + INTEGER :: KM1, KP1, KTM, M, ISTEP + INTEGER :: II, JJ, LL, NN + REAL*8 :: CABV, CBEL, CDIFR, CD2, DENOM + REAL*8 :: SMALL, MBSTH, MUPDUDP, MINC, MAXC + REAL*8 :: QN, FLUXIN, FLUXOUT, NETFLUX + REAL*8 :: CHAT(IIPAR,LLPAR) + REAL*8 :: COND(IIPAR,LLPAR) + REAL*8 :: CMIX(IIPAR,LLPAR) + REAL*8 :: FISG(IIPAR,LLPAR) + REAL*8 :: CONU(IIPAR,LLPAR) + REAL*8 :: DCONDT(IIPAR,LLPAR) + REAL*8 :: AREA_M2, DELTAP + REAL*8 :: TRC_BFCONVTRAN, TRC_AFCONVTRAN + REAL*8 :: PLUMEIN, PLUMEOUT, PLUMECHANGE + + !================================================================= + ! CONVTRAN begins here! + !================================================================= + + ! A small number + SMALL = 1.d-36 + + ! Threshold below which we treat the mass fluxes as zero (in mb/s) + MBSTH = 1.d-15 + + !================================================================= + ! Find the highest level top and bottom levels of convection + !================================================================= + KTM = LLPAR + KBM = LLPAR + DO I = IL1G, IL2G + KTM = MIN( KTM, JT(I) ) + KBM = MIN( KBM, MX(I) ) + ENDDO + + ! Loop ever each tracer + DO M = 1, NTRACE + + ! Gather up the tracer and set tend to zero + DO K = 1, LLPAR + DO I = IL1G, IL2G + CMIX(I,K) = Q(IDEEP(I),J,K,M) + FISG(I,K) = FRACIS(IDEEP(I),J,K,M) + ENDDO + ENDDO + + !============================================================== + ! From now on work only with gathered data + ! Interpolate environment tracer values to interfaces + !============================================================== + DO K = 1, LLPAR + KM1 = MAX(1,K-1) + + DO I = IL1G, IL2G + + MINC = MIN( CMIX(I,KM1), CMIX(I,K) ) + MAXC = MAX( CMIX(I,KM1), CMIX(I,K) ) + + IF ( MINC < 0 ) THEN + CDIFR = 0.D0 + ELSE + CDIFR = ABS( CMIX(I,K)-CMIX(I,KM1) ) / MAX(MAXC,SMALL) + ENDIF + + IF ( CDIFR > 1.D-6 ) THEN + + ! If the two layers differ significantly. + ! use a geometric averaging procedure + CABV = MAX( CMIX(I,KM1), MAXC*TINYNUM, SMALLEST ) + CBEL = MAX( CMIX(I,K), MAXC*TINYNUM, SMALLEST ) + + ! If CABV-CBEL is zero then set CHAT=SMALLEST + ! so that we avoid div by zero (bmy, 12/19/06) + IF ( ABS( CABV - CBEL ) > 0d0 ) THEN + CHAT(I,K) = LOG( CABV / CBEL ) + & / ( CABV - CBEL ) + & * CABV * CBEL + ELSE + CHAT(I,K) = SMALLEST + ENDIF + + ELSE + + ! If CDFIR <= 1d6, just use arithmetic mean + CHAT(I,K) = 0.5d0 * ( CMIX(I,K) + CMIX(I,KM1) ) + + ENDIF + + ! Provisional up and down draft values + CONU(I,K) = CHAT(I,K) + COND(I,K) = CHAT(I,K) + + ! Provisional tends + DCONDT(I,K) = 0.d0 + ENDDO + ENDDO + + !============================================================== + ! Do levels adjacent to top and bottom + !============================================================== + K = 2 + KM1 = 1 + KK = LLPAR + + DO I = IL1G, IL2G + PLUMEIN = MU(I,KK) + + IF ( PLUMEIN > MBSTH ) THEN + CONU(I,KK) = CMIX(I,KK) + ENDIF + + IF ( MD(I,K) < -MBSTH ) THEN + COND(I,K) = 0.5d0 * ( CMIX(I,KM1) + CONU(I,KM1) ) + ENDIF + ENDDO + + !============================================================== + ! Updraft from bottom to top + !============================================================== + DO KK = LLPAR-1,1,-1 + KKP1 = MIN( LLPAR, KK+1 ) + + DO I = IL1G, IL2G + PLUMEIN = MU(I,KKP1) + EU(I,KK) + PLUMEOUT = MU(I,KK) + DU(I,KK) - 0.5D0*MD(I,KK) + PLUMECHANGE = PLUMEOUT - PLUMEIN + + IF ( PLUMECHANGE > MBSTH ) THEN + IF ( PLUMEOUT > MBSTH ) THEN + CONU(I,KK) = (MU(I,KKP1)*CONU(I,KKP1) *FISG(I,KK) + & + EU(I,KK)*CMIX(I,KK) + & + PLUMECHANGE*CMIX(I,KK) ) + & / PLUMEOUT + ENDIF + + ELSE + IF ( PLUMEIN > MBSTH ) THEN + CONU(I,KK) = ( MU(I,KKP1)*CONU(I,KKP1) *FISG(I,KK) + & + EU(I,KK)*CMIX(I,KK) ) + & / PLUMEIN + ENDIF + ENDIF + + IF ( CONU(I,KK) < 0.0D0 ) THEN + WRITE(6,*) 'Warning! negative conu!!!', conu(I,KK) + CALL FLUSH(6) + !ELSE IF ( CONU(I,KK) > 1.0e-10 ) THEN + ! write(6,*) 'Warning! Too big conu!!!', conu(I,KK) + ! call flush(6) + ENDIF + ENDDO + ENDDO + + !============================================================== + ! Downdraft from top to bottom + !============================================================== + DO K = 3, LLPAR + KM1 = MAX( 1, K-1 ) + + DO I = IL1G, IL2G + + IF ( TOTALMD(I,K) < -MBSTH ) THEN + IF ( MD(I,K) < -MBSTH ) THEN + COND(I,K) = ( TOTALMD(I,KM1)*COND(I,KM1) + $ + 0.5D0 * MD(I,K) * ( CMIX(I,K)+CONU(I,K) )) + $ / TOTALMD(I,K) + ELSE + COND(I,K) = COND(I,KM1) + ENDIF + ENDIF + + IF ( COND(I,K) < 0.0D0 ) THEN + WRITE(6,*) 'WARNING! negative cond!!!', cond(I,K) + CALL FLUSH(6) + !ELSE IF ( COND(I,K) > 1.0e-10 ) THEN + ! write(6,*) 'Warning! Too big cond!!!', cond(I,K) + ! call flush(6) + ENDIF + ENDDO + ENDDO + + DO K = 1, LLPAR + KM1 = MAX( 1, K-1 ) + KP1 = MIN( LLPAR, K+1 ) + + DO I = IL1G, IL2G + + ! Version 3 limit fluxes outside convection to mass in + ! appropriate layer. These limiters are probably only safe + ! for positive definite quantitities. It assumes that mu + ! and md already satify a courant number limit of 1 + +! FLUXIN = MU(I,KP1)* CONU(I,KP1) * FISG(I,K) +! $ + (MU(I,K)+ totalMD(I,K)) * CMIX(I,KM1) +! $ - totalMD(I,K) * COND(I,K) +! +! FLUXOUT = MU(I,K) * CONU(I,K) +! $ + (MU(I,KP1)+ totalMD(I,KP1))*CMIX(I,K) +! $ - totalMD(I,KP1) * COND(I,KP1) + + IF ( K == LLPAR ) THEN + + FLUXIN = MU(I,K) * CMIX(I,KM1) + & - TOTALMD(I,KM1) * COND(I,KM1) + + FLUXOUT = MU(I,K) * CONU(I,K) + & - TOTALMD(I,KM1) * CMIX(I,K) + + ELSE + + FLUXIN = MU(I,KP1) * CONU(I,KP1) * FISG(I,K) + & + MU(I,K) * CMIX(I,KM1) + & - TOTALMD(I,KM1) * COND(I,KM1) + & - TOTALMD(I,K) * CMIX(I,KP1) * FISG(I,K) + + FLUXOUT = MU(I,K) * CONU(I,K) + & + MU(I,KP1) * CMIX(I,K) + & - TOTALMD(I,K) * COND(I,K) + & - TOTALMD(I,KM1) * CMIX(I,K) + ENDIF + +!!!!!!!!!!!!!!!!!!!backup: also works OK !!!!!!!!!!!!!!!!!!!!!!! +!! FLUXIN = MU(I,KP1)* CONU(I,KP1) +!! $ + MU(I,K) * 0.5d0*(CHAT(I,K)+CMIX(I,KM1)) +!! $ - MD(I,K) * COND(I,K) +!! $ - MD(I,KP1)* 0.5d0*(CHAT(I,KP1)+CMIX(I,KP1)) +!! +!! FLUXOUT = MU(I,K) * CONU(I,K) +!! $ + MU(I,KP1) * 0.5d0*(CHAT(I,KP1)+CMIX(I,K)) +!! $ - MD(I,KP1) * COND(I,KP1) +!! $ - MD(I,K) * 0.5d0*(CHAT(I,K)+CMIX(I,K)) +!! +!! FLUXIN = MU(I,KP1)* CONU(I,KP1) +!! $ + MU(I,K) * CHAT(I,K) +!! $ - MD(I,K) * COND(I,K) +!! $ - MD(I,KP1)* CHAT(I,KP1) +!! +!! FLUXOUT = MU(I,K) * CONU(I,K) +!! $ + MU(I,KP1) * CHAT(I,KP1) +!! $ - MD(I,KP1) * COND(I,KP1) +!! $ - MD(I,K) * CHAT(I,K) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + !================================================== + ! ND38 Diagnostic: loss of soluble tracer to wet + ! scavenging in cloud updrafts [kg/s]. + !================================================== + NN = INDEXSOL(M) + + IF ( ND38 > 0 .and. NN > 0 ) THEN + + ! Grid box indices + II = IDEEP(I) + JJ = J + LL = LLPAR - K + 1 + + ! Grid box surface area [m2] + AREA_M2 = GET_AREA_M2( JJ ) + + ! Save into AD38 array [kg/s] + AD38(II,JJ,LL,NN) = AD38(II,JJ,LL,NN) + & + MU(I,KP1) * AREA_M2 / GRAV * CONU(I,KP1) + & * (1-FISG(I,K)) / TCVV(M) / FLOAT(NSTEP) + & - TOTALMD(I,K) * AREA_M2 / GRAV * CMIX(I,KP1) + & * (1-FISG(I,K)) / TCVV(M) / FLOAT(NSTEP) + ENDIF + + IF ( ND14 > 0 ) THEN + II = IDEEP(I) + JJ = J + LL = LLPAR - K + 1 + + ! Grid box surface area [m2] + AREA_M2 = GET_AREA_M2( JJ ) + + CONVFLUP(II,JJ,LL,M) = CONVFLUP(II,JJ,LL,M) + & + MU(I,K) * AREA_M2 * (CONU(I,K)-CMIX(I,KM1)) + & / GRAV / TCVV(M) / FLOAT(NSTEP) + & - TOTALMD(I,KM1) * AREA_M2 * (CMIX(I,K)-COND(I,KM1)) + & / GRAV / TCVV(M) / FLOAT(NSTEP) + + ENDIF + + NETFLUX = FLUXIN - FLUXOUT + + IF ( DP(I,K)< 0.0D0 ) THEN + WRITE(6,*) 'WARNING! negative DP!!!', DP(I,K) + CALL FLUSH(6) + ENDIF + + + DCONDT(I,K)= NETFLUX/DP(I,K) !AD(IDEEP(I),lati_index,llpar+1-k) + ENDDO !I + ENDDO !K + + + DO K = KBM, LLPAR + KM1 = MAX( 1, K-1 ) + + DO I = IL1G, IL2G + + !!!temp diag ATTENTION HERE!!!! + + IF ( K == (MX(I) + 100000) ) THEN + + FLUXIN =(MU(I,K)+MD(I,K))* CMIX(I,KM1) + $ - MD(I,K)*COND(I,K) + + FLUXOUT = MU(I,K)*CONU(I,K) + +!!!!!!!!!!!!!!!!!!!!!!BACK UP; also works well !!!!!!!!!!!!!!!!!!!!! +! FLUXIN = MU(I,K)*0.5d0*(CHAT(I,K)+CMIX(I,KM1)) +! $ - MD(I,K)*COND(I,K) +! +! FLUXOUT = MU(I,K)*CONU(I,K) +! $ - MD(I,K)*0.5d0*(CHAT(I,K)+CMIX(I,K)) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + + NETFLUX = FLUXIN - FLUXOUT + + IF (ABS(NETFLUX).LT.MAX(FLUXIN,FLUXOUT)*TINYNUM) THEN + NETFLUX = 0.d0 + ENDIF + + DCONDT(I,K) = NETFLUX / DP(I,K) + + ELSE IF ( K > MX(I) ) THEN + + !!!!DCONDT(I,K) = 0.D0 + + ENDIF + + ENDDO !I + ENDDO !K + + !============================================================== + ! Update and scatter data back to full arrays + !============================================================== + DO K = 1, LLPAR + KP1 = MIN( LLPAR, K+1 ) + DO I = IL1G, IL2G + + QN = CMIX(I,K) + DCONDT(I,K) * DELT + + ! Do not make Q negative!!! + IF ( QN < 0d0 ) then + QN = 0D0 + ENDIF + + Q(IDEEP(I),J,K,M) = QN + ENDDO + ENDDO + + ENDDO ! End of tracer loop + + ! Return to calling program + END SUBROUTINE CONVTRAN + +!----------------------------------------------------------------------------- + + SUBROUTINE WHENFGT( N, ARRAY, INC, TARGET, INDEX, NVAL ) +! +!****************************************************************************** +! Subroutine WHENFGT is a +! +! Arguments as Input: +! ============================================================================ +! +!****************************************************************************** +! + ! Arguments + INTEGER :: INDEX(*), NVAL, INC, N + REAL*8 :: ARRAY(*), TARGET + + ! Local variables + INTEGER :: I, INA + + !================================================================= + ! WHENFGT begins here! + !================================================================= + INA = 1 + NVAL = 0 + + IF ( INC < 0 ) INA = (-INC)*(N-1)+1 + + DO I = 1, N + IF ( ARRAY(INA) > TARGET ) THEN + NVAL = NVAL+1 + INDEX(NVAL) = I + ENDIF + INA = INA + INC + ENDDO + + ! Return to calling program + END SUBROUTINE WHENFGT + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE GCAP_CONVECT_MOD diff --git a/code/gcap_read_mod.f b/code/gcap_read_mod.f new file mode 100644 index 0000000..2ebee57 --- /dev/null +++ b/code/gcap_read_mod.f @@ -0,0 +1,547 @@ +! $Id: gcap_read_mod.f,v 1.1 2009/06/09 21:51:52 daven Exp $ + MODULE GCAP_READ_MOD +! +!****************************************************************************** +! Module PHIS_READ_MOD contains subroutines that unzip, open, and read the +! GCAP PHIS and LWI_GISS fields from disk. (bmy, swu, 2/1/06) +! +! Module Routines: +! ============================================================================ +! (1 ) UNZIP_GCAP_FIELDS : Unzips & copies met field files to a temp dir +! (2 ) OPEN_GCAP_FIELDS : Opens met field files residing in the temp dir +! (3 ) GET_GCAP_FIELDS : Wrapper for routine READ_I6 +! (4 ) CHECK_TIME : Tests if met field timestamps equal current time +! (5 ) READ_GCAP : Reads PHIS fields from disk +! (6 ) GCAP_CHECK : Checks if we have found all the PHIS field +! +! GEOS-CHEM modules referenced by phis_read_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module w/ routines for binary punch file I/O +! (2 ) dao_mod.f : Module w/ arrays for DAO met fields +! (3 ) diag_mod.f : Module w/ GEOS-CHEM diagnostic arrays +! (4 ) directory_mod.f : Module w/ GEOS-CHEM data & met field dirs +! (5 ) error_mod.f : Module w/ NaN and other error check routines +! (6 ) logical_mod.f : Module w/ GEOS-CHEM logical switches +! (7 ) file_mod.f : Module w/ file unit #'s and error checks +! (8 ) time_mod.f : Module w/ routines for computing time & date +! (9 ) transfer_mod.f : Module w/ routines to cast & resize arrays +! (10) unix_cmds_mod.f : Module w/ Unix commands for unzipping +! +! NOTES: +! (1 ) Adapted from the obsolete "phis_read_mod.f" (bmy, 2/1/06) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE PRIVATE DECLARATIONS -- keep certain internal variables + ! and routines from being seen outside "gcap_read_mod.f" + !================================================================= + + ! Make everything PRIVATE ... + PRIVATE + + ! ... except these routines + PUBLIC :: GET_GCAP_FIELDS + PUBLIC :: OPEN_GCAP_FIELDS + PUBLIC :: UNZIP_GCAP_FIELDS + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE UNZIP_GCAP_FIELDS( OPTION ) +! +!****************************************************************************** +! Subroutine UNZIP_GCAP_FIELDS invokes a FORTRAN system call to uncompress +! GCAP PHIS met field files and store the uncompressed data in a +! temporary directory, where GEOS-CHEM can read them. The original data +! files are not disturbed. (bmy, bdf, 6/15/98, 5/25/05) +! +! Arguments as input: +! =========================================================================== +! (1 ) OPTION (CHAR*(*)) : Option +! +! NOTES: +! (1 ) Adapted from UNZIP_MET_FIELDS of "dao_read_mod.f" (bmy, 6/16/03) +! (2 ) Directory information YYYY/MM or YYYYMM is now contained w/in +! GEOS_1_DIR, GEOS_S_DIR, GEOS_3_DIR, GEOS_4_DIR (bmy, 12/11/03) +! (3 ) Now reference "directory_mod.f" and "unix_cmds_mod.f". Now prevent +! EXPAND_DATE from overwriting directory paths with Y/M/D tokens in +! them (bmy, 7/20/04) +! (4 ) Now modified for GEOS-5 and GCAP met fields (swu, bmy, 5/25/05) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD + USE ERROR_MOD, ONLY : ERROR_STOP + USE TIME_MOD, ONLY : EXPAND_DATE + USE UNIX_CMDS_MOD + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + CHARACTER(LEN=*), INTENT(IN) :: OPTION + + ! Local variables + INTEGER :: NYMD + CHARACTER(LEN=255) :: GEOS_DIR, PHIS_STR + CHARACTER(LEN=255) :: PHIS_FILE_GZ, PHIS_FILE + CHARACTER(LEN=255) :: UNZIP_BG, UNZIP_FG + CHARACTER(LEN=255) :: REMOVE_ALL, REMOVE_DATE + + !================================================================= + ! UNZIP_GCAP_FIELD begins here! + !================================================================= + + ! Date for PHIS field + NYMD = 20000101 + + ! Strings for directory & filename + GEOS_DIR = TRIM( GCAP_DIR ) + PHIS_STR = 'YYYYMMDD.phis.' // GET_RES_EXT() + + ! Replace date tokens + CALL EXPAND_DATE( GEOS_DIR, NYMD, 000000 ) + CALL EXPAND_DATE( PHIS_STR, NYMD, 000000 ) + + ! Location of zipped A-3 file in data dir + PHIS_FILE_GZ = TRIM( DATA_DIR ) // TRIM( GEOS_DIR ) // + & TRIM( PHIS_STR ) // TRIM( ZIP_SUFFIX ) + + ! Location of unzipped A-3 file in temp dir + PHIS_FILE = TRIM( TEMP_DIR ) // TRIM( PHIS_STR ) + + ! Remove A-3 files for this date from temp dir + REMOVE_DATE = TRIM( REMOVE_CMD ) // ' ' // + & TRIM( TEMP_DIR ) // TRIM( PHIS_STR ) + + !================================================================= + ! Define the foreground and background UNZIP commands + !================================================================= + + ! Foreground unzip + UNZIP_FG = TRIM( UNZIP_CMD ) // ' ' // TRIM( PHIS_FILE_GZ ) // + & TRIM( REDIRECT ) // ' ' // TRIM( PHIS_FILE ) + + ! Background unzip + UNZIP_BG = TRIM( UNZIP_FG ) // TRIM( BACKGROUND ) + + !================================================================= + ! Define command to remove all PHIS files from the TEMP dir + !================================================================= + REMOVE_ALL = TRIM( REMOVE_CMD ) // ' ' // TRIM( TEMP_DIR ) // + & TRIM( WILD_CARD ) //'.phis.'// TRIM( WILD_CARD ) + + !================================================================= + ! Perform an F90 system call to do the desired operation + !================================================================= + SELECT CASE ( TRIM( OPTION ) ) + + ! Unzip PHIS field in the Unix foreground + CASE ( 'unzip foreground' ) + WRITE( 6, 100 ) TRIM( PHIS_FILE_GZ ) + CALL SYSTEM( TRIM( UNZIP_FG ) ) + + ! Unzip PHIS field in the Unix background + CASE ( 'unzip background' ) + WRITE( 6, 100 ) TRIM( PHIS_FILE_GZ ) + CALL SYSTEM( TRIM( UNZIP_BG ) ) + + ! Remove A-3 field for this date in temp dir + CASE ( 'remove date' ) + WRITE( 6, 110 ) TRIM( PHIS_FILE ) + CALL SYSTEM( TRIM( REMOVE_DATE ) ) + + ! Remove all A-3 fields in temp dir + CASE ( 'remove all' ) + WRITE( 6, 120 ) TRIM( REMOVE_ALL ) + CALL SYSTEM( TRIM( REMOVE_ALL ) ) + + ! Error -- bad option! + CASE DEFAULT + CALL ERROR_STOP( 'Invalid value for OPTION!', + & 'UNZIP_PHIS_FIELDS (phis_read_mod.f)' ) + + END SELECT + + ! FORMAT strings + 100 FORMAT( ' - Unzipping: ', a ) + 110 FORMAT( ' - Removing: ', a ) + 120 FORMAT( ' - About to execute command: ', a ) + + ! Return to calling program + END SUBROUTINE UNZIP_GCAP_FIELDS + +!------------------------------------------------------------------------------ + + SUBROUTINE OPEN_GCAP_FIELDS +! +!****************************************************************************** +! Subroutine OPEN_GCAP_FIELDS opens the PHIS and LWI met fields file for +! date 2000/01/01. (swu, bmy, 2/1/06) +! +! NOTES: +! (1 ) Adapted from OPEN_MET_FIELDS of "dao_read_mod.f" (bmy, 6/13/03) +! (2 ) Now opens either zipped or unzipped files (bmy, 12/11/03) +! (3 ) Now skips past the GEOS-4 ident string (bmy, 12/12/04) +! (4 ) Now references "directory_mod.f" instead of CMN_SETUP. Also now +! references LUNZIP from "logical_mod.f". Also now prevents EXPAND_DATE +! from overwriting Y/M/D tokens in directory paths. (bmy, 7/20/04) +! (5 ) Now use FILE_EXISTS from "file_mod.f" to determine if file unit IU_PH +! refers to a valid file on disk (bmy, 3/23/05) +! (6 ) Now modified for GEOS-5 and GCAP met fields (swu, bmy, 5/25/05) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD + USE ERROR_MOD, ONLY : ERROR_STOP + USE LOGICAL_MOD, ONLY : LUNZIP + USE FILE_MOD, ONLY : IU_PH, IOERROR, FILE_EXISTS + USE TIME_MOD, ONLY : EXPAND_DATE + +# include "CMN_SIZE" ! Size parameters + + ! Local variables + LOGICAL, SAVE :: FIRST = .TRUE. + LOGICAL :: IT_EXISTS + INTEGER :: NYMD, NHMS + INTEGER :: IOS, IUNIT + CHARACTER(LEN=8) :: IDENT + CHARACTER(LEN=255) :: GEOS_DIR + CHARACTER(LEN=255) :: PHIS_FILE + CHARACTER(LEN=255) :: PATH + + !================================================================= + ! OPEN_PHIS_FIELDS begins here! + !================================================================= + + ! Define date and hour + NYMD = 20000101 + NHMS = 000000 + + ! Open the A-3 file 0 GMT of each day, or on the first call + IF ( NHMS == 000000 .or. FIRST ) THEN + + ! Strings for directory & filename + GEOS_DIR = TRIM( GCAP_DIR ) + PHIS_FILE = 'YYYYMMDD.phis.' // GET_RES_EXT() + + ! Replace date tokens + CALL EXPAND_DATE( GEOS_DIR, NYMD, NHMS ) + CALL EXPAND_DATE( PHIS_FILE, NYMD, NHMS ) + + ! If unzipping, open GEOS-1 file in TEMP dir + ! If not unzipping, open GEOS-1 file in DATA dir + IF ( LUNZIP ) THEN + PATH = TRIM( TEMP_DIR ) // TRIM( PHIS_FILE ) + ELSE + PATH = TRIM( DATA_DIR ) // + & TRIM( GEOS_DIR ) // TRIM( PHIS_FILE ) + ENDIF + + ! Close previously opened A-3 file + CLOSE( IU_PH ) + + ! Make sure the file unit is valid before we open the file + IF ( .not. FILE_EXISTS( IU_PH ) ) THEN + CALL ERROR_STOP( 'Could not find file!', + & 'OPEN_PHIS_FIELD (phis_read_mod.f)' ) + ENDIF + + ! Open the file + OPEN( UNIT = IU_PH, FILE = TRIM( PATH ), + & STATUS = 'OLD', ACCESS = 'SEQUENTIAL', + & FORM = 'UNFORMATTED', IOSTAT = IOS ) + + IF ( IOS /= 0 ) THEN + CALL IOERROR( IOS, IU_PH, 'open_phis_fields:1' ) + ENDIF + + ! Echo info + WRITE( 6, 100 ) TRIM( PATH ) + 100 FORMAT( ' - Opening: ', a ) + + ! Set the proper first-time-flag false + FIRST = .FALSE. + + ! Skip past the GEOS-4 ident string + READ( IU_PH, IOSTAT=IOS ) IDENT + + IF ( IOS /= 0 ) THEN + CALL IOERROR( IOS, IU_PH, 'open_phis_fields:2' ) + ENDIF + ENDIF + + ! Return to calling program + END SUBROUTINE OPEN_GCAP_FIELDS + +!------------------------------------------------------------------------------ + + SUBROUTINE GET_GCAP_FIELDS +! +!****************************************************************************** +! Subroutine GET_GCAP_FIELDS is a wrapper for routine READ_PHIS. This routine +! calls READ_PHIS properly for reading PHIS fields from GEOS-1, GEOS-STRAT, +! GEOS-3, or GEOS-4 met data sets at the START of a GEOS-CHEM run. +! (bmy, swu, 2/1/06) +! +! NOTES: +! (1 ) Now also read LWI_GISS for GCAP met fields (swu, bmy, 5/25/05) +!****************************************************************************** +! + ! References to F90 modules + USE DAO_MOD, ONLY : PHIS, LWI_GISS + + ! Local variables + INTEGER :: NYMD, NHMS + + !================================================================= + ! GET_PHIS_FIELD begins here! + !================================================================= + + ! Date and time + NYMD = 20000101 + NHMS = 000000 + + ! For GCAP met fields: read PHIS and LWI_GISS + CALL READ_GCAP( NYMD=NYMD, NHMS=NHMS, PHIS=PHIS, LWI=LWI_GISS ) + + ! Return to calling program + END SUBROUTINE GET_GCAP_FIELDS + +!--------------------------------------------------------------------------- + + FUNCTION CHECK_TIME( XYMD, XHMS, NYMD, NHMS ) RESULT( ITS_TIME ) +! +!****************************************************************************** +! Function CHECK_TIME checks to see if the timestamp of the A-3 field just +! read from disk matches the current time. If so, then it's time to return +! the A-3 field to the calling program. (bmy, 6/16/03) +! +! Arguments as Input: +! ============================================================================ +! (1 ) XYMD (REAL*4 or INTEGER) : (YY)YYMMDD timestamp for A-3 field in file +! (2 ) XHMS (REAL*4 or INTEGER) : HHMMSS timestamp for A-3 field in file +! (3 ) NYMD (INTEGER ) : YYYYMMDD at which A-3 field is to be read +! (4 ) NHMS (INTEGER ) : HHMMSS at which A-3 field is to be read +! +! NOTES: +!****************************************************************************** +! +# include "CMN_SIZE" + + ! Arguments + INTEGER, INTENT(IN) :: XYMD, XHMS, NYMD, NHMS + + ! Function value + LOGICAL :: ITS_TIME + + !================================================================= + ! GEOS-3, GEOS-4: XYMD and XHMS are integers + !================================================================= + IF ( XYMD == NYMD .AND. XHMS == NHMS ) THEN + ITS_TIME = .TRUE. + ELSE + ITS_TIME = .FALSE. + ENDIF + + ! Return to calling program + END FUNCTION CHECK_TIME + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_GCAP( NYMD, NHMS, PHIS, LWI ) +! +!****************************************************************************** +! Subroutine READ_PHIS reads DAO PHIS (surface geopotential heights) field +! from disk. PHIS is an I-6 field, but is time-independent. Thus READ_PHIS +! only needs to be called once at the beginning of the model run. +! (bmy, swu, 2/1/06) +! +! Arguments as input: +! ============================================================================ +! (1 ) NYMD : YYMMDD +! (2 ) NHMS : and HHMMSS of PHIS field to be read from disk +! +! Arguments as output: +! ============================================================================ +! (3 ) PHIS : DAO field for surface geopotential height (= g0 * m) +! in units of m^2 / s^2, where g0 = 9.8 m / s^2. +! +! NOTES: +! (1 ) Adapted from READ_PHIS from "dao_read_mod.f" (bmy, 6/16/03) +! (2 ) Now use function TIMESTAMP_STRING from "time_mod.f" for formatted +! date/time output. (bmy, 10/28/03) +! (3 ) Now also read LWI_GISS for GCAP met fields. Added optional variable +! LWI to the arg list. (swu, bmy, 5/25/05) +!****************************************************************************** +! + ! References to F90 modules + USE DIAG_MOD, ONLY : AD67 + USE FILE_MOD, ONLY : IOERROR, IU_PH + USE TIME_MOD, ONLY : TIMESTAMP_STRING + USE TRANSFER_MOD, ONLY : TRANSFER_2D + +# include "CMN_SIZE" ! Size parameters +# include "CMN_GCTM" ! g0 +# include "CMN_DIAG" ! ND67 + + ! Arguments + INTEGER, INTENT(IN) :: NYMD, NHMS + REAL*8, INTENT(OUT) :: PHIS(IIPAR,JJPAR) + REAL*8, INTENT(OUT), OPTIONAL :: LWI(IIPAR,JJPAR) + + ! Local Variables + INTEGER :: NFOUND, IOS + INTEGER :: XYMD, XHMS + REAL*4 :: Q2(IGLOB,JGLOB) + CHARACTER(LEN=8) :: NAME + CHARACTER(LEN=16) :: STAMP + + ! Number of fields in the file + INTEGER, PARAMETER :: N_PHIS = 2 + + !================================================================= + ! READ_PHIS begins here! + !================================================================= + + ! Zero number of PHIS fields we have found + NFOUND = 0 + + !================================================================= + ! Read PHIS field from disk + !================================================================= + DO + + ! PHIS field name + READ( IU_PH, IOSTAT=IOS ) NAME + + ! IOS < 0: EOF, but make sure we have found everything + IF ( IOS < 0 ) THEN + CALL GCAP_CHECK( NFOUND, N_PHIS ) + EXIT + ENDIF + + ! IOS > 0: True I/O error + IF ( IOS > 0 ) CALL IOERROR( IOS, IU_PH, 'read_phis:1' ) + + ! CASE statement for met fields + SELECT CASE ( TRIM( NAME ) ) + + !--------------------------------- + ! PHIS: geopotential heights + !--------------------------------- + CASE ( 'PHIS' ) + READ( IU_PH, IOSTAT=IOS ) XYMD, XHMS, Q2 + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_PH, 'read_phis:2' ) + + IF ( CHECK_TIME( XYMD, XHMS, NYMD, NHMS ) ) THEN + CALL TRANSFER_2D( Q2, PHIS ) + NFOUND = NFOUND + 1 + ENDIF + + !--------------------------------- + ! LWI_GISS: GCAP land/water flags + !--------------------------------- + CASE ( 'LWI', 'LWI_GISS' ) + READ( IU_PH, IOSTAT=IOS ) XYMD, XHMS, Q2 + IF ( IOS /= 0 ) CALL IOERROR( IOS, IU_PH, 'read_phis:3' ) + + IF ( CHECK_TIME( XYMD, XHMS, NYMD, NHMS ) ) THEN + IF ( PRESENT( LWI ) ) CALL TRANSFER_2D( Q2, LWI ) + NFOUND = NFOUND + 1 + ENDIF + + !-------------------------------- + ! Field not found + !-------------------------------- + CASE DEFAULT + WRITE( 6, '(a)' ) 'Searching for next field!' + END SELECT + + !============================================================== + ! If we have found all the fields for this time, then exit + ! the loop. Otherwise, go on to the next iteration. + !============================================================== + IF ( CHECK_TIME( XYMD, XHMS, NYMD, NHMS ) .AND. + & NFOUND == N_PHIS ) THEN + STAMP = TIMESTAMP_STRING( NYMD, NHMS ) + WRITE( 6, 200 ) STAMP + 200 FORMAT( ' - Found PHIS met fields for ', a ) + EXIT + ENDIF + ENDDO + + !================================================================= + ! Divide PHIS by 9.8 m / s^2 to obtain surface heights in meters. + ! + ! ND67 diagnostic: Accumulating DAO surface fields: + ! Field #15 in the ND67 diagnostic is the geopotential heights + !================================================================= + PHIS = PHIS / g0 + + IF ( ND67 > 0 ) THEN + AD67(:,:,15) = AD67(:,:,15) + PHIS + ENDIF + + ! Since we only read PHIS at the start of the run, + ! close the file unit (bmy, 6/16/03) + CLOSE( IU_PH ) + + ! Return to calling program + END SUBROUTINE READ_GCAP + +!------------------------------------------------------------------------------ + + SUBROUTINE GCAP_CHECK( NFOUND, N_PHIS ) +! +!****************************************************************************** +! Subroutine PHIS_CHECK prints an error message if not all of the A-3 met +! fields are found. The run is also terminated. (bmy, 10/27/00, 6/16/03) +! +! Arguments as Input: +! ============================================================================ +! (1 ) NFOUND (INTEGER) : # of met fields read from disk +! (2 ) N_PHIS (INTEGER) : # of met fields expected to be read from disk +! +! NOTES +! (1 ) Adapted from DAO_CHECK from "dao_read_mod.f" (bmy, 6/16/03) +!****************************************************************************** +! + ! References to F90 modules + USE ERROR_MOD, ONLY : GEOS_CHEM_STOP + + ! Arguments + INTEGER, INTENT(IN) :: NFOUND, N_PHIS + + !================================================================= + ! PHIS_CHECK begins here! + !================================================================= + IF ( NFOUND /= N_PHIS ) THEN + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + WRITE( 6, '(a)' ) 'ERROR -- not enough PHIS fields found!' + + WRITE( 6, 120 ) N_PHIS, NFOUND + 120 FORMAT( 'There are ', i2, ' fields but only ', i2 , + & ' were found!' ) + + WRITE( 6, '(a)' ) '### STOP in PHIS_CHECK (dao_read_mod.f)' + WRITE( 6, '(a)' ) REPEAT( '=', 79 ) + + ! Deallocate arrays and stop (bmy, 10/15/02) + CALL GEOS_CHEM_STOP + ENDIF + + ! Return to calling program + END SUBROUTINE GCAP_CHECK + +!------------------------------------------------------------------------------ + + ! End of module + END MODULE GCAP_READ_MOD diff --git a/code/geia_mod.f b/code/geia_mod.f new file mode 100644 index 0000000..2481238 --- /dev/null +++ b/code/geia_mod.f @@ -0,0 +1,1113 @@ +! $Id: geia_mod.f,v 1.1 2009/06/09 21:51:51 daven Exp $ + MODULE GEIA_MOD +! +!****************************************************************************** +! Module GEIA_MOD contains routines used to read and scale the GEIA fossil +! fuel emissions for NOx, CO, and hydrocarbons (bmy, 7/28/00, 11/6/08) +! +! Module Routines: +! ============================================================================ +! (1 ) READ_TOTCO2 : reads total CO2 scale factors (for FF NOx) +! (2 ) READ_LIQCO2 : reads liquid CO2 scale factors (for CO, HC's) +! (3 ) READ_TODX : reads "time-of-day" scale factors for GEIA em's +! (4 ) READ_GEIA_ASCII : reads GEIA fossil fuel emissions from ASCII file +! (5 ) READ_GEIA : reads GEIA fossil fuel emissions from binary file +! (6 ) READ_C3H8_C2H6_NGAS : reads C2H6 and C3H8 based on Natural Gas em's +! (7 ) GET_DAY_INDEX : Determines if today is a weekday, Sat., or Sun. +! (8 ) GET_IHOUR : Returns index for the "time-of-day" scale factor +! (9 ) TOTAL_FOSSIL_TG : Computes total fossil fuel emissions in Tg +! +! GEOS-CHEM modules referenced by geia_mod.f +! ============================================================================ +! (1 ) bpch2_mod.f : Module containing routines for binary punch file I/O +! (2 ) directory_mod.f : Module containing GEOS-CHEM data & met field dirs +! (3 ) file_mod.f : Module containing file unit numbers and error checks +! (4 ) grid_mod.f : Module containing horizontal grid information +! +! NOTES: +! (1 ) Renamed original READ_GEIA to READ_GEIA_ASCII. The new READ_GEIA +! now reads fossil fuel emissions from the newer binary punch +! file format. (bmy, 4/23/01) +! (2 ) Added new routine TOTAL_FOSSIL_TG (bmy, 4/27/01) +! (3 ) Bug fix: now read C2H6 from punch file correctly (bmy, 7/2/01) +! (4 ) Added new routine: READ_C3H8_C2H6_NGAS. Also updated comments. +! (bmy, 9/4/01) +! (5 ) Deleted obsolete code from 9/01 (bmy, 11/15/01) +! (6 ) Now read scalefoss* files directly from the DATA_DIR filesystem, +! instead of relying on symbolic links. Also updated comments. +! (bmy, 1/25/02) +! (7 ) Eliminated obsolete code (bmy, 2/27/02) +! (8 ) Routine READ_TODX now reads files from DATA_DIR/fossil_200104/, and +! routine READ_GEIA_ASCII now reads files from DATA_DIR/fossil_obsolete. +! This eliminates the need for symbolic file links. (bmy, 4/3/02) +! (9 ) Updated comments (bmy, 5/28/02) +! (10) Now references "file_mod.f" (bmy, 6/27/02) +! (11) Now references "grid_mod.f" and the new "time_mod.f" (bmy, 2/10/03) +! (12) Now references "directory_mod.f" (bmy, 7/20/04) +! (13) Now can read data from both GEOS and GCAP grids (bmy, 8/16/05) +! (14) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05) +! (15) Modifications for 0.5 x 0.666 nested grids (yxw, dan, bmy, 11/6/08) +!****************************************************************************** +! + IMPLICIT NONE + + !================================================================= + ! MODULE ROUTINES -- follow below the "CONTAINS" statement + !================================================================= + CONTAINS + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_TOTCO2( SCALEYEAR, TOTCO2 ) +! +!****************************************************************************** +! Subroutine READ_TOTCO2 reads in the scale factors (SCALEYEAR/1985) based +! on total CO2 emissions. These are used to scale anthropogenic NOx +! emissions from 1985 to the present. (bmy, 9/13/00, 7/20/04) +! +! NOTES: +! (1 ) Now use IOS /= 0 to trap both I/O errors and EOF. (bmy, 9/13/00) +! (2 ) Make sure parentheses end before column 73 (bmy, 9/25/00) +! (3 ) Now read the "scalefoss.tot*" files directly from the +! scalefoss_200202/ subdirectory of DATA_DIR, w/o relying on +! symbolic links. Also updated comments. (bmy, 1/24/02) +! (4 ) Eliminated obsolete code from 1/02 (bmy, 2/27/02) +! (5 ) Now write file name to stdout (bmy, 4/3/02) +! (6 ) Now use IU_FILE instead of IUNIT. Also reference IU_FILE and IOERROR +! from "file_mod.f" (bmy, 6/27/02) +! (7 ) Now use ENCODE to define CYEAR string for PGI/Linux (bmy, 9/29/03) +! (8 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : IU_FILE, IOERROR + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: SCALEYEAR + REAL*4, INTENT(OUT) :: TOTCO2(IGLOB,JGLOB) + + ! Local variables + INTEGER :: I, J, IX, JX, IOS + CHARACTER(LEN=4 ) :: CYEAR + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_TOTCO2 begins here! + !================================================================= + WRITE( 6, 10 ) SCALEYEAR + 10 FORMAT( 'READ_TOTCO2: Year for Total CO2 scale factor: ', i4 ) + + ! Define the file name and the file unit + ! Now use ENCODE for PGI/F90 on Linux (bmy, 9/29/03) +#if defined( LINUX ) + ENCODE( 4, '(i4)', CYEAR ) SCALEYEAR +#else + WRITE( CYEAR, '(i4)' ) SCALEYEAR +#endif + + FILENAME = TRIM( DATA_DIR ) // + & 'scalefoss_200202/scalefoss.tot.' // + & GET_RES_EXT() // '.' // CYEAR + + ! 1985 is the base year -- TOTCO2 = 1 in 1985! + IF ( SCALEYEAR == 1985 ) THEN + TOTCO2 = 1d0 + + ELSE + + ! Echo filename to stdout + WRITE( 6, 20 ) TRIM( FILENAME ) + 20 FORMAT( 'READ_TOTCO2: Reading ', a ) + + ! Open the file containing liquid CO2 scale factors + OPEN( IU_FILE, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='UNFORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_FILE,'read_totco2_file:1') + + ! Read the array dimensions IX, JX + READ( IU_FILE, IOSTAT=IOS ) IX, JX + IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_FILE,'read_totco2_file:2') + + ! Read the data block of Liquid CO2 scale factors + READ( IU_FILE, IOSTAT=IOS ) ( ( TOTCO2(I,J), I=1,IX ), J=1,JX ) + IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_FILE,'read_totco2_file:3') + + ! Close the file + CLOSE( IU_FILE ) + + ENDIF + + ! Return to calling program + END SUBROUTINE READ_TOTCO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_LIQCO2( SCALEYEAR, LIQCO2 ) +! +!****************************************************************************** +! Subroutine READ_LIQCO2 reads in the scale factors (SCALEYEAR/1985) based +! on liquid CO2 emissions. These are used to scale anthropogenic CO and +! hydrocarbon emissions from 1985 to the present. (bmy, 9/13/00, 7/20/04) +! +! NOTES: +! (1 ) Now use IOS /= 0 to trap both I/O errors and EOF. (bmy, 9/13/00) +! (2 ) Make sure parentheses end before column 73 (bmy, 9/25/00) +! (3 ) Now read the "scalefoss.liq*" files directly from the +! scalefoss_200202/ subdirectory of DATA_DIR, w/o relying on +! symbolic links. Also updated comments. (bmy, 1/24/02) +! (4 ) Eliminated obsolete code from 1/02 (bmy, 2/27/02) +! (5 ) Now write file name to stdout (bmy, 4/3/02) +! (6 ) Now use IU_FILE instead of IUNIT. Also reference IU_FILE and IOERROR +! from "file_mod.f" (bmy, 6/27/02) +! (7 ) Now use ENCODE to define CYEAR string for PGI/Linux (bmy, 9/29/03) +! (8 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : IU_FILE, IOERROR + USE BPCH2_MOD, ONLY : GET_RES_EXT + + + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: SCALEYEAR + REAL*4, INTENT(OUT) :: LIQCO2(IGLOB,JGLOB) + + ! Local variables + INTEGER :: I, J, IX, JX, IOS + CHARACTER(LEN=4 ) :: CYEAR + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_LIQCO2 begins here! + !================================================================= + WRITE( 6, 10 ) SCALEYEAR + 10 FORMAT( 'READ_LIQCO2: Year for Liquid CO2 scale factor: ', i4 ) + + ! Define the file name and the file unit + ! Now use ENCODE to define CYEAR string for Linux (bmy, 9/29/03) +#if defined( LINUX ) + ENCODE( 4, '(i4)', CYEAR ) SCALEYEAR +#else + WRITE( CYEAR, '(i4)' ) SCALEYEAR +#endif + FILENAME = TRIM( DATA_DIR ) // + & 'scalefoss_200202/scalefoss.liq.' // + & GET_RES_EXT() // '.' // CYEAR + + ! 1985 is the base year -- LIQCO2 = 1 in 1985! + IF ( SCALEYEAR == 1985 ) THEN + LIQCO2 = 1d0 + + ELSE + + ! Echo filename to stdout + WRITE( 6, 20 ) TRIM( FILENAME ) + 20 FORMAT( 'READ_TOTCO2: Reading ', a ) + + ! Open the file containing liquid CO2 scale factors + OPEN( IU_FILE, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='UNFORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_FILE,'read_liqco2_file:1') + + ! Read the array dimensions IX, JX + READ( IU_FILE, IOSTAT=IOS ) IX, JX + IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_FILE,'read_liqco2_file:2') + + ! Read the data block of Liquid CO2 scale factors + READ( IU_FILE, IOSTAT=IOS ) ( ( LIQCO2(I,J), I=1,IX ), J=1,JX ) + IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_FILE,'read_liqco2_file:3') + + ! Close the file + CLOSE( IU_FILE ) + ENDIF + + ! Return to calling program + END SUBROUTINE READ_LIQCO2 + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_TODX( TODN, TODH, TODB, SCNR89 ) +! +!****************************************************************************** +! Subroutine READ_TODX reads the time-of-day emission scale factors and +! weekday/weekend scale factors for GEIA emissions. (bmy, 7/18/00, 11/6/08) +! +! Arguments as Input: +! ============================================================================ +! (1 ) TODN (REAL*8) : Time-of-day scale factor for NOx +! (2 ) TODH (REAL*8) : Time-of-day scale factor for hydrocarbons +! (3 ) TODB (REAL*8) : Time-of-day scale factor for biogenic species +! (4 ) SCNR89 (REAL*8) : Weekday/Saturday/Sunday emission scale factors +! +! NOTES: +! (1 ) Copied from routine "anthroems.f" (bmy, 7/18/00) +! (2 ) Added code for 1 x 1 GEOS grid (bmy, 8/7/00) +! (3 ) Now use IOS /= 0 to trap both I/O errors and EOF (bmy, 9/13/00) +! (4 ) Now read files directly from DATA_DIR/fossil_200104 subdirectory. +! Also echo the file name to stdout. Now reference DATA_DIR from +! the "CMN_SETUP" header file. (bmy, 4/3/02) +! (5 ) Now reference IU_FILE and IOERROR from "file_mod.f". Also deleted +! obsolete code from April 2002 (bmy, 6/27/02) +! (6 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +! (7 ) Added space in the #ifdef block for 1 x 1.25 grid (bmy, 12/1/04) +! (8 ) Now reads appropriate file for 0.5 x 0.666 nested grid simulations +! (yxw, dan, bmy, 11/6/08) +! (9) BUG: Jintai Lin reported issues with some of the data read here. The +! sum of TODB is not 6, which points to a problem. However this is not +! used in the code. (phs, 4/16/09) +!****************************************************************************** +! + ! References to F90 modules + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : IU_FILE, IOERROR + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*8, INTENT(OUT) :: TODH(6), TODN(6), TODB(6), SCNR89(3,3) + + ! Local variables + INTEGER :: I, J, K, IOS, IUNIT + REAL*4 :: DUMMY(IGLOB,JGLOB) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_TODX begins here! + !================================================================= + + ! File name unit + IUNIT = IU_FILE + +#if defined( GRID4x5 ) + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'fossil_200104/MELD_N96_70_HC' + + ! Echo file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_TODX: Reading ', a ) + + ! Open the 4 x 5 file + OPEN( IUNIT, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='FORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:1' ) + + ! For 4 x 5 grid, skip over plume data + DO K = 1, 2 + READ( IUNIT, '(6e12.4)', IOSTAT=IOS ) + & ( ( DUMMY(I+3,J+23), I=1,29 ), J=1,15 ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:2' ) + ENDDO + + ! Read time-of-day emission scale factors + READ( IUNIT, '(6e12.4)', IOSTAT=IOS ) TODN, TODH, TODB + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:3' ) + + ! Read weekday/saturday/sunday emission scale factors + READ( IUNIT, '(2f6.3, f7.4)', IOSTAT=IOS ) + & ( ( SCNR89(I,J), J=1,3 ), I=1,3 ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:4' ) + + ! Close the 4 x 5 file + CLOSE( IUNIT ) + +#elif defined( GRID2x25 ) + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'fossil_200104/MELD2x25' + + ! Echo file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_TODX: Reading: ', a ) + + ! Open the 2 x 2.5 file + OPEN( IUNIT, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='FORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:5' ) + + ! Read time-of-day scale factors + READ( IUNIT, '(6E12.4)', IOSTAT=IOS ) TODN, TODH, TODB + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:6' ) + + ! Read Weekday/Saturday/Sunday emission scale factors + READ( IUNIT, '(3F7.4)', IOSTAT=IOS ) + & ( ( SCNR89(I,J), J=1,3 ), I=1,3 ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:7' ) + + ! Close the file + CLOSE( IUNIT ) + +#elif defined( GRID1x125 ) + + ! NOTE: Need to define this! + +#elif defined( GRID1x1 ) + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'fossil_200104/MELD1x1' + + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_TODX: Reading: ', a ) + + ! Open the 1 x 1 file + OPEN( IUNIT, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='FORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:5' ) + + ! Read time-of-day scale factors + READ( IUNIT, '(6E12.4)', IOSTAT=IOS ) TODN, TODH, TODB + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:6' ) + + ! Read Weekday/Saturday/Sunday emission scale factors + READ( IUNIT, '(3F7.4)', IOSTAT=IOS ) + & ( ( SCNR89(I,J), J=1,3 ), I=1,3 ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:7' ) + + ! Close the file + CLOSE( IUNIT ) + +#elif defined( GRID05x0666 ) + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'fossil_200104/MELD05x0666' + + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_TODX: Reading: ', a ) + + ! Open the 05x0666 file + OPEN( IUNIT, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='FORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:5' ) + + ! Read time-of-day scale factors + READ( IUNIT, '(6E12.4)', IOSTAT=IOS ) TODN, TODH, TODB + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:6' ) + + + ! Read Weekday/Saturday/Sunday emission scale factors + READ( IUNIT, '(3F7.4)', IOSTAT=IOS ) + & ( ( SCNR89(I,J), J=1,3 ), I=1,3 ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:7' ) + + ! Close the file + CLOSE( IUNIT ) + +!!===== (lzh, 02/01/2015) add 025x03125 the same as 05x0666 ===== +#elif defined( GRID025x03125 ) + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'fossil_200104/MELD025x03125' + + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_TODX: Reading: ', a ) + + ! Open the 05x0666 file + OPEN( IUNIT, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='FORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:5' ) + + ! Read time-of-day scale factors + READ( IUNIT, '(6E12.4)', IOSTAT=IOS ) TODN, TODH, TODB + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:6' ) + + + ! Read Weekday/Saturday/Sunday emission scale factors + READ( IUNIT, '(3F7.4)', IOSTAT=IOS ) + & ( ( SCNR89(I,J), J=1,3 ), I=1,3 ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_todx:7' ) + + ! Close the file + CLOSE( IUNIT ) + +#endif + + ! Return to calling program + END SUBROUTINE READ_TODX + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_GEIA_ASCII( E_NOX, E_CO, E_ETHE, E_PRPE, + & E_C2H6, E_C3H8, E_ALK4, E_ACET, + & E_MEK, E_SOX ) +! +!****************************************************************************** +! Subroutine READ_GEIA_ASCII reads the anthropogenic GEIA emissions from +! from the old-style ASCII "merge file". (bmy, 7/18/00, 7/20/04) +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_NOX (REAL*4) : GEIA anthro NOx (4 seasons, 2 levels) +! (2 ) E_CO (REAL*4) : GEIA anthro CO (no seasonality, 1 level ) +! (3 ) E_ETHE (REAL*4) : GEIA anthro ETHE (no seasonality, 1 level ) +! (4 ) E_PRPE (REAL*4) : GEIA anthro PRPE (no seasonality, 1 level ) +! (5 ) E_C2H6 (REAL*4) : GEIA anthro C2H6 (no seasonality, 1 level ) +! (6 ) E_C3H8 (REAL*4) : GEIA anthro C3H8 (no seasonality, 1 level ) +! (7 ) E_ALK4 (REAL*4) : GEIA anthro ALK4 (no seasonality, 1 level ) +! (8 ) E_ACET (REAL*4) : GEIA anthro ACET (no seasonality, 1 level ) +! (9 ) E_MEK (REAL*4) : GEIA anthro MEK (no seasonality, 1 level ) +! (10) E_SOX (REAL*4) : GEIA anthro SOx (4 seasons, 2 levels) +! +! NOTES: +! (1 ) All arguments are optional. +! (2 ) Copied from routine "anthroems.f" (bmy, 7/18/00) +! (3 ) Now use IOS /= 0 to trap both I/O errors and EOF (bmy, 9/13/00) +! (4 ) Renamed to READ_GEIA_ASCII, since this only reads the old-style +! ASCII merge file (bmy, 4/23/01) +! (5 ) Now read files directly from DATA_DIR/fossil_obsolete subdirectory. +! Also echo the file name to stdout. Now reference DATA_DIR from +! the "CMN_SETUP" header file. (bmy, 4/3/02) +! (6 ) Now reference IU_FILE and IOERROR from "file_mod.f". Also deleted +! obsolete code from April 2002 (bmy, 6/27/02) +! (7 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_RES_EXT + USE DIRECTORY_MOD, ONLY : DATA_DIR + USE FILE_MOD, ONLY : IU_FILE, IOERROR + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT), OPTIONAL :: E_NOX (IGLOB,JGLOB,4,2) + REAL*4, INTENT(OUT), OPTIONAL :: E_CO (IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_ETHE(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_PRPE(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_C2H6(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_C3H8(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_ALK4(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_ACET(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_MEK (IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_SOX (IGLOB,JGLOB,4,2) + + ! Local variables + INTEGER :: IOS, IUNIT + + REAL*4 :: T_NOX (IGLOB,JGLOB,4,2) + REAL*4 :: T_CO (IGLOB,JGLOB ) + REAL*4 :: T_ETHE(IGLOB,JGLOB ) + REAL*4 :: T_PRPE(IGLOB,JGLOB ) + REAL*4 :: T_C2H6(IGLOB,JGLOB ) + REAL*4 :: T_C3H8(IGLOB,JGLOB ) + REAL*4 :: T_ALK4(IGLOB,JGLOB ) + REAL*4 :: T_ACET(IGLOB,JGLOB ) + REAL*4 :: T_MEK (IGLOB,JGLOB ) + REAL*4 :: T_SOX (IGLOB,JGLOB,4,2) + + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_GEIA_ASCII begins here! + !================================================================= + + ! Define the file name + FILENAME = TRIM( DATA_DIR ) // 'fossil_obsolete/merge.' // + & GET_RES_EXT() // '_CTM' + +#if defined( GRID4x5 ) + ! For 4x5, the old ASCII file had the "_SASS" extension. + ! This is historical baggage (bmy, 4/3/02) + FILENAME = TRIM( FILENAME ) // '_SASS' +#endif + + ! Define the file unit + IUNIT = IU_FILE + + ! Echo the filename to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_GEIA_ASCII: Reading ', a ) + + ! Open the GEIA emissions merge file + OPEN( IUNIT, FILE=TRIM( FILENAME ), STATUS='OLD', + & FORM='FORMATTED', IOSTAT=IOS ) + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_geia:1' ) + + ! Read data into temporary arrays + READ( IUNIT, '(7e10.3)', IOSTAT=IOS ) + & T_NOX, T_CO, T_ETHE, T_PRPE, T_C2H6, + & T_C3H8, T_ALK4, T_ACET, T_MEK, T_SOX + IF ( IOS /= 0 ) CALL IOERROR( IOS, IUNIT, 'read_geia:2' ) + + ! Close the merge file + CLOSE( IUNIT ) + + ! Assign data from temporary arrays into optional arguments + IF ( PRESENT( E_NOX ) ) E_NOX = T_NOX + IF ( PRESENT( E_CO ) ) E_CO = T_CO + IF ( PRESENT( E_ETHE ) ) E_ETHE = T_ETHE + IF ( PRESENT( E_PRPE ) ) E_PRPE = T_PRPE + IF ( PRESENT( E_C2H6 ) ) E_C2H6 = T_C2H6 + IF ( PRESENT( E_C3H8 ) ) E_C3H8 = T_C3H8 + IF ( PRESENT( E_ALK4 ) ) E_ALK4 = T_ALK4 + IF ( PRESENT( E_ACET ) ) E_ACET = T_ACET + IF ( PRESENT( E_MEK ) ) E_MEK = T_MEK + IF ( PRESENT( E_SOX ) ) E_SOX = T_SOX + + ! Return to calling program + END SUBROUTINE READ_GEIA_ASCII + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_GEIA( E_NOX, E_CO, E_ALK4, E_ACET, E_MEK, + & E_PRPE, E_C3H8, E_C2H6, E_ETHE, E_SOX ) +! +!****************************************************************************** +! Subroutine READ_GEIA reads the anthropogenic GEIA emissions +! from a binary punch file. (bmy, 4/23/01, 8/16/05) +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_NOX (REAL*4) : GEIA anthro NOx (4 seasons, 2 levels) +! (2 ) E_CO (REAL*4) : GEIA anthro CO (no seasonality, 1 level ) +! (3 ) E_ALK4 (REAL*4) : GEIA anthro ALK4 (no seasonality, 1 level ) +! (4 ) E_ACET (REAL*4) : GEIA anthro ACET (no seasonality, 1 level ) +! (5 ) E_MEK (REAL*4) : GEIA anthro MEK (no seasonality, 1 level ) +! (6 ) E_PRPE (REAL*4) : GEIA anthro PRPE (no seasonality, 1 level ) +! (7 ) E_C3H8 (REAL*4) : GEIA anthro C3H8 (no seasonality, 1 level ) +! (8 ) E_C2H6 (REAL*4) : GEIA anthro C2H6 (no seasonality, 1 level ) +! (9 ) E_ETHE (REAL*4) : GEIA anthro ETHE (no seasonality, 1 level ) +! (10) E_SOX (REAL*4) : GEIA anthro SOx (4 seasons, 2 levels) +! +! NOTES: +! (1 ) Now reads from binary punch file format. This is more convenient, +! and is readable directly into GAMAP. Read directly from the +! DATA_DIR/fossil_200104/ subdirectory. (bmy, 4/23/01) +! (2 ) Bug fix: T_C2H6 was being overwritten with T_ETHE. This has now +! been corrected. (bmy, 7/2/01) +! (3 ) Now only read emissions for tracers whose keywords have been passed +! (bmy, 9/6/01) +! (4 ) Now write file name to stdout (bmy, 4/3/02) +! (5 ) Now call READ_BPCH2 with QUIET=.TRUE. (bmy, 3/14/03) +! (6 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +! (7 ) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D, GET_RES_EXT, READ_BPCH2 + USE DIRECTORY_MOD, ONLY : DATA_DIR + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT), OPTIONAL :: E_NOX (IGLOB,JGLOB,4,2) + REAL*4, INTENT(OUT), OPTIONAL :: E_CO (IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_ALK4(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_ACET(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_MEK (IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_PRPE(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_C3H8(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_C2H6(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_ETHE(IGLOB,JGLOB ) + REAL*4, INTENT(OUT), OPTIONAL :: E_SOX (IGLOB,JGLOB,4,2) + + ! Local variables + INTEGER :: L + REAL*4 :: ARRAY(IGLOB,JGLOB,2) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_GEIA begins here! + !================================================================= + + ! Define the binary punch file name + FILENAME = TRIM( DATA_DIR ) // + & 'fossil_200104/merge_nobiofuels.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! Write file name to stdout + WRITE( 6, 100 ) TRIM( FILENAME ) + 100 FORMAT( 'READ_GEIA: Reading ', a ) + + !================================================================= + ! Read NOx (tracer #1): 4 seasons, 2 levels + !================================================================= + IF ( PRESENT( E_NOX ) ) THEN + + ! Read winter NOx (DJF) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 1, + & -744d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_NOX(:,:,1,L) = ARRAY(:,:,L) + ENDDO + + ! Read spring NOx (MAM) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 1, + & 1416d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_NOX(:,:,2,L) = ARRAY(:,:,L) + ENDDO + + ! Read summer NOx (JJA) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 1, + & 3624d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_NOX(:,:,3,L) = ARRAY(:,:,L) + ENDDO + + ! Read autumn NOx (SON) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 1, + & 5832d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_NOX(:,:,4,L) = ARRAY(:,:,L) + ENDDO + ENDIF + + !================================================================= + ! Read CO (tracer #4): aseasonal + !================================================================= + IF ( PRESENT( E_CO ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 4, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_CO(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read ALK4 (tracer #5): aseasonal + !================================================================= + IF ( PRESENT( E_ALK4 ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 5, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_ALK4(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read ACET (tracer #9): aseasonal + !================================================================= + IF ( PRESENT( E_ACET ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 9, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_ACET(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read MEK (tracer #10): aseasonal + !================================================================= + IF ( PRESENT( E_MEK ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 10, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_MEK(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read PRPE (tracer #18): aseasonal + !================================================================= + IF ( PRESENT( E_PRPE ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 18, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_PRPE(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read C3H8 (tracer #19): aseasonal + !================================================================= + IF ( PRESENT( E_C3H8 ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 19, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_C3H8(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read C2H6 (tracer #20): aseasonal + !================================================================= + IF ( PRESENT( E_C2H6 ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 21, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_C2H6(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read ETHE (tracer #26): aseasonal + !================================================================= + IF ( PRESENT( E_ETHE ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 26, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY(:,:,1), QUIET=.TRUE. ) + + E_ETHE(:,:) = ARRAY(:,:,1) + ENDIF + + !================================================================= + ! Read SOx (tracer #27): 4 seasons, 2 levels + !================================================================= + IF ( PRESENT( E_SOX ) ) THEN + + ! Read winter SOx (DJF) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 27, + & -744d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_SOX(:,:,1,L) = ARRAY(:,:,L) + ENDDO + + ! Read spring SOx (MAM) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 27, + & 1416d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_SOX(:,:,2,L) = ARRAY(:,:,L) + ENDDO + + ! Read summer SOx (JJA) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 27, + & 3624d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_SOX(:,:,3,L) = ARRAY(:,:,L) + ENDDO + + ! Read autumn SOx (SON) + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 27, + & 5832d0, IGLOB, JGLOB, + & 2, ARRAY, QUIET=.TRUE. ) + + DO L = 1, 2 + E_SOX(:,:,4,L) = ARRAY(:,:,L) + ENDDO + ENDIF + + ! Return to calling program + END SUBROUTINE READ_GEIA + +!------------------------------------------------------------------------------ + + SUBROUTINE READ_C3H8_C2H6_NGAS( E_C3H8, E_C2H6 ) +! +!****************************************************************************** +! Subroutine READ_C3H8_C2H6_NGAS reads the anthropogenic C3H8 and C2H6 +! emissions, which are scaled from Natural Gas (CH4) (bmy, 9/6/01, 8/16/05) +! +! Emissions files are from Yaping Xiao (9/01) Their path names are: +! /data/ctm/GEOS_2x2.5/C3H8_C2H6_200109/C3H8_C2H6_ngas.geos.2x25 +! /data/ctm/GEOS_4x5/C3H8/C2H6_200109/C3H8_C2H6_ngas.geos.4x5 +! +! Arguments as Output: +! ============================================================================ +! (1 ) E_C3H8 (REAL*4) : Anthro C3H8 scaled from CH4 (aseasonal, 1 level) +! (2 ) E_C2H6 (REAL*4) : Anthro C2H6 scaled from CH4 (aseasonal, 1 level) +! +! NOTES: +! (1 ) Adapted from READ_GEIA (bmy, 9/6/01) +! (2 ) Now echo filename to standard output (bmy, 1/25/02) +! (3 ) Now call READ_BPCH2 with QUIET=.TRUE. (bmy, 3/11/03) +! (4 ) Now references DATA_DIR from "directory_mod.f" (bmy, 7/20/04) +! (5 ) Now can read data for both GEOS and GCAP grids (bmy, 8/16/05) +!****************************************************************************** +! + ! References to F90 modules + USE BPCH2_MOD + USE DIRECTORY_MOD, ONLY : DATA_DIR + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + REAL*4, INTENT(OUT), OPTIONAL :: E_C3H8(IGLOB,JGLOB) + REAL*4, INTENT(OUT), OPTIONAL :: E_C2H6(IGLOB,JGLOB) + + ! Local variables + INTEGER :: I, J, L, S + REAL*4 :: ARRAY(IGLOB,JGLOB,1) + CHARACTER(LEN=255) :: FILENAME + + !================================================================= + ! READ_GEIA begins here! + !================================================================= + + ! Define the binary punch file name + FILENAME = TRIM( DATA_DIR ) // + & 'C3H8_C2H6_200109/C3H8_C2H6_ngas.' // + & GET_NAME_EXT_2D() // '.' // GET_RES_EXT() + + ! Echo filename to std output + WRITE( 6, 110 ) TRIM( FILENAME ) + 110 FORMAT( 'READ_C3H8_C2H6_NGAS: Reading ', a ) + + ! Read C3H8 (tracer #19): aseasonal + IF ( PRESENT( E_C3H8 ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 19, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + E_C3H8(:,:) = ARRAY(:,:,1) + ENDIF + + ! Read C2H6 (tracer #21): aseasonal + IF ( PRESENT( E_C2H6 ) ) THEN + CALL READ_BPCH2( FILENAME, 'ANTHSRCE', 21, + & 0d0, IGLOB, JGLOB, + & 1, ARRAY, QUIET=.TRUE. ) + + E_C2H6(:,:) = ARRAY(:,:,1) + ENDIF + + ! Return to calling program + END SUBROUTINE READ_C3H8_C2H6_NGAS + +!------------------------------------------------------------------------------ + + FUNCTION GET_DAY_INDEX( NTAU ) RESULT( JSCEN ) +! +!***************************************************************************** +! Function GET_DAY_INDEX returns the day index (Saturday/Sunday/Weekday) +! for the given time. This is used to scale GEIA emissions. (bmy, 7/28/00) +! +! Arguments as Input: +! =========================================================================== +! (1) NTAU (INTEGER) : Integral hours since 0h, 1 Jan 1985 +! +! Return value: +! =========================================================================== +! (1) JSCEN (INTEGER) : Flag for Saturday (1), Sunday (2), or Weekday (3) +! +! NOTES: +! (1) Scale factors for Saturday/Sunday/Weekday must average out to 1! +!***************************************************************************** +! + ! Arguments + INTEGER, INTENT(IN) :: NTAU + + ! Local variables + INTEGER :: NDAY + + ! Return value + INTEGER :: JSCEN + + !================================================================= + ! GET_DAY_INDEX begins here! + !================================================================= + + ! NDAY is the day of the week + NDAY = NTAU / 24 + + ! 1 Jan 1980 and 1 Jan 1985 were both Tuesdays, so NDAY mod 7 = 4 is a + ! Saturday and NDAY mod 7 = 5 is a Sunday (bmy, 3/23/98) + SELECT CASE ( MOD( NDAY, 7 ) ) + + ! Saturday + CASE ( 4 ) + JSCEN = 1 + + ! Sunday + CASE ( 5 ) + JSCEN = 2 + + ! Weekday + CASE DEFAULT + JSCEN = 3 + + END SELECT + + ! Return to calling program + END FUNCTION GET_DAY_INDEX + +!------------------------------------------------------------------------------ + + FUNCTION GET_IHOUR( I ) RESULT( IHOUR ) +! +!****************************************************************************** +! Function GET_IHOUR returns the index for the TODH, TODN, TODB scale +! factors which are read by subroutine GET_TODX. (bmy, 7/28/00, 4/23/01) +! +! Arguments as Input: +! ============================================================================ +! (1 ) I (INTEGER) : Grid box longitude index +! +! Return value +! ============================================================================ +! (1 ) IHOUR (INTEGER) : Index for scale factor arrays +! +! NOTES: +! (1 ) COMPUTE IHOUR TO DETERMINE TIME OF DAY FACTOR FOR EMISSIONS +! THIS TOFDAY IS IN GREENWICH TIME(GMT); WE NEED TO CHANGE IT TO +! (I,J)BOX TIME=XLOCTM +! TOFDAY is GMT at the BEGINNING of the time step. +! (TOFDAY and NTAU do not refer to the end of time step until they +! are updated at line 300 of the main driver, just before the +! diagnostics are written.) +! The 0.001 is added to remove roundoff amibuity when timestep +! is exactly on boundary for emissions change. +! 1hr changed NCHEM->NDYN in following line +! (2 ) For GEOS-CTM, NDYN is in minutes, NDYN/60 is in hours (bmy, 2/26/98) +! (3 ) Make sure 0 <= XLOCTM < 24, to avoid subscript errors (bmy, 6/11/98) +! (4 ) Middle of time step is between 10pm-2am when IHOUR = 1 +! (5 ) Updated comments (bmy, 4/23/01) +! (6 ) Now use function GET_LOCALTIME from the new "time_mod.f". Remove +! IREF, NDYN, TOFDAY, DISIZE from arg list. Add I to the arg list. +! Removed XLOCTM variable. (bmy, 2/10/03) +! (7 ) Modified to use NINT instead of INT to calculate the local time +! (ccc, 4/15/09) +!****************************************************************************** +! + ! References to F90 modules + USE TIME_MOD, ONLY : GET_LOCALTIME + + ! Arguments + INTEGER, INTENT(IN) :: I + + ! Return value + INTEGER :: IHOUR + + !================================================================= + ! GET_IHOUR begins here! + !================================================================= + + ! IHOUR ranges from 1-6 + ! Modified to use NINT instead of INT (ccc, 4/15/09) +! prior to 4/15/09 --------------------------------- +! IHOUR = INT( ( GET_LOCALTIME( I ) ) / 4 ) + 1 + IHOUR = NINT( ( GET_LOCALTIME( I ) ) / 4 ) + 1 + IF ( IHOUR == 7 ) IHOUR = 1 + + ! Return to calling program + END FUNCTION GET_IHOUR + +!------------------------------------------------------------------------------ + + SUBROUTINE TOTAL_FOSSIL_TG( FFARRAY, IX, JX, LX, + & MOLWT, NAME, NSEASON ) +! +!****************************************************************************** +! Subroutine TOTAL_FOSSIL_TG prints the amount of biomass burning +! emissions that are emitted each month in Tg or Tg C. (bmy, 4/27/01, 2/4/03) +! +! Arguments as Input: +! ============================================================================ +! (1 ) FFARRAY (REAL*8 ) : Fossil Fuel CO emissions [molec (C)/cm2/month] +! (2-4) IX,JX,LX (INTEGER) : Dimensions of FFARRAY +! (5 ) MOLWT (REAL*8 ) : Molecular wt [kg/mole] for the given tracer +! (6 ) NAME (REAL*8 ) : Tracer name +! (7 ) NSEASON (INTEGER) : Number of the season, for seasonal NOx/SOX +! +! NOTES: +! (1) Scale factors were determined by Jennifer Logan (jal@io.harvard.edu), +! Bryan Duncan (bnd@io.harvard.edu), and Daniel Jacob (djj@io.harvard.edu) +! (2) Now replace DXYP(J)*1d4 with routine GET_AREA_CM2 from "grid_mod.f". +! (bmy, 2/4/03) +!****************************************************************************** +! + ! References to F90 modules + USE GRID_MOD, ONLY : GET_AREA_CM2 + +# include "CMN_SIZE" ! Size parameters + + ! Arguments + INTEGER, INTENT(IN) :: IX, JX, LX + INTEGER, OPTIONAL, INTENT(IN) :: NSEASON + REAL*8, INTENT(IN) :: FFARRAY(IX,JX,LX) + REAL*8, INTENT(IN) :: MOLWT + CHARACTER(LEN=*), INTENT(IN) :: NAME + + ! Local variables + INTEGER :: I, J, L + REAL*8 :: TOTAL, A_CM2 + CHARACTER(LEN=6) :: UNIT + + !================================================================= + ! TOTAL_FOSSIL_TG begins here! + !================================================================= + + ! Initialize summing variable + TOTAL = 0d0 + + DO L = 1, LX + DO J = 1, JX + + ! Grid box surface area [cm2] + A_CM2 = GET_AREA_CM2( J ) + + DO I = 1, IX + TOTAL = TOTAL + FFARRAY(I,J,L) * A_CM2 * ( MOLWT/ 6.023d23 ) + ENDDO + ENDDO + ENDDO + + IF ( PRESENT( NSEASON ) ) THEN + + ! Total for each season + SELECT CASE( NSEASON ) + + ! DJF is 90 days long + CASE ( 1 ) + TOTAL = TOTAL * 1d-9 * 90d0 * 86400d0 + + ! MAM, JJA are 92 days long + CASE ( 2, 3 ) + TOTAL = TOTAL * 1d-9 * 92d0 * 86400d0 + + ! SON is 91 days long + CASE ( 4 ) + TOTAL = TOTAL * 1d-9 * 91d0 * 86400d0 + END SELECT + + ELSE + + ! Convert from kg --> Tg for aseasonal emissions + TOTAL = TOTAL * 1d-9 * 365.25d0 * 86400d0 + + ENDIF + + ! Define unit string + SELECT CASE( TRIM( NAME ) ) + CASE ( 'NOx' ) + UNIT = '[Tg N]' + CASE ( 'CO', 'CH2O' ) + UNIT = '[Tg ]' + CASE DEFAULT + UNIT = '[Tg C]' + END SELECT + + ! Write totals + IF ( PRESENT( NSEASON ) ) THEN + + ! Seasonal + WRITE( 6, 100 ) NAME, TOTAL, UNIT, NSEASON + 100 FORMAT( 'Total Anthropogenic ', a4, ': ', f9.3, 1x, a, + & ' Season =', i3 ) + + ELSE + + ! Aseasonal + WRITE( 6, 110 ) NAME, TOTAL, UNIT + 110 FORMAT( 'Total Anthropogenic ', a4, ': ', f9.3, 1x, a ) + + ENDIF + + ! Return to calling program + END SUBROUTINE TOTAL_FOSSIL_TG + +!------------------------------------------------------------------------------ + + END MODULE GEIA_MOD