module progseasalts_intr 8,8 !--------------------------------------------------------------------------------- ! Module to interface the aerosol parameterizations with CAM ! written by PJR (extensively modified from chemistry module) ! prognostic sea salt module taken from dust module by nmm 11/12/03 !--------------------------------------------------------------------------------- use shr_kind_mod,only: r8 => shr_kind_r8 use spmd_utils, only: masterproc use ppgrid, only: pcols, pver,pverp use physconst, only: mwdry, mwh2o,gravit,rair use constituents,only: pcnst, cnst_add, cnst_name, cnst_get_ind use drydep_mod, only: calcram use dust_sediment_mod, only: dust_sediment_tend, dust_sediment_vel use cam_logfile, only: iulog implicit none private ! Make default type private to the module save public nsst ! number of sea salt constituents public ncnst ! number of sea salt constituents #if (defined MODAL_AERO) #if (defined MODAL_AERO_7MODE) integer, parameter:: nsst =4 #elif (defined MODAL_AERO_3MODE) integer, parameter:: nsst =3 #endif #else integer, parameter:: nsst =4 #endif integer :: ncyear integer :: ix_progseasalts = -1 integer :: nx_progseasalts #if (defined MODAL_AERO) #if (defined MODAL_AERO_7MODE) integer, parameter :: ncnst=nsst+4 ! number of constituents #elif (defined MODAL_AERO_3MODE) integer, parameter :: ncnst=nsst+3 ! number of constituents #endif #else integer, parameter :: ncnst=nsst ! number of constituents #endif character(len=8), dimension(ncnst), parameter :: & ! constituent names #if (defined MODAL_AERO) #if (defined MODAL_AERO_7MODE) cnst_names = (/'ncl_a1', 'ncl_a2', 'ncl_a4', 'ncl_a6', 'num_a1', 'num_a2', 'num_a4', 'num_a6'/) #elif (defined MODAL_AERO_3MODE) cnst_names = (/'ncl_a1', 'ncl_a2', 'ncl_a3', 'num_a1', 'num_a2', 'num_a3'/) #endif #else cnst_names = (/'SSLT01', 'SSLT02', 'SSLT03', 'SSLT04'/) #endif ! ! Public interfaces ! public progseasalts_register_cnst ! register consituents public progseasalts_implements_cnst ! returns true if consituent is implemented by this package public progseasalts_init_cnst ! initialize mixing ratios if not read from initial file public progseasalts_initialize ! initialize (history) variables public progseasalts_wet_intr ! interface to wet deposition public progseasalts_emis_intr ! interface to emission public progseasalts_drydep_intr ! interface to tendency computation !!$ public progseasalts_time_interp ! interpolate oxidants and fluxes to current time public progseasalts_idx1 ! allow other parts of code to know where progseasalts is public progseasalts_set_idx public progseasalts_names public progseasalts_has_wet_dep character(len=8), dimension(ncnst) :: progseasalts_names = cnst_names logical :: progseasalts_has_wet_dep(ncnst) = .true. #if (defined MODAL_AERO) #if (defined MODAL_AERO_7MODE) real(r8) :: stk_crc(nsst)=(/ 1.0_r8, 1.0_r8, 1.0_r8, 1.0_r8 /) #elif (defined MODAL_AERO_3MODE) real(r8) :: stk_crc(nsst)=(/ 1.0_r8, 1.0_r8, 1.0_r8 /) #endif #else real(r8) :: stk_crc(nsst)=(/ 1.0_r8, 1.0_r8, 1.0_r8, 1.0_r8 /) #endif ![frc] Correction to Stokes settling velocity--we are assuming they are close enough 1.0 to be ! set to one--unlikely to cause considerable error real(r8),parameter:: dns_aer_sst = & 2200.0_r8 ![kg m-3] Aerosol density ! ! real(r8):: soil_erodibility(plon,plat) ! soil erodibility factor #if (defined MODAL_AERO) real(r8) :: sst_sz_range_lo(nsst) = & #if (defined MODAL_AERO_7MODE) (/0.08e-6_r8, 0.02e-6_r8, 0.3e-6_r8, 1.0e-6_r8/) ! accu, aitken, fine, coarse #elif (defined MODAL_AERO_3MODE) (/0.08e-6_r8, 0.02e-6_r8, 1.0e-6_r8/) ! accu, aitken, coarse #endif real(r8) :: sst_sz_range_hi(nsst) = & #if (defined MODAL_AERO_7MODE) (/0.3e-6_r8, 0.08e-6_r8, 1.0e-6_r8, 10.0e-6_r8/) #elif (defined MODAL_AERO_3MODE) (/1.0e-6_r8, 0.08e-6_r8, 10.0e-6_r8/) #endif #else real(r8) :: sst_sz_range(nsst+1) = & (/0.2e-6_r8,1.0e-6_r8,3.0e-6_r8,10.0e-6_r8,20.0e-6_r8/) ! bottom and tops of size bins for sea salts in m #endif !(diameter not radius as in tie) real(r8) :: sst_source(nsst) ! source factors for each bin #if (defined MODAL_AERO) real(r8) :: sst_source_num(nsst) integer, target :: spc_ndx(nsst) integer, target :: spc_num_ndx(nsst) #if (defined MODAL_AERO_7MODE) integer, pointer :: ncl_a1_ndx, ncl_a2_ndx, ncl_a4_ndx, ncl_a6_ndx integer, pointer :: num_a1_ndx, num_a2_ndx, num_a4_ndx, num_a6_ndx #elif (defined MODAL_AERO_3MODE) integer, pointer :: ncl_a1_ndx, ncl_a2_ndx, ncl_a3_ndx integer, pointer :: num_a1_ndx, num_a2_ndx, num_a3_ndx #endif #endif real(r8) :: smt_vwr(nsst) & #if (defined MODAL_AERO) #if (defined MODAL_AERO_7MODE) =(/0.051e-6_r8, 0.15e-6_r8, 0.56e-6_r8, 3.6e-6_r8/) ![m] Mass-weighted mean diameter resolved #elif (defined MODAL_AERO_3MODE) =(/0.051e-6_r8, 0.256e-6_r8, 3.6e-6_r8/) ![m] Mass-weighted mean diameter resolved #endif ! assume stddev=2.0 for seasalt, Dp is calculated from Dpg which is based on observations ! (Seinfeld and Pandis, Smirnov et al. 2003 etc). Dpg is assumed to be 0.05,0.2,3.0,10.0 #else =(/0.52e-6_r8,2.38e-6_r8,4.86e-6_r8,15.14e-6_r8/) ![m] Mass-weighted mean diameter resolved #endif !initializaed in module and used in emissions #if (defined MODAL_AERO) ! here is used for Ekman's ss integer :: sections ! number of sections used to calculate fluxes parameter (sections=(31)) ! only use up to ~20um real(r8), dimension(sections) :: Dg = (/ & 0.0020e-5_r8, 0.0025e-5_r8, 0.0032e-5_r8, & 0.0040e-5_r8, 0.0051e-5_r8, 0.0065e-5_r8, & 0.0082e-5_r8, 0.0104e-5_r8, 0.0132e-5_r8, & 0.0167e-5_r8, 0.0211e-5_r8, 0.0267e-5_r8, & 0.0338e-5_r8, 0.0428e-5_r8, 0.0541e-5_r8, & 0.0685e-5_r8, 0.0867e-5_r8, 0.1098e-5_r8, & 0.1389e-5_r8, 0.1759e-5_r8, 0.2226e-5_r8, & 0.2818e-5_r8, 0.3571e-5_r8, 0.4526e-5_r8, & 0.5735e-5_r8, 0.7267e-5_r8, 0.9208e-5_r8, & 1.1668e-5_r8, 1.4786e-5_r8, 1.8736e-5_r8, & 2.3742e-5_r8 /) real(r8), dimension(sections) :: bm, rdry, rm real(r8), dimension(4,sections) :: consta, constb !constants for calculating emission polynomial #endif ! size ranges for sea salts contains !=============================================================================== subroutine progseasalts_register_cnst,5 !----------------------------------------------------------------------- ! ! Purpose: register advected constituents for all aerosols ! ! Method: ! <Describe the algorithm(s) used in the routine.> ! <Also include any applicable external references.> ! ! Author: P. J. Rasch ! !----------------------------------------------------------------------- !---------------------------Local workspace----------------------------- integer :: m ! tracer index real(r8), parameter :: one = 1._r8 real(r8), parameter :: zero = 0._r8 !----------------------------------------------------------------------- ! Set names of variables undergoing evolution ! returns m as current index for tracer numbers call cnst_add(cnst_names(1), one, one, zero, m) ! and store the start index of progseasalts species used elsewhere in model retrieved by progseasalts_idx1 call progseasalts_set_idx(m) call cnst_add(cnst_names(2), one, one, zero, m) call cnst_add(cnst_names(3), one, one, zero, m) call cnst_add(cnst_names(4), one, one, zero, m) return end subroutine progseasalts_register_cnst !======================================================================= function progseasalts_implements_cnst(name) 1 !----------------------------------------------------------------------- ! ! Purpose: return true if specified constituent is implemented by this ! package ! ! Author: T. Henderson ! !----------------------------------------------------------------------- implicit none !-----------------------------Arguments--------------------------------- character(len=*), intent(in) :: name ! constituent name logical :: progseasalts_implements_cnst ! return value !---------------------------Local workspace----------------------------- integer :: m !----------------------------------------------------------------------- progseasalts_implements_cnst = .false. if ( ix_progseasalts < 1 ) return do m = 1, ncnst if (name == cnst_names(m)) then progseasalts_implements_cnst = .true. return end if end do end function progseasalts_implements_cnst !======================================================================= subroutine progseasalts_init_cnst(name, q, gcid) 1 !----------------------------------------------------------------------- ! ! Purpose: ! Set initial mass mixing ratios. ! !----------------------------------------------------------------------- implicit none !-----------------------------Arguments--------------------------------- character(len=*), intent(in) :: name ! constituent name real(r8), intent(out) :: q(:,:) ! mass mixing ratio integer, intent(in) :: gcid(:) ! global column id !----------------------------------------------------------------------- if ( name == cnst_names(1) ) then q = 0._r8 else if ( name == cnst_names(2) ) then q = 0._r8 else if ( name == cnst_names(3) ) then q = 0._r8 else if ( name == cnst_names(4) ) then q = 0._r8 end if end subroutine progseasalts_init_cnst function progseasalts_idx1() 5 implicit none integer progseasalts_idx1 progseasalts_idx1 = ix_progseasalts end function progseasalts_idx1 subroutine progseasalts_set_idx(m) 1 implicit none integer m ix_progseasalts = m end subroutine progseasalts_set_idx !=============================================================================== subroutine progseasalts_initialize 2,34 !----------------------------------------------------------------------- ! ! Purpose: initialize parameterization of progseasalts chemistry ! (declare history variables) ! ! Method: ! <Describe the algorithm(s) used in the routine.> ! <Also include any applicable external references.> ! ! Author: NCAR CMS ! NMM, november 14,2003 ! !----------------------------------------------------------------------- use cam_history, only: addfld, add_default, phys_decomp use physconst, only: pi,rair,boltz #if (defined MODAL_AERO) use mo_chem_utls, only: get_spc_ndx #endif implicit none !---------------------------Local workspace----------------------------- integer :: m,n integer :: numsplit,ix,mm parameter (numsplit=50) real (r8):: b,rmid,dr ! work variables for entrainment parameters character dummy*20 #if (defined MODAL_AERO) real(r8) :: d0, d1, drydens, seasalt_emfac_num, seasalt_emfac_mas #endif !----------------------------------------------------------------------- #if (defined MODAL_AERO) #if (defined MODAL_AERO_7MODE) ncl_a1_ndx => spc_ndx(1) ncl_a2_ndx => spc_ndx(2) ncl_a4_ndx => spc_ndx(3) ncl_a6_ndx => spc_ndx(4) num_a1_ndx => spc_num_ndx(1) num_a2_ndx => spc_num_ndx(2) num_a4_ndx => spc_num_ndx(3) num_a6_ndx => spc_num_ndx(4) ncl_a1_ndx = get_spc_ndx( 'ncl_a1' ) ncl_a2_ndx = get_spc_ndx( 'ncl_a2' ) ncl_a4_ndx = get_spc_ndx( 'ncl_a4' ) ncl_a6_ndx = get_spc_ndx( 'ncl_a6' ) num_a1_ndx = get_spc_ndx( 'num_a1' ) num_a2_ndx = get_spc_ndx( 'num_a2' ) num_a4_ndx = get_spc_ndx( 'num_a4' ) num_a6_ndx = get_spc_ndx( 'num_a6' ) #elif (defined MODAL_AERO_3MODE) ncl_a1_ndx => spc_ndx(1) ncl_a2_ndx => spc_ndx(2) ncl_a3_ndx => spc_ndx(3) num_a1_ndx => spc_num_ndx(1) num_a2_ndx => spc_num_ndx(2) num_a3_ndx => spc_num_ndx(3) ncl_a1_ndx = get_spc_ndx( 'ncl_a1' ) ncl_a2_ndx = get_spc_ndx( 'ncl_a2' ) ncl_a3_ndx = get_spc_ndx( 'ncl_a3' ) num_a1_ndx = get_spc_ndx( 'num_a1' ) num_a2_ndx = get_spc_ndx( 'num_a2' ) num_a3_ndx = get_spc_ndx( 'num_a3' ) #endif #endif ! initialize the emission bins: sst_source(:)=0._r8 #if (defined MODAL_AERO) sst_source_num(:)=0._r8 #endif ! sea salt source apprortionment calculated elsewhere. Based on ! gong et al., with andreas 1998 refinement--see Mahowald et al., 2005 seasalt paper for descriptions #if (defined MODAL_AERO) ! do n = 1,nsst ! d0 = sst_sz_range(n) * 1.e+2_r8 ! diameter in cm ! d1 = sst_sz_range(n+1) * 1.e+2_r8 ! diameter in cm ! drydens = dns_aer_sst * 1.e-3_r8 ! g/cm3 ! call seasalt_emitfactors_1bin( 1, d0, d1, drydens, seasalt_emfac_num, seasalt_emfac_mas ) ! sst_source_num(n) = seasalt_emfac_num ! #/m2/s ! sst_source(n) = seasalt_emfac_mas * 1.0e-3_r8 ! convert from g/m2/s to kg/m2/s ! end do ! use Ekman's ss rdry(:)=Dg(:)/2._r8 ! meter ! multiply rm with 1.814 because it should be RH=80% and not dry particles ! for the parameterization rm(:)=1.814_r8*rdry(:)*1.e6_r8 ! um bm(:)=(0.380_r8-log10(rm(:)))/0.65_r8 ! use in Manahan ! calculate constants form emission polynomials do m=1,sections if ((m).le.9)then consta(1,m) = (-2.576)*10.**35*Dg(m)**4+5.932*10.**28 & * Dg(m)**3+(-2.867)*10.**21*Dg(m)**2+(-3.003) & * 10.**13*Dg(m) + (-2.881)*10.**6 constb(1,m) = 7.188*10.**37 & * Dg(m)**4+(-1.616)*10.**31*Dg(m)**3+6.791*10.**23 & * Dg(m)**2+1.829*10.**16*Dg(m)+7.609*10.**8 elseif ((m).ge.10.and.(m).le.13)then consta(2,m) = (-2.452)*10.**33*Dg(m)**4+2.404*10.**27 & * Dg(m)**3+(-8.148)*10.**20*Dg(m)**2+(1.183)*10.**14 & * Dg(m)+(-6.743)*10.**6 constb(2,m) = 7.368*10.**35 & * Dg(m)**4+(-7.310)*10.**29*Dg(m)**3+ 2.528*10.**23 & * Dg(m)**2+(-3.787)*10.**16*Dg(m)+ 2.279*10.**9 elseif ((m).ge.14.and.(m).lt.22)then consta(3,m) = (1.085)*10.**29*Dg(m)**4+(-9.841)*10.**23 & * Dg(m)**3+(3.132)*10.**18*Dg(m)**2+(-4.165)*10.**12 & * Dg(m)+(2.181)*10.**6 constb(3,m) = (-2.859)*10.**31 & * Dg(m)**4+(2.601)*10.**26*Dg(m)**3+(-8.297)*10.**20 & * Dg(m)**2+(1.105)*10.**15*Dg(m)+(-5.800)*10.**8 elseif (m.ge.22.and.m.le.40)then ! use monahan consta(4,m) = (1.373*rm(m)**(-3)*(1+0.057*rm(m)**1.05) & * 10**(1.19*exp(-bm(m)**2))) & * (rm(m)-rm(m-1)) endif enddo #else ! gives source in units of kg/m2/s /(m/s)**3.41 sst_source(1)=4.77e-15_r8 sst_source(2)=5.19e-14_r8 sst_source(3)=1.22e-13_r8 sst_source(4)=6.91e-14_r8 #endif ix=ix_progseasalts do m = 1, nsst #if (defined MODAL_AERO) dummy = trim(cnst_name(ix-spc_ndx(1)+spc_ndx(m))) // 'SF' write(iulog,*)'m,ix,spc_ndx=',m,ix,spc_ndx(m),' dummy=',dummy call addfld (dummy,'kg/m2/s ',1, 'A',trim(cnst_name(ix-spc_ndx(1)+spc_ndx(m)))//' progseasalts surface emission',phys_decomp) call add_default (dummy, 1, ' ') #else dummy = trim(cnst_name(ix-1+m)) call addfld (dummy,'kg/kg ',pver, 'A',trim(cnst_name(ix-1+m))//' progseasalts mixing ratio',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'SF' call addfld (dummy,'kg/m2/s ',1, 'A',trim(cnst_name(ix-1+m))//' progseasalts surface emission',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'OD' call addfld (dummy,'Tau ',1, 'A',trim(cnst_name(ix-1+m))//' optical depth',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'TB' call addfld (dummy,'kg/m2/s ',1, 'A',trim(cnst_name(ix-1+m))//' turbulent dry deposition flux',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'GV' call addfld (dummy,'kg/m2/s ',1, 'A',trim(cnst_name(ix-1+m))//' gravitational dry deposition flux',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'DD' call addfld (dummy,'kg/m2/s ',1, 'A',trim(cnst_name(ix-1+m))//' dry deposition flux at bottom (grav + turb)',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'DT' call addfld (dummy,'kg/kg/s ',pver, 'A',trim(cnst_name(ix-1+m))//' dry deposition',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'PP' call addfld (dummy,'kg/kg/s ',pver, 'A',trim(cnst_name(ix-1+m))//' wet deposition',phys_decomp) call add_default (dummy, 1, ' ') dummy = trim(cnst_name(ix-1+m)) // 'DV' call addfld (dummy,'m/s ',pver, 'A',trim(cnst_name(ix-1+m))//' deposition velocity',phys_decomp) call add_default (dummy, 1, ' ') #if defined ( debugseasalts) dummy = trim(cnst_name(ix-1+m)) // 'DI' call addfld (dummy,'m/s ',pver, 'A',trim(cnst_name(ix-1+m))//' deposition diameter',phys_decomp) call add_default (dummy, 1, ' ') #endif #endif end do dummy = 'SSTSFDRY' call addfld (dummy,'kg/m2/s',1, 'A','Dry deposition flux at surface',phys_decomp) call add_default (dummy, 1, ' ') dummy = 'SSTSFMBL' call addfld (dummy,'kg/m2/s',1, 'A','Mobilization flux at surface',phys_decomp) call add_default (dummy, 1, ' ') dummy = 'SSTSFWET' call addfld (dummy,'kg/m2/s',1, 'A','Wet deposition flux at surface',phys_decomp) call add_default (dummy, 1, ' ') dummy = 'SSTODXC' call addfld (dummy,'Tau ',1, 'A','Optical depth for diagnostics',phys_decomp) call add_default (dummy, 1, ' ') #if defined ( debugseasalts) dummy = 'RH' call addfld (dummy,'frac',pver, 'A','RH in dry dep calc',phys_decomp) call add_default (dummy, 1, ' ') #endif if (masterproc) then write(iulog,*) 'Initializing Prog seasalts' write(iulog,*) ' start index for progseasalts is ', ix_progseasalts write(iulog,*) ' sst_source',sst_source end if end subroutine progseasalts_initialize !=============================================================================== subroutine progseasalts_wet_intr (state, ptend, nstep, dt, lat, clat, cme, prain, & 1,8 evapr, cldv, cldc, cldn, fracis, calday, cmfdqr, conicw, rainmr ) !----------------------------------------------------------------------- ! ! Purpose: ! Interface to wet processing of aerosols (source and sinks). ! ! Method: ! <Describe the algorithm(s) used in the routine.> ! <Also include any applicable external references.> ! ! Author: B.A. Boville ! !----------------------------------------------------------------------- use cam_history, only: outfld use physics_types, only: physics_state, physics_ptend use wetdep, only: wetdepa_v1 !----------------------------------------------------------------------- implicit none !----------------------------------------------------------------------- ! ! Arguments: ! real(r8), intent(in) :: dt ! time step type(physics_state), intent(in ) :: state ! Physics state variables integer, intent(in) :: nstep integer, intent(in) :: lat(pcols) ! latitude index for S->N storage real(r8), intent(in) :: clat(pcols) ! latitude real(r8), intent(in) :: cme(pcols,pver) ! local condensation of cloud water real(r8), intent(in) :: prain(pcols,pver) ! production of rain real(r8), intent(in) :: evapr(pcols,pver) ! evaporation of rain real(r8), intent(in) :: cldn(pcols,pver) ! cloud fraction real(r8), intent(in) :: cldc(pcols,pver) ! convective cloud fraction real(r8), intent(in) :: cldv(pcols,pver) ! cloudy volume undergoing scavenging type(physics_ptend), intent(inout) :: ptend ! indivdual parameterization tendencies real(r8), intent(inout) :: fracis(pcols,pver,pcnst) ! fraction of transported species that are insoluble ! ! Local variables ! integer :: lchnk ! chunk identifier integer :: ncol ! number of atmospheric columns integer :: ix real(r8) :: tstate(pcols, pver, 4) ! temporary state vector real(r8), intent(in) :: conicw(pcols, pver) real(r8), intent(in) :: cmfdqr(pcols, pver) real(r8), intent(in) :: rainmr(pcols, pver) ! rain mixing ratio real(r8) :: sflx(pcols) ! deposition flux real(r8) :: obuf(1) real(r8) :: calday ! current calendar day real(r8) :: iscavt(pcols, pver) real(r8) :: scavt(pcols, pver) integer :: yr, mon, day, ncsec integer :: ncdate integer :: mm,i,k integer :: m ! tracer index integer :: ixcldliq integer :: ixcldice real(r8) totcond(pcols, pver) ! total condensate real(r8) :: sol_fact real(r8) scavcoef(pcols,pver) ! ! Dana and Hales coefficient (/mm) (0.1) !----------------------------------------------------------------------- lchnk = state%lchnk ncol = state%ncol sflx(:)=0._r8 scavcoef(:ncol,:) = 0.1_r8 call cnst_get_ind('CLDICE', ixcldice) call cnst_get_ind('CLDLIQ', ixcldliq) totcond(:ncol,:) = state%q(:ncol,:,ixcldliq) + state%q(:ncol,:,ixcldice) do m = 1, nsst if (progseasalts_has_wet_dep(m) ) then mm = ix_progseasalts + m - 1 scavt=0._r8 ! write(iulog,*) 'wet dep removed for debugging' ptend%lq(mm) = .TRUE. ptend%name = trim(ptend%name)//',sslt' sol_fact = 0.3_r8 call wetdepa_v1( state%t, state%pmid, state%q, state%pdel, & cldn, cldc, cmfdqr, conicw, prain, cme, & evapr, totcond, state%q(:,:,mm), dt, & scavt, iscavt, cldv, fracis(:,:,mm), sol_fact, ncol, & scavcoef ) ptend%q(:ncol,:,mm)=scavt(:ncol,:) call outfld( trim(cnst_name(mm))//'PP', ptend%q(:,:,mm), pcols, lchnk) ! write(iulog,*) ' range of ptend ix ', minval(ptend%q(:ncol,:,mm)),maxval(ptend%q(:ncol,:,mm)) do k=1,pver do i=1,ncol sflx(i)=sflx(i)+ptend%q(i,k,mm)*state%pdel(i,k)/gravit enddo enddo endif end do call outfld( 'SSTSFWET', sflx, pcols, lchnk) ! write(iulog,*) ' progseasalts_wet_intr: pcols, pcols ', pcols, pcols return end subroutine progseasalts_wet_intr subroutine progseasalts_drydep_intr (state, ptend, wvflx, dt, lat, clat, & 1,18 fsds, obklen, ts, ustar, prect, snowh, pblh, hflx, month, landfrac, & icefrac, ocnfrac,fvin,ram1in) !----------------------------------------------------------------------- ! ! Purpose: ! Interface to dry deposition and sedimentation of progseasalts ! ! Method: ! <Describe the algorithm(s) used in the routine.> ! <Also include any applicable external references.> ! ! Author: Natalie Mahowald and Phil Rasch ! !----------------------------------------------------------------------- use cam_history, only: outfld use physics_types, only: physics_state, physics_ptend use phys_grid, only: get_lat_all_p use constituents, only: cnst_name use drydep_mod, only: d3ddflux use dust_sediment_mod, only: dust_sediment_tend, dust_sediment_vel !----------------------------------------------------------------------- implicit none !----------------------------------------------------------------------- ! ! Arguments: ! real(r8), intent(in) :: dt ! time step type(physics_state), intent(in ) :: state ! Physics state variables integer, intent(in) :: lat(pcols) ! latitude index for S->N storage real(r8), intent(in) :: clat(pcols) ! latitude real(r8), intent(in) :: fsds(pcols) ! longwave down at sfc real(r8), intent(in) :: obklen(pcols) ! obklen real(r8), intent(in) :: ustar(pcols) ! sfc fric vel--used over oceans and sea ice. real(r8), intent(in) :: ts(pcols) ! sfc temp real(r8), intent(in) :: landfrac(pcols) ! land fraction real(r8), intent(in) :: icefrac(pcols) ! ice fraction real(r8), intent(in) :: ocnfrac(pcols) ! ocean fraction real(r8), intent(in) :: hflx(pcols) ! sensible heat flux real(r8), intent(in) :: prect(pcols) ! prect real(r8), intent(in) :: snowh(pcols) ! snow depth real(r8), intent(in) :: pblh(pcols) ! pbl height integer, intent(in) :: month real(r8), intent(in) :: wvflx(pcols) ! water vapor flux real(r8), intent(in) :: fvin(pcols) ! for dry dep velocities from land model for progseasalts real(r8), intent(in) :: ram1in(pcols) ! for dry dep velocities from land model for progseasalts type(physics_ptend), intent(inout) :: ptend ! indivdual parameterization tendencies ! ! Local variables ! integer :: m ! tracer index integer :: mm ! tracer index integer :: ioff ! offset for ghg indices integer :: lchnk ! chunk identifier integer :: ncol ! number of atmospheric columns integer :: ix real(r8) :: tvs(pcols,pver) real(r8) :: dvel(pcols) ! deposition velocity real(r8) :: sflx(pcols) ! deposition flux real(r8) :: vlc_dry(pcols,pver,nsst) ! dep velocity real(r8) :: vlc_grv(pcols,pver,nsst) ! dep velocity real(r8):: vlc_trb(pcols,nsst) ! dep velocity real(r8):: dep_trb(pcols) !kg/m2/s real(r8):: dep_dry(pcols) !kg/m2/s (total of grav and trb) real(r8):: dep_grv(pcols) !kg/m2/s (total of grav and trb) real(r8):: dep_dry_tend(pcols,pver) !kg/kg/s (total of grav and trb) real(r8) :: obuf(1) real (r8) :: rho(pcols,pver) ! air density in kg/m3 real(r8) pvprogseasalts(pcols,pverp) ! sedimentation velocity in Pa real(r8) :: tsflx(pcols) real(r8) :: fv(pcols) ! for dry dep velocities, from land modified over ocean & ice real(r8) :: ram1(pcols) ! for dry dep velocities, from land modified over ocean & ice integer :: i,k real(r8) :: oro(pcols) ! !----------------------------------------------------------------------- ix = progseasalts_idx1() ioff = ix - 1 lchnk = state%lchnk ncol = state%ncol tvs(:ncol,:) = state%t(:ncol,:)!*(1+state%q(:ncol,k) rho(:ncol,:)= state%pmid(:ncol,:)/(rair*state%t(:ncol,:)) ! calculate oro--need to run match !!$ do i=1,ncol !!$ oro(i)=1._r8 !!$ if(icefrac(i)>0.5) oro(i)=2._r8 !!$ if(ocnfrac(i)>0.5) oro(i)=0._r8 !!$ enddo !!$ call outfld( 'ORO', oro, pcols, lchnk ) ! write(iulog,*) ' progseasalts drydep invoked ' ! Dry deposition of Progseasalts Aerosols ! ################################# ! call setdvel( ncol, landfrac, icefrac, ocnfrac, .001_r8, .001_r8, .001_r8, dvel ) ! we get the ram1,fv from the land model as ram1in,fvin,, but need to calculate it over oceans and ice. ! better if we got thse from the ocean and ice model ! for friction velocity, we use ustar (from taux and tauy), except over land, where we use fv from the land model. ! copy fv,ram1 values from land model to variables to modify in calcram ! fv = fvin ! ram1 = ram1in call calcram(ncol,landfrac,icefrac,ocnfrac,obklen,& ustar,ram1in,ram1,state%t(:,pver),state%pmid(:,pver),& state%pdel(:,pver),fvin,fv) ! this is the same as in the dust model--perhaps there is someway to !calculate them up higher in the model !!$ call outfld( 'airFV', fv(:), pcols, lchnk ) !!$ call outfld( 'RAM1', ram1(:), pcols, lchnk ) ! call outfld( 'icefrc', icefrac(:), pcols, lchnk ) call ProgseasaltsDryDep(ncol,state%t(:,:),state%pmid(:,:),ram1,fv,vlc_dry,vlc_trb,vlc_grv,state) tsflx(:)=0._r8 do m=1,nsst mm = progseasalts_idx1() + m - 1 ! use pvprogseasalts instead (means making the top level 0) pvprogseasalts(:ncol,1)=0._r8 pvprogseasalts(:ncol,2:pverp) = vlc_dry(:ncol,:,m) call outfld( trim(cnst_name(mm))//'DV', pvprogseasalts(:,2:pverp), pcols, lchnk ) if(.true.) then ! use phil's method ! convert from meters/sec to pascals/sec ! pvprogseasalts(:,1) is assumed zero, use density from layer above in conversion pvprogseasalts(:ncol,2:pverp) = pvprogseasalts(:ncol,2:pverp) * rho(:ncol,:)*gravit ! calculate the tendencies and sfc fluxes from the above velocities call dust_sediment_tend( & ncol, dt, state%pint(:,:), state%pmid, state%pdel, state%t , & state%q(:,:,mm) , pvprogseasalts , ptend%q(:,:,mm), sflx ) else !use charlie's method call d3ddflux(ncol, vlc_dry(:,:,m), state%q(:,:,mm),state%pmid,state%pdel, tvs,sflx,ptend%q(:,:,mm),dt) endif ! apportion dry deposition into turb and gravitational settling for tapes do i=1,ncol dep_trb(i)=sflx(i)*vlc_trb(i,m)/vlc_dry(i,pver,m) dep_grv(i)=sflx(i)*vlc_grv(i,pver,m)/vlc_dry(i,pver,m) enddo tsflx(:ncol)=tsflx(:ncol)+sflx(:ncol) call outfld( trim(cnst_name(mm))//'DD',sflx, pcols, lchnk) call outfld( trim(cnst_name(mm))//'TB', dep_trb, pcols, lchnk ) call outfld( trim(cnst_name(mm))//'GV', dep_grv, pcols, lchnk ) call outfld( trim(cnst_name(mm))//'DT',ptend%q(:,:,mm), pcols, lchnk) ! write(iulog,*) ' range of tends for progseasalts ', mm, minval(ptend%q(:ncol,:,mm)), maxval(ptend%q(:ncol,:,mm)) ! call outfld( trim(cnst_name(mm))//'DRY', sflx, pcols, lchnk) end do ! output the total dry deposition call outfld( 'SSTSFDRY', tsflx, pcols, lchnk) ! set flags for tendencies (water and 4 ghg's) ptend%name = ptend%name//'+progseasalts_drydep' ptend%lq(ioff+1:ioff+4) = .TRUE. return end subroutine progseasalts_drydep_intr !!$ subroutine progseasalts_time_interp !!$ !!$ use time_manager, only: get_curr_date, get_perp_date, get_curr_calday, & !!$ is_perpetual !!$ ! use progseasaltsbnd, only: progseasaltsbndint !!$ !!$ implicit none !!$ !!$ real(r8) calday !!$ integer :: yr, mon, day, ncsec !!$ !!$ if ( ix_progseasalts < 1 ) return !!$ !!$ calday = get_curr_calday() !!$ if ( is_perpetual() ) then !!$ call get_perp_date(yr, mon, day, ncsec) !!$ else !!$ call get_curr_date(yr, mon, day, ncsec) !!$ end if !!$ !!$ write(iulog,*) ' progseasalts_time_interp: interpolating progseasalts emissions ', calday !!$ ! call progseasaltsbndint(calday) ! interpolate oxidants !!$ !!$ !!$ end subroutine progseasalts_time_interp #if (defined MODAL_AERO) subroutine progseasalts_emis_intr (state, ptend, dt,cflx,ocnfrc,sst) 2,16 #else subroutine progseasalts_emis_intr (state, ptend, dt,cflx,ocnfrc) 2,16 #endif !----------------------------------------------------------------------- ! ! Purpose: ! Interface to emission of all progseasaltss. ! Derives from Xue Xie Tie's seasalts in MOZART, which derives from ! Chin et al., 2001 (JAS) and Gong et al., 1997 (JGR-102,3805-3818). ! ! Method: ! <Describe the algorithm(s) used in the routine.> ! <Also include any applicable external references.> ! ! Author: Phil Rasch and Natalie Mahowald ! ! Derives from Martensson et al. (2003) (JGR-108, 4297,doi:10.1029/2002JD002263) ! valid from 20nm to ~2500nm dry diameter (based on lab experiment with artificial sea water) ! ! currently we recommend that it is combined with ! the parameterisation by Monahan et al. (1986) for ! dry diameters > 2-3 um even if it lacks ! temperature dependence (despite that Bowyer et ! al. (1990) found a similar dependency in the tank ! from Monahan et al. (1986)) ! !----------------------------------------------------------------------- use cam_history, only: outfld use physics_types, only: physics_state, physics_ptend use phys_grid, only: get_lon_all_p, get_lat_all_p, get_rlat_all_p use time_manager, only: get_curr_date, get_perp_date, get_curr_calday, & is_perpetual #if (defined MODAL_AERO) use physconst, only: pi #endif ! use progseasalts, only: progseasaltssf !----------------------------------------------------------------------- implicit none !----------------------------------------------------------------------- ! ! Arguments: ! real(r8), intent(in) :: dt ! time step type(physics_state), intent(in ) :: state ! Physics state variables type(physics_ptend), intent(inout) :: ptend ! indivdual parameterization tendencies real(r8), intent(inout) :: cflx(pcols,pcnst) real(r8):: ocnfrc(pcols) #if (defined MODAL_AERO) real(r8), intent(in):: sst(pcols) ! sea surface temp for Ekman's ss #endif integer lat(pcols) ! latitude index integer lon(pcols) ! longitude index integer lchnk integer ncol integer i integer m,mm real(r8):: sflx(pcols) ! accumulate over all bins for output real(r8) :: soil_erod_tmp(pcols) real(r8) :: u10cubed(pcols) ! real (r8), parameter :: z0=0.5 ! m roughness length over oceans--from Tie. real (r8), parameter :: z0=0.0001_r8 ! m roughness length over oceans--from ocean model ! #if (defined MODAL_AERO) ! use Ekman's ss real (r8) :: fi(pcols,sections) real (r8) :: W(pcols) #endif real(r8) :: calday ! current calendar day integer :: yr, mon, day, ncsec integer :: ncdate calday = get_curr_calday() if ( is_perpetual() ) then call get_perp_date(yr, mon, day, ncsec) else call get_curr_date(yr, mon, day, ncsec) end if lchnk = state%lchnk ncol = state%ncol call get_lat_all_p(lchnk, ncol, lat) call get_lon_all_p(lchnk, ncol, lon) sflx(:)=0._r8 u10cubed(:ncol)=sqrt(state%u(:ncol,pver)**2+state%v(:ncol,pver)**2) ! move the winds to 10m high from the midpoint of the gridbox: ! follows Tie and Seinfeld and Pandis, p.859 with math. u10cubed(:ncol)=u10cubed(:ncol)*log(10._r8/z0)/log(state%zm(:ncol,pver)/z0) ! we need them to the 3.41 power, according to Gong et al., 1997: u10cubed(:ncol)=u10cubed(:ncol)**3.41_r8 #if (defined MODAL_AERO) ! Calculations of source strength and size distribution ! NB the 0.1 is the dlogDp we have to multiplie with to get the flux, but the value dependence ! of course on what dlogDp you have. You will also have to change the sections of Dg if you use ! a different number of size bins with different intervals. W(:ncol)=3.84e-6_r8*u10cubed(:ncol)*0.1_r8 ! whitecap area ! calculate number flux fi (#/m2/s) fi(:,:)=0._r8 do m=1,sections if (m.le.9)then fi(:ncol,m)=W(:ncol)*((sst(:ncol))*consta(1,m)+constb(1,m)) elseif (m.ge.10.and.m.le.13)then fi(:ncol,m)=W(:ncol)*((sst(:ncol))*consta(2,m)+constb(2,m)) elseif (m.ge.14.and.m.lt.22)then fi(:ncol,m)=W(:ncol)*((sst(:ncol))*consta(3,m)+constb(3,m)) elseif (m.ge.22.and.m.le.40)then ! use Monahan fi(:ncol,m)=consta(4,m)*u10cubed(:ncol) endif enddo #endif do m=1,nsst #if (defined MODAL_AERO) if(spc_num_ndx(m) > 0) then mm=progseasalts_idx1()+spc_num_ndx(m)-spc_ndx(1) ! cflx(:ncol,mm)=0.0_r8 ! we need to include dst_a1, dst_a3 to num_a1 and num_a3 do i=1, sections if (Dg(i).ge.sst_sz_range_lo(m) .and. Dg(i).lt.sst_sz_range_hi(m)) then ! cflx(:ncol,mm)=cflx(:ncol,mm)+fi(:ncol,i)*ocnfrc(:ncol) cflx(:ncol,mm)=cflx(:ncol,mm)+fi(:ncol,i)*ocnfrc(:ncol)*1.35_r8 !++ ag: scale sea-salt endif enddo endif mm=progseasalts_idx1()+spc_ndx(m)-spc_ndx(1) cflx(:ncol,mm)=0.0_r8 do i=1, sections if (Dg(i).ge.sst_sz_range_lo(m) .and. Dg(i).lt.sst_sz_range_hi(m)) then cflx(:ncol,mm)=cflx(:ncol,mm)+fi(:ncol,i)*ocnfrc(:ncol)*1.35_r8 & !++ ag: scale sea-salt *4._r8/3._r8*pi*rdry(i)**3*dns_aer_sst ! should use dry size, convert from number to mass flux (kg/m2/s) endif enddo sflx(:ncol)=sflx(:ncol)+cflx(:ncol,mm) ! if(spc_num_ndx(m) > 0) then ! mm=progseasalts_idx1()+spc_num_ndx(m)-spc_ndx(1) ! cflx(:ncol,mm)=sst_source_num(m)* u10cubed(:ncol)*ocnfrc(:ncol) ! endif ! mm=progseasalts_idx1()+spc_ndx(m)-spc_ndx(1) ! cflx(:ncol,mm)=sst_source(m)* u10cubed(:ncol)*ocnfrc(:ncol) ! sflx(:ncol)=sflx(:ncol)+cflx(:ncol,mm) #else mm=progseasalts_idx1()+m-1 cflx(:ncol,mm)=sst_source(m)* u10cubed(:ncol)*ocnfrc(:ncol) sflx(:ncol)=sflx(:ncol)+cflx(:ncol,mm) #endif call outfld(trim(cnst_name(mm)) // 'SF',cflx(:,mm),pcols,lchnk) ! this is being done inside of the vertical diffusion automatically ! ptend%lq(m) = .true. ! tendencies for all progseasalts on ! ptend%q(:ncol,pver,mm) = cflx(:ncol,m)*gravit/state%pdel(:ncol,pver) enddo call outfld('SSTSFMBL',sflx(:),pcols,lchnk) ! write(42,*) cflx(1,1) return end subroutine progseasalts_emis_intr !------------------------------------------------------------------------ !BOP ! ! !IROUTINE: subroutine ProgseasaltsDryDep(c) ! ! !INTERFACE: ! subroutine ProgseasaltsDryDep(ncol,t,pmid,ram1,fv,vlc_dry,vlc_trb,vlc_grv,state) 1,7 ! ! !DESCRIPTION: ! ! Dry deposition for seasalts: modified from dust dry deposition following ! Xue Xie Tie's MOZART seasalts by NMM. Sam Levis did hte first dust dry ! deposition in CLM/CCSM2 from Charlie Zender's codes, modified by NMM for CAM. ! Sam's Notes in CLM: ! Determine Turbulent dry deposition for progseasalts. Calculate the turbulent ! component of progseasalts dry deposition, (the turbulent deposition velocity ! through the lowest atmospheric layer. CAM will calculate the settling ! velocity through the whole atmospheric column. The two calculations ! will determine the progseasalts dry deposition flux to the surface. ! Note: Same process should occur over oceans. For the coupled CCSM, ! we may find it more efficient to let CAM calculate the turbulent dep ! velocity over all surfaces. This would require passing the ! aerodynamic resistance, ram(1), and the friction velocity, fv, from ! the land to the atmosphere component. In that case, progseasaltsini need not ! calculate particle diamter (dmt_vwr) and particle density (dns_aer). ! Source: C. Zender's dry deposition code ! Note that because sea salts' radius changes with humidity we cannot ! precalculate slip coefficients, etc. in the initialization subroutine, but ! we have to calculate them at the time--how slow??? ! ! !USES ! use physconst, only: rair,pi,boltz use wv_saturation, only: aqsat use physics_types, only: physics_state, physics_ptend use cam_history, only: outfld ! !ARGUMENTS: ! implicit none ! real(r8) :: t(pcols,pver) !atm temperature (K) real(r8) :: pmid(pcols,pver) !atm pressure (Pa) real(r8) :: rho(pcols,pver) !atm density (kg/m**3) real(r8) :: fv(pcols) !friction velocity (m/s) real(r8) :: ram1(pcols) !aerodynamical resistance (s/m) real(r8) :: vlc_trb(pcols,nsst) !Turbulent deposn velocity (m/s) real(r8) :: vlc_grv(pcols,pver,nsst) !grav deposn velocity (m/s) real(r8) :: vlc_dry(pcols,pver,nsst) !dry deposn velocity (m/s) integer, intent(in) :: ncol type(physics_state), intent(in ) :: state ! Physics state variables ! ! !REVISION HISTORY ! Created by Sam Levis ! Modified for CAM by Natalie Mahowald ! Modified for Seasalts by NMM !EOP !------------------------------------------------------------------------ !------------------------------------------------------------------------ ! Local Variables integer :: m,i,k,ix,lchnk !indices real(r8) :: vsc_dyn_atm(pcols,pver) ![kg m-1 s-1] Dynamic viscosity of air real(r8) :: vsc_knm_atm(pcols,pver) ![m2 s-1] Kinematic viscosity of atmosphere real(r8) :: shm_nbr_xpn ![frc] Sfc-dep exponent for aerosol-diffusion dependence on Schmidt number real(r8) :: shm_nbr ![frc] Schmidt number real(r8) :: stk_nbr ![frc] Stokes number real(r8) :: mfp_atm(pcols,pver) ![m] Mean free path of air real(r8) :: dff_aer ![m2 s-1] Brownian diffusivity of particle real(r8) :: rss_trb ![s m-1] Resistance to turbulent deposition real(r8) :: slp_crc(pcols,pver,nsst) ![frc] Slip correction factor real(r8) :: rss_lmn(nsst) ![s m-1] Quasi-laminar layer resistance real(r8) :: tmp ,r !temporary real(r8) :: wetdia(pcols,pver,nsst) ! wet diameter of seasalts real(r8) :: RH(pcols,pver),es(pcols,pver),qs(pcols,pver) ! for wet radius calculation ! constants real(r8),parameter::shm_nbr_xpn_lnd=-2._r8/3._r8 ![frc] shm_nbr_xpn over land real(r8),parameter::shm_nbr_xpn_ocn=-1._r8/2._r8 ![frc] shm_nbr_xpn over ccean real(r8),parameter:: c1=0.7674_r8, c2=3.0790_r8, c3=2.57e-11_r8,c4=-1.424_r8 ! wet radius calculation constants ! needs fv and ram1 passed in from lnd model !------------------------------------------------------------------------ call aqsat(state%t,state%pmid,es,qs,pcols,ncol,pver,1,pver) RH(:ncol,:)=state%q(:ncol,:,1)/qs(:ncol,:) RH(:ncol,:)=max(0.01_r8,min(0.99_r8,RH(:ncol,:))) ! set stokes correction to 1.0 for now not a bad assumption for our size range) do m=1,nsst stk_crc(m)=1._r8 enddo do k=1,pver do i=1,ncol rho(i,k)=pmid(i,k)/rair/t(i,k) ! from subroutine dst_dps_dry (consider adding sanity checks from line 212) ! when code asks to use midlayer density, pressure, temperature, ! I use the data coming in from the atmosphere, ie t(i,k), pmid(i,k) ! Quasi-laminar layer resistance: call rss_lmn_get ! Size-independent thermokinetic properties vsc_dyn_atm(i,k) = 1.72e-5_r8 * ((t(i,k)/273.0_r8)**1.5_r8) * 393.0_r8 / & (t(i,k)+120.0_r8) ![kg m-1 s-1] RoY94 p. 102 mfp_atm(i,k) = 2.0_r8 * vsc_dyn_atm(i,k) / & ![m] SeP97 p. 455 (pmid(i,k)*sqrt(8.0_r8/(pi*rair*t(i,k)))) vsc_knm_atm(i,k) = vsc_dyn_atm(i,k) / rho(i,k) ![m2 s-1] Kinematic viscosity of air do m = 1, nsst r=smt_vwr(m)/2.0_r8 wetdia(i,k,m)=((r**3+c1*r**c2/(c3*r**c4-log(RH(i,k))))**(1._r8/3._r8))*2.0_r8 slp_crc(i,k,m) = 1.0_r8 + 2.0_r8 * mfp_atm(i,k) * & (1.257_r8+0.4_r8*exp(-1.1_r8*wetdia(i,k,m)/(2.0_r8*mfp_atm(i,k)))) / & wetdia(i,k,m) ![frc] Slip correction factor SeP97 p. 464 vlc_grv(i,k,m) = (1.0_r8/18.0_r8) * wetdia(i,k,m) * wetdia(i,k,m) * dns_aer_sst * & gravit * slp_crc(i,k,m) / vsc_dyn_atm(i,k) ![m s-1] Stokes' settling velocity SeP97 p. 466 vlc_grv(i,k,m) = vlc_grv(i,k,m) * stk_crc(m) ![m s-1] Correction to Stokes settling velocity vlc_dry(i,k,m)=vlc_grv(i,k,m) end do enddo enddo k=pver ! only look at bottom level for next part do m = 1, nsst do i=1,ncol r=smt_vwr(m)/2.0_r8 wetdia(i,k,m)=((r**3+c1*r**c2/(c3*r**c4-log(RH(i,k))))**(1._r8/3._r8))*2.0_r8 stk_nbr = vlc_grv(i,k,m) * fv(i) * fv(i) / (gravit*vsc_knm_atm(i,k)) ![frc] SeP97 p.965 dff_aer = boltz * t(i,k) * slp_crc(i,k,m) / & ![m2 s-1] (3.0_r8*pi*vsc_dyn_atm(i,k)*wetdia(i,k,m)) !SeP97 p.474 shm_nbr = vsc_knm_atm(i,k) / dff_aer ![frc] SeP97 p.972 shm_nbr_xpn = shm_nbr_xpn_lnd ![frc] ! if(ocnfrac.gt.0.5) shm_nbr_xpn=shm_nbr_xpn_ocn ! fxm: Turning this on dramatically reduces ! deposition velocity in low wind regimes ! Schmidt number exponent is -2/3 over solid surfaces and ! -1/2 over liquid surfaces SlS80 p. 1014 ! if (oro(i)==0.0) shm_nbr_xpn=shm_nbr_xpn_ocn else shm_nbr_xpn=shm_nbr_xpn_lnd ! [frc] Surface-dependent exponent for aerosol-diffusion dependence on Schmidt # tmp = shm_nbr**shm_nbr_xpn + 10.0_r8**(-3.0_r8/stk_nbr) rss_lmn(m) = 1.0_r8 / (tmp*fv(i)) ![s m-1] SeP97 p.972,965 rss_trb = ram1(i) + rss_lmn(m) + ram1(i)*rss_lmn(m)*vlc_grv(i,k,m) ![s m-1] vlc_trb(i,m) = 1.0_r8 / rss_trb ![m s-1] vlc_dry(i,k,m) = vlc_trb(i,m) +vlc_grv(i,k,m) end do !ncol end do #if defined ( debugseasalts) ! debugging options for wetdiameter depedence on relative humidity lchnk = state%lchnk ix=ix_progseasalts do m=1,4 call outfld( trim(cnst_name(m+ix-1))//'DI',wetdia(:,:,m), pcols, lchnk) enddo call outfld( 'RH',RH(:,:), pcols, lchnk) #endif return end subroutine ProgseasaltsDryDep #if (defined MODAL_AERO) subroutine seasalt_emitfactors_1bin( ireduce_smallr_emit, &,1 dpdrylo_cm, dpdryhi_cm, drydens, emitfact_numb, emitfact_mass ) !c !c computes seasalt emissions factors for a specifed !c dry particle size range !c dpdrylo_cm = lower dry diameter (cm) !c dpdryhi_cm = upper dry diameter (cm) !c !c number and mass emissions are then computed as !c number emissions (#/m2/s) == emitfact_numb * (u10*3.41) !c dry-mass emissions (g/m2/s) == emitfact_mass * (u10*3.41) !c !c where u10 = 10 m windspeed in m/s !c !c uses bubble emissions formula (eqn 5a) from !c Gong et al. [JGR, 1997, p 3805-3818] !c !c *** for rdry < rdry_star, this formula overpredicts emissions. !c A strictly ad hoc correction is applied to the formula, !c based on sea-salt size measurements of !c O'Dowd et al. [Atmos Environ, 1997, p 73-80] !c !c *** the correction is only applied when ireduce_smallr_emit > 0 !c use mo_constants, only : pi implicit none !c subr arguments integer ireduce_smallr_emit real(r8), intent(in) :: dpdrylo_cm, dpdryhi_cm, drydens real(r8), intent(out) :: emitfact_numb, emitfact_mass !c local variables integer isub_bin, nsub_bin real(r8) :: alnrdrylo real(r8) :: drydens_43pi_em12 real(r8) :: dum, dumadjust, dumb, dumexpb real(r8) :: dumsum_na, dumsum_ma real(r8) :: drwet, dlnrdry real(r8) :: df0drwet, df0dlnrdry, df0dlnrdry_star real(r8) :: relhum real(r8) :: rdry, rdrylo, rdryhi, rdryaa, rdrybb real(r8) :: rdrylowermost, rdryuppermost, rdry_star real(r8) :: rwet, rwetaa, rwetbb real(r8) :: rdry_cm, rwet_cm real(r8) :: sigmag_star real(r8) :: xmdry real(r8),parameter:: c1=0.7674_r8, c2=3.0790_r8, c3=2.57e-11_r8,c4=-1.424_r8 ! wet radius calculation constants !c factor for radius (micrometers) to mass (g) drydens_43pi_em12 = drydens*(4.0_r8/3.0_r8)*pi*1.0e-12_r8 !c bubble emissions formula assume 80% RH relhum = 0.80_r8 !c rdry_star = dry radius (micrometers) below which the !c dF0/dr emission formula is adjusted downwards rdry_star = 0.1_r8 if (ireduce_smallr_emit .le. 0) rdry_star = -1.0e20_r8 !c sigmag_star = geometric standard deviation used for !c rdry < rdry_star sigmag_star = 1.9_r8 !c initialize sums dumsum_na = 0.0_r8 dumsum_ma = 0.0_r8 !c rdrylowermost, rdryuppermost = lower and upper !c dry radii (micrometers) for overall integration rdrylowermost = dpdrylo_cm*0.5e4_r8 rdryuppermost = dpdryhi_cm*0.5e4_r8 !c !c "section 1" !c integrate over rdry > rdry_star, where the dF0/dr emissions formula is applicable !c (when ireduce_smallr_emit <= 0, rdry_star = -1.0e20, !c and the entire integration is done here) !c if (rdryuppermost .le. rdry_star) goto 2000 !c rdrylo, rdryhi = lower and upper dry radii (micrometers) !c for this part of the integration rdrylo = max( rdrylowermost, rdry_star ) rdryhi = rdryuppermost nsub_bin = 1000 alnrdrylo = log( rdrylo ) dlnrdry = (log( rdryhi ) - alnrdrylo)/nsub_bin !c compute rdry, rwet (micrometers) at lowest size rdrybb = exp( alnrdrylo ) rdry_cm = rdrybb*1.0e-4_r8 rwet_cm = ( rdry_cm**3 + (c1*(rdry_cm**c2))/ & ( (c3*(rdry_cm**c4)) - log10(relhum) ) )**0.333_r8 rwetbb = rwet_cm*1.0e4_r8 do 1900 isub_bin = 1, nsub_bin !c rdry, rwet at sub_bin lower boundary are those !c at upper boundary of previous sub_bin rdryaa = rdrybb rwetaa = rwetbb !c compute rdry, rwet (micrometers) at sub_bin upper boundary dum = alnrdrylo + isub_bin*dlnrdry rdrybb = exp( dum ) rdry_cm = rdrybb*1.0e-4_r8 rwet_cm = ( rdry_cm**3 + (c1*(rdry_cm**c2))/ & ( (c3*(rdry_cm**c4)) - log10(relhum) ) )**0.333_r8 rwetbb = rwet_cm*1.0e4_r8 !c geometric mean rdry, rwet (micrometers) for sub_bin rdry = sqrt(rdryaa * rdrybb) rwet = sqrt(rwetaa * rwetbb) drwet = rwetbb - rwetaa !c xmdry is dry mass in g xmdry = drydens_43pi_em12 * (rdry**3.0) !c dumb is "B" in Gong's Eqn 5a !c df0drwet is "dF0/dr" in Gong's Eqn 5a dumb = ( 0.380 - log10(rwet) ) / 0.650 dumexpb = exp( -dumb*dumb) df0drwet = 1.373_r8 * (rwet**(-3.0_r8)) * & (1.0_r8 + 0.057_r8*(rwet**1.05_r8)) * & (10.**(1.19*dumexpb)) dumsum_na = dumsum_na + drwet*df0drwet dumsum_ma = dumsum_ma + drwet*df0drwet*xmdry 1900 continue !c !c "section 2" !c integrate over rdry < rdry_star, where the dF0/dr emissions !c formula is just an extrapolation and predicts too many emissions !c !c 1. compute dF0/dln(rdry) = (dF0/drwet)*(drwet/dlnrdry) !c at rdry_star !c 2. for rdry < rdry_star, assume dF0/dln(rdry) is lognormal, !c with the same lognormal parameters observed in !c O'Dowd et al. [1997] !c 2000 if (rdrylowermost .ge. rdry_star) goto 3000 !c compute dF0/dln(rdry) at rdry_star rdryaa = 0.99_r8*rdry_star rdry_cm = rdryaa*1.0e-4_r8 rwet_cm = ( rdry_cm**3 + (c1*(rdry_cm**c2))/ & ( (c3*(rdry_cm**c4)) - log10(relhum) ) )**0.333_r8 rwetaa = rwet_cm*1.0e4_r8 rdrybb = 1.01_r8*rdry_star rdry_cm = rdrybb*1.0e-4_r8 rwet_cm = ( rdry_cm**3 + (c1*(rdry_cm**c2))/ & ( (c3*(rdry_cm**c4)) - log10(relhum) ) )**0.333_r8 rwetbb = rwet_cm*1.0e4_r8 rwet = 0.5_r8*(rwetaa + rwetbb) dumb = ( 0.380 - log10(rwet) ) / 0.650 dumexpb = exp( -dumb*dumb) df0drwet = 1.373_r8 * (rwet**(-3.0_r8)) * & (1.0_r8 + 0.057_r8*(rwet**1.05_r8)) * & (10.0**(1.19*dumexpb)) drwet = rwetbb - rwetaa dlnrdry = log( rdrybb/rdryaa ) df0dlnrdry_star = df0drwet * (drwet/dlnrdry) !c rdrylo, rdryhi = lower and upper dry radii (micrometers) !c for this part of the integration rdrylo = rdrylowermost rdryhi = min( rdryuppermost, rdry_star ) nsub_bin = 1000 alnrdrylo = log( rdrylo ) dlnrdry = (log( rdryhi ) - alnrdrylo)/nsub_bin do 2900 isub_bin = 1, nsub_bin !c geometric mean rdry (micrometers) for sub_bin dum = alnrdrylo + (isub_bin-0.5)*dlnrdry rdry = exp( dum ) !c xmdry is dry mass in g xmdry = drydens_43pi_em12 * (rdry**3.0_r8) !c dumadjust is adjustment factor to reduce dF0/dr dum = log( rdry/rdry_star ) / log( sigmag_star ) dumadjust = exp( -0.5_r8*dum*dum ) df0dlnrdry = df0dlnrdry_star * dumadjust dumsum_na = dumsum_na + dlnrdry*df0dlnrdry dumsum_ma = dumsum_ma + dlnrdry*df0dlnrdry*xmdry 2900 continue !c !c all done !c 3000 emitfact_numb = dumsum_na*1.35_r8 !++ ag: scale sea-salt emitfact_mass = dumsum_ma*1.35_r8 !++ ag: scale sea-salt return end subroutine seasalt_emitfactors_1bin #endif end module progseasalts_intr