module mo_aerosols !----------------------------------------------------------------- ! ! this module computes the production of ammonium nitrate ! using the formulation by Seinfeld and Pandis (p531, 1998) ! with the simplification of activity coefficients and ! aerosol molality using the parameterizations ! from Metzger et al. (JGR, ACH-16, 107(D16), 2002) ! ! written by Jean-Francois Lamarque (April 2004) ! adapted for CAM (May 2004) ! !----------------------------------------------------------------- use shr_kind_mod, only : r8 => shr_kind_r8 use ppgrid, only : pver use cam_logfile, only: iulog private public :: aerosols_inti,aerosols_formation public :: has_aerosols save integer, target :: spc_ndx(5) integer, pointer :: nh3_ndx, nh4no3_ndx, nh4_ndx integer, pointer :: so4_ndx, hno3_ndx integer :: xhno3_ndx, xnh4no3_ndx integer :: nu_i(2) real(r8) :: zeta_inv real(r8) :: z_i(2) logical :: has_aerosols = .true. contains subroutine aerosols_inti() use mo_chem_utls, only : get_spc_ndx use cam_history, only : addfld, phys_decomp use spmd_utils, only : masterproc implicit none !----------------------------------------------------------------- ! ... local variables !----------------------------------------------------------------- integer :: m nh3_ndx => spc_ndx(1) nh4no3_ndx => spc_ndx(2) so4_ndx => spc_ndx(3) hno3_ndx => spc_ndx(4) nh4_ndx => spc_ndx(5) !----------------------------------------------------------------- ! ... set species index !----------------------------------------------------------------- nh3_ndx = get_spc_ndx( 'NH3' ) nh4no3_ndx = get_spc_ndx( 'NH4NO3' ) so4_ndx = get_spc_ndx( 'SO4' ) hno3_ndx = get_spc_ndx( 'HNO3' ) nh4_ndx = get_spc_ndx( 'NH4' ) xnh4no3_ndx = get_spc_ndx( 'XNH4NO3' ) xhno3_ndx = get_spc_ndx( 'XHNO3' ) has_aerosols = all( spc_ndx(:) > 0 ) if( .not. has_aerosols ) then if (masterproc) then write(iulog,*) '-----------------------------------------' write(iulog,*) 'mozart will NOT do nh4no3' write(iulog,*) 'following species are missing' do m = 1,size(spc_ndx) if( spc_ndx(m) < 1 ) then write(iulog,*) m end if end do write(iulog,*) '-----------------------------------------' endif return else if (masterproc) then write(iulog,*) '-----------------------------------------' write(iulog,*) 'mozart will do nh4no3' write(iulog,*) '-----------------------------------------' end if end if ! ! define parameters ! ! ammonium nitrate (NH4NO3) ! zeta_inv = 1._r8/4._r8 nu_i(1) = 4 z_i (1) = 1._r8 ! ! ammonium sulfate ! nu_i(2) = 4 z_i (2) = 0.5_r8 call addfld ('TSO4_VMR', 'mol/mol',pver, 'A','total sulfate in mo_aerosols',phys_decomp) call addfld ('THNO3_VMR','mol/mol',pver, 'A','total nitric acid in mo_aerosols',phys_decomp) return end subroutine aerosols_inti subroutine aerosols_formation( ncol, lchnk, index_lat, index_lon, tfld, rh, qin) use ppgrid, only : pcols, pver use chem_mods, only : gas_pcnst, adv_mass use wv_saturation, only : aqsat use cam_history, only : outfld implicit none ! ! input arguments ! ! ! input arguments ! integer, intent(in) :: ncol ! number columns in chunk integer, intent(in) :: lchnk ! chunk index integer, intent(in) :: index_lat(pcols) ! chunk lat indicies integer, intent(in) :: index_lon(pcols) ! chunk lon indicies real(r8), intent(in) :: tfld(pcols,pver) ! temperature real(r8), intent(in) :: rh(ncol,pver) ! relative humidity real(r8), intent(inout) :: qin(ncol,pver,gas_pcnst) ! xported species ( vmr ) ! ! local variables ! integer :: i,j,k,n,ii,jj integer :: domain_number ! concentration domain real(r8) :: sulfate_state ! fraction of sulfate neutralized by ammonia real(r8), dimension(ncol,pver) :: tso4, & ! total sulfate thno3,& ! total nitric acid txhno3 ! total nitric acid ( XHNO3 ) real(r8) :: tnh3, & ! total ammonia fnh3, & ! free ammonia rhd, & ! relative humidity of deliquescence gamma, & ! activity coefficient ssm_nh4no3, & ! single solute molality for NH4NO3 ta, & ! total ammonia tn, & ! total nitrate kp, & ! equilibrium constant nh4no3 ! ammonium nitrate produced real(r8) :: log_t real(r8) :: ti real(r8) :: xnh4no3 do k=1,pver do i=1,ncol ii = index_lon(i) jj = index_lat(i) ! ! compute total concentrations ! tnh3 = (qin(i,k, nh3_ndx)+qin(i,k,nh4_ndx)) tso4(i,k) = qin(i,k,so4_ndx) ! ! define concentration domain ! if ( tnh3 < tso4(i,k) ) then domain_number = 4 sulfate_state = 1.0_r8 elseif ( tnh3 < 2._r8*tso4(i,k) ) then domain_number = 3 sulfate_state = 1.5_r8 else domain_number = 2 sulfate_state = 2.0_r8 endif ! ! define free ammonia (ammonia available for ammonium nitrate production) ! fnh3 = tnh3 - sulfate_state * tso4(i,k) fnh3 = max(0._r8,fnh3) ! ! convert initial concentrations to ppbv ! tso4(i,k) = tso4(i,k) * 1.e9_r8 tnh3 = tnh3 * 1.e9_r8 fnh3 = fnh3 * 1.e9_r8 thno3(i,k) = (qin(i,k,hno3_ndx)+qin(i,k,nh4no3_ndx)) * 1.e9_r8 if ( xhno3_ndx > 0 .and. xnh4no3_ndx > 0 ) then txhno3(i,k) = (qin(i,k,xhno3_ndx)+qin(i,k,xnh4no3_ndx)) * 1.e9_r8 endif ! ! compute relative humidity of deliquescence (%) for NH4NO3 ! (Seinfeld and Pandis, p532) ! ti = 1._r8/tfld(i,k) rhd = 0.01_r8 * exp( 1.6954_r8 + 723.7_r8*ti ) log_t = log( tfld(i,k)/298._r8 ) if ( rh(i,k) < rhd ) then ! ! crystalline ammonium nitrate ! ! compute equilibrium constant ! kp = exp( 84.6_r8 - 24220._r8*ti - 6.1_r8*log_t ) ! else ! ! aqueous phase ammonium nitrate ! ! compute activity coefficients (from Menzger et al.) ! n = domain_number gamma = (rh(i,k)**n/(1000._r8/n*(1._r8-rh(i,k))+n))**zeta_inv ! ! compute single solute molality for NH4NO3 ! ssm_nh4no3 = (1000._r8 * 0.81_r8 * nu_i(1) * (1._r8/rh(i,k)-1._r8)/80._r8)**z_i(1) ! ! compute equilibrium constant ! kp = (gamma*ssm_nh4no3)**2 * exp( 53.19_r8 - 15850.62_r8*ti + 11.51_r8*log_t ) endif ! ! calculate production of NH4NO3 (in ppbv) using Seinfeld and Pandis (p534, 1998) ! ta = fnh3 tn = thno3(i,k) nh4no3 = 0.5_r8 * (ta + tn - sqrt(max(0._r8,(ta+tn)**2 - 4._r8*(ta*tn-kp)))) nh4no3 = max(0._r8,nh4no3) if ( xhno3_ndx > 0 .and. xnh4no3_ndx > 0 ) then tn = txhno3(i,k) xnh4no3 = 0.5_r8 * (ta + tn - sqrt(max(0._r8,(ta+tn)**2 - 4._r8*(ta*tn-kp)))) xnh4no3 = max(0._r8,xnh4no3) endif ! ! reset concentrations according to equilibrium calculation ! qin(i,k,nh4no3_ndx) = nh4no3 if ( xhno3_ndx > 0 ) then qin(i,k,xnh4no3_ndx) = xnh4no3 endif qin(i,k,nh3_ndx ) = max(0._r8,(fnh3-nh4no3)) qin(i,k,nh4_ndx ) = max(0._r8,(tnh3-(fnh3-nh4no3))) qin(i,k,hno3_ndx ) = max(0._r8,(thno3(i,k)-nh4no3)) if ( xhno3_ndx > 0 ) then qin(i,k,xhno3_ndx ) = max(0._r8,(txhno3(i,k)-xnh4no3)) endif qin(i,k,so4_ndx ) = tso4(i,k) ! ! convert from ppbv to vmr ! qin(i,k,nh4no3_ndx) = qin(i,k,nh4no3_ndx) * 1.e-9_r8 qin(i,k,nh3_ndx ) = qin(i,k,nh3_ndx ) * 1.e-9_r8 qin(i,k,nh4_ndx ) = qin(i,k,nh4_ndx ) * 1.e-9_r8 qin(i,k,hno3_ndx ) = qin(i,k,hno3_ndx ) * 1.e-9_r8 qin(i,k,so4_ndx ) = qin(i,k,so4_ndx ) * 1.e-9_r8 if ( xhno3_ndx > 0 ) then qin(i,k,xnh4no3_ndx) = qin(i,k,xnh4no3_ndx) * 1.e-9_r8 endif if ( xhno3_ndx > 0 ) then qin(i,k,xhno3_ndx ) = qin(i,k,xhno3_ndx ) * 1.e-9_r8 endif end do end do ! ! outputs ! call outfld ('TSO4_VMR' ,tso4 (:ncol,:), ncol, lchnk ) call outfld ('THNO3_VMR',thno3(:ncol,:), ncol, lchnk ) return end subroutine aerosols_formation end module mo_aerosols