1 MODULE MODULE_GOCART_SETTLING
4 ! KYKang, MKlose, CLWu various changes
5 ! YShao [2011/09/30] complete update
7 ! 11/29/18 - A. Ukhov, bug fix: dust (and sea salt) mass balance was
8 ! violated in the "settling" routine
12 SUBROUTINE gocart_settling_driver(dt,config_flags,t_phy,moist, &
13 chem,rho_phy,dz8w,p8w,p_phy, &
15 dustgraset_1,dustgraset_2,dustgraset_3, &
16 dustgraset_4,dustgraset_5, &
17 setvel_1,setvel_2,setvel_3,setvel_4,setvel_5,imod, &
18 ids,ide,jds,jde,kds,kde, &
19 ims,ime,jms,jme,kms,kme, &
20 its,ite,jts,jte,kts,kte)
23 USE module_state_description
24 USE module_data_gocart_dust
25 USE module_data_gocart_seas
26 USE module_model_constants, ONLY: mwdry
29 TYPE(grid_config_rec_type), INTENT(IN) :: config_flags
31 INTEGER, INTENT(IN) :: ids,ide, jds,jde, kds,kde, &
32 ims,ime, jms,jme, kms,kme, &
33 its,ite, jts,jte, kts,kte
35 REAL, DIMENSION(ims:ime,kms:kme,jms:jme,num_moist), INTENT(IN) :: moist
36 REAL, DIMENSION(ims:ime,kms:kme,jms:jme,num_chem), INTENT(INOUT) :: chem
37 REAL, DIMENSION(ims:ime,kms:kme,jms:jme), INTENT(IN) :: t_phy,p_phy,dz8w,p8w,rho_phy
38 REAL, DIMENSION( ims:ime , jms:jme, 5 ), &
39 INTENT(IN ) :: dustin,seasin
41 INTEGER, INTENT(IN) :: imod
42 REAL, DIMENSION(ims:ime,jms:jme), INTENT(INOUT):: &
43 dustgraset_1,dustgraset_2,dustgraset_3, &
44 dustgraset_4,dustgraset_5, &
45 setvel_1,setvel_2,setvel_3,setvel_4,setvel_5
47 REAL*8, DIMENSION (1,1,5) :: graset_dust,grasetvel_dust
48 REAL*8, DIMENSION (1,1,4) :: graset_ss,grasetvel_ss
50 REAL, INTENT(IN) :: dt,dx,g
51 INTEGER :: kkk,nmx,i,j,k,kk,lmx,iseas,idust
52 REAL*8, DIMENSION (1,1,kte-kts+1) :: tmp,airden,p_mid,delz,rh
53 REAL*8, DIMENSION (1,1,kte-kts+1,5) :: ddust
54 REAL*8, DIMENSION (1,1,kte-kts+1,4) :: sea_salt
56 INTEGER :: uoc_flag ! flag for UoC dust schemes
58 ! REAL*8, DIMENSION (5), PARAMETER :: den_dust(5)=(/2500.,2650.,2650.,2650.,2650./)
59 ! REAL*8, DIMENSION (5), PARAMETER :: reff_dust(5)=(/0.73D-6,1.4D-6,2.4D-6,4.5D-6,8.0D-6/)
60 ! REAL*8, DIMENSION (4), PARAMETER :: den_seas(4)=(/2200.,2200.,2200.,2290./)
61 ! REAL*8, DIMENSION (4), PARAMETER :: reff_seas(4)=(/0.30D-6,1.00D-6,3.25D-6,7.50D-6/)
63 REAL*8 conver, converi
68 if (config_flags%dust_opt .eq. 4) uoc_flag = 1
75 IF(config_flags%chem_opt == 2 .or. config_flags%chem_opt == 11) THEN
77 ddust(1,1,kts,kkk)=dustin(i,j,kkk)*conver
83 p_mid(1,1,kk) =.01*p_phy(i,kte-k+kts,j)
84 delz(1,1,kk) =dz8w(i,kte-k+kts,j)
85 airden(1,1,kk)=rho_phy(i,k,j)
86 tmp(1,1,kk)= t_phy(i,k,j)
88 rh(1,1,kk) = MIN( .95, moist(i,k,j,p_qv) / &
89 (3.80*exp(17.27*(t_phy(i,k,j)-273.)/ &
90 (t_phy(i,k,j)-36.))/(.01*p_phy(i,k,j))))
91 rh(1,1,kk) = max(1.0D-1,rh(1,1,kk))
98 ddust(1,1,kk,1)=chem(i,k,j,p_dust_1) ! chem and dust in [ug/kg]
99 ddust(1,1,kk,2)=chem(i,k,j,p_dust_2)
100 ddust(1,1,kk,3)=chem(i,k,j,p_dust_3)
101 ddust(1,1,kk,4)=chem(i,k,j,p_dust_4)
102 ddust(1,1,kk,5)=chem(i,k,j,p_dust_5)
104 p_mid(1,1,kk)=.01*p_phy(i,kte-k+kts,j)
105 delz(1,1,kk)=dz8w(i,kte-k+kts,j) ! delz(1) = dz8w(kte), delz(lmx)=dz8w(kts)
106 airden(1,1,kk)=rho_phy(i,k,j)
107 tmp(1,1,kk) =t_phy(i,k,j)
109 rh(1,1,kk) = MIN( .95, moist(i,k,j,p_qv) / &
110 (3.80*exp(17.27*(t_phy(i,k,j)-273.)/ &
111 (t_phy(i,k,j)-36.))/(.01*p_phy(i,k,j))))
112 rh(1,1,kk)=max(1.0D-1,rh(1,1,kk))
115 graset_dust(1,1,:)=0.
120 CALL settling(1,1,lmx,5,g,dyn_visc,ddust,tmp,p_mid,delz, &
121 imod,graset_dust,grasetvel_dust, uoc_flag, &
122 den_dust,reff_dust,dt,rh,idust,iseas,airden)
124 IF (config_flags%chem_opt == 2 .or. config_flags%chem_opt == 11 ) THEN
127 if (kkk .le. 4) sea_salt(1,1,kts,kkk)=seasin(i,j,kkk)*conver
128 if(ddust(1,1,kk,kkk) .ge. dustin(i,j,kkk)) ddust(1,1,kk,kkk)=dustin(i,j,kkk)
130 chem(i,kts,j,p_p25i)=chem(i,kts,j,p_p25i) &
131 +.25*(ddust(1,1,kk,1)+.286*ddust(1,1,kk,2))*converi
132 chem(i,kts,j,p_p25i)=max(chem(i,kts,j,p_p25i),1.e-16)
133 chem(i,kts,j,p_p25j)=chem(i,kts,j,p_p25j) &
134 +.75*(ddust(1,1,kk,1)+.286*ddust(1,1,kk,2))*converi
135 chem(i,kts,j,p_p25j)=max(chem(i,kts,j,p_p25j),1.e-16)
136 chem(i,kts,j,p_soila)=chem(i,kts,j,p_soila) &
137 +(.714*ddust(1,1,kk,2)+ddust(1,1,kk,3))*converi
138 chem(i,kts,j,p_soila)=max(chem(i,kts,j,p_soila),1.e-16)
143 chem(i,k,j,p_dust_1)=ddust(1,1,kk,1) ! dust for size bin 1 [ug/kg]
144 chem(i,k,j,p_dust_2)=ddust(1,1,kk,2) ! ...
145 chem(i,k,j,p_dust_3)=ddust(1,1,kk,3) ! ...
146 chem(i,k,j,p_dust_4)=ddust(1,1,kk,4) ! ...
147 chem(i,k,j,p_dust_5)=ddust(1,1,kk,5) ! dust for size bin 5 (dust_opt 3: for all size bins) [ug/kg]
149 sea_salt(1,1,kk,1)=chem(i,k,j,p_seas_1) ! salt [ug/kg]
150 sea_salt(1,1,kk,2)=chem(i,k,j,p_seas_2)
151 sea_salt(1,1,kk,3)=chem(i,k,j,p_seas_3)
152 sea_salt(1,1,kk,4)=chem(i,k,j,p_seas_4)
156 !graset_dust in [ug/kg][m/s]
157 dustgraset_1(i,j)=dustgraset_1(i,j)+conver*graset_dust(1,1,1)*airden(1,1,1)*dt !dustgraset [kg/m2]
158 dustgraset_2(i,j)=dustgraset_2(i,j)+conver*graset_dust(1,1,2)*airden(1,1,1)*dt
159 dustgraset_3(i,j)=dustgraset_3(i,j)+conver*graset_dust(1,1,3)*airden(1,1,1)*dt
160 dustgraset_4(i,j)=dustgraset_4(i,j)+conver*graset_dust(1,1,4)*airden(1,1,1)*dt
161 dustgraset_5(i,j)=dustgraset_5(i,j)+conver*graset_dust(1,1,5)*airden(1,1,1)*dt
163 setvel_1(i,j)=grasetvel_dust(1,1,1) ! settling velocity [m/s]
164 setvel_2(i,j)=grasetvel_dust(1,1,2)
165 setvel_3(i,j)=grasetvel_dust(1,1,3)
166 setvel_4(i,j)=grasetvel_dust(1,1,4)
167 setvel_5(i,j)=grasetvel_dust(1,1,5)
172 CALL settling(1,1,lmx,4,g,dyn_visc,sea_salt,tmp,p_mid,delz, &
173 imod,graset_ss,grasetvel_ss, uoc_flag, &
174 den_seas,reff_seas,dt,rh,idust,iseas,airden)
175 IF (config_flags%chem_opt == 2 .or. config_flags%chem_opt == 11 ) THEN
178 if(sea_salt(1,1,kk,kkk) .ge. seasin(i,j,kkk))sea_salt(1,1,kk,kkk)=seasin(i,j,kkk)
180 chem(i,kts,j,p_naai)=chem(i,kts,j,p_naai) &
181 +.25*(sea_salt(1,1,kk,1)+.942*sea_salt(1,1,kk,2))*converi
182 chem(i,kts,j,p_naai)=max(1.e-16,chem(i,kts,j,p_naai))
183 chem(i,kts,j,p_naaj)=chem(i,kts,j,p_naaj) &
184 +.75*(sea_salt(1,1,kk,1)+.942*sea_salt(1,1,kk,2))*converi
185 chem(i,kts,j,p_naaj)=max(1.e-16,chem(i,kts,j,p_naaj))
186 chem(i,kts,j,p_seas)=chem(i,kts,j,p_seas) &
187 +(.058*sea_salt(1,1,kk,2)+sea_salt(1,1,kk,3))*converi
188 chem(i,kts,j,p_seas)=max(1.e-16,chem(i,kts,j,p_seas))
193 chem(i,k,j,p_seas_1)=sea_salt(1,1,kk,1)
194 chem(i,k,j,p_seas_2)=sea_salt(1,1,kk,2)
195 chem(i,k,j,p_seas_3)=sea_salt(1,1,kk,3)
196 chem(i,k,j,p_seas_4)=sea_salt(1,1,kk,4)
203 END SUBROUTINE gocart_settling_driver
206 subroutine settling(imx,jmx,lmx,nmx,g0,dyn_visc,tc,tmp,p_mid,delz, &
207 imod,graset, grasetvel, uoc, &
208 den_in,reff_in,dt,rh,idust,iseas,airden)
210 ! ****************************************************************************
212 ! * Calculate the loss by settling, using an implicit method *
214 ! * Input variables: *
215 ! * SIGE(k) - sigma coordinate of the vertical edges *
216 ! * PS(i,j) - Surface pressure (mb) *
217 ! * TMP(i,j,k) - Air temperature (K) *
218 ! * CT(i,j) - Surface exchange coeff for moisture
220 ! ****************************************************************************
224 INTEGER, INTENT(IN) :: imx, jmx, lmx, nmx,iseas,idust
226 REAL, INTENT(IN) :: dt,g0,dyn_visc
227 REAL*8, INTENT(IN) :: tmp(imx,jmx,lmx), delz(imx,jmx,lmx), &
228 rh(imx,jmx,lmx), p_mid(imx,jmx,lmx),airden(imx,jmx,lmx)
230 REAL*8, INTENT(IN) :: den_in(nmx), reff_in(nmx)
232 REAL*8, INTENT(INOUT) :: tc(imx,jmx,lmx,nmx)
234 INTEGER, INTENT(IN) :: imod, uoc
235 REAL*8, INTENT(INOUT) :: graset(imx,jmx,nmx)
236 REAL*8, INTENT(OUT) :: grasetvel(imx,jmx,nmx)
238 REAL*8 :: den(nmx), reff(nmx) ! local variables here
239 REAL*8 :: dt_settl(nmx), rcm(nmx), rho(nmx)
240 INTEGER :: ndt_settl(nmx)
241 REAL*8 :: dzmin, vsettl, dtmax, pres, rhb, rwet(nmx), ratio_r(nmx)
242 REAL*8 :: c_stokes, free_path, c_cun, viscosity, growth_fac
243 REAL*8 :: vd_cor(lmx), vd_wk1
244 INTEGER :: k, n, i, j, l, l2
246 REAL*8 :: transfer_to_below_level,temp_tc
249 REAL*8, PARAMETER :: c1=0.7674, c2=3.079, c3=2.573E-11, c4=-1.424
252 REAL*8 :: rwet_priv(nmx), rho_priv(nmx)
254 ! IF (type) /= 'dust' .AND. TRIM(aero_type) /= 'sea_salt') RETURN
255 IF ( idust.ne.1 .and. iseas.ne.1 ) RETURN
256 WHERE ( tc(:,:,:,:) < 0.0 ) tc(:,:,:,:) = 1.0D-32
260 dzmin = MINVAL(delz(:,:,:))
261 IF (idust == 1) growth_fac = 1.0
262 IF (iseas == 1) growth_fac = 3.0
264 IF (idust == 1 .and. uoc == 1) then
265 den(1) = 2650. ! constant density is use in UoC dust emission schemes;
266 ! dust radii are now consistent with GOCART dust schemes. [mklose, 03082015]
269 DO k = 1, nmx ! k for different size bins
271 ! Settling velocity (m/s) for each tracer (Stokes Law)
272 ! DEN density (kg/m3)
273 ! REFF effective radius (m)
274 ! dyn_visc dynamic viscosity (kg/m/s)
276 ! 3.0 corresponds to a growth of a factor 3 of radius with 100% RH
277 ! 0.5 upper limit with temp correction
279 vsettl = 4.0/9.0 * g0 * den(k) * (growth_fac*reff(k))**2 / dyn_visc
281 ! Determine the maximum time-step satisying CFL: dt <= (dz)_min / v_settl
284 dtmax = dzmin / vsettl
285 ndt_settl(k) = MAX( 1,INT(ntdt/dtmax) )
287 ! Limit maximum number of iterations
288 IF (ndt_settl(k) > 12) ndt_settl(k) = 12
289 dt_settl(k) = REAL(ntdt) / REAL(ndt_settl(k))
291 ! Particles radius in centimeters
292 IF (iseas.eq.1)rcm(k) = reff(k)*100.0
300 ! Solve the bidiagonal matrix (l,l)
303 !$OMP DEFAULT( SHARED ) &
304 !$OMP PRIVATE( i, j, l, l2, n, k, rhb, rwet_priv, ratio_r, c_stokes)&
305 !$OMP PRIVATE( free_path, c_cun, viscosity, rho_priv, vd_cor )
307 ! Loop over latitudes
309 DO j = 1,jmx ! lat loop
310 DO i = 1,imx ! lon loop
311 DO k = 1,nmx ! bin loop
316 rwet_priv(k) = rwet(k)
320 DO n = 1,ndt_settl(k) ! time loop
322 transfer_to_below_level=0
324 DO l = lmx,1,-1 ! height loop, from top
328 rhb = MIN(9.9D-1, rh(i,j,l)) ! Aerosol growth with relative humidity (Gerber, 1985)
329 rwet_priv(k) = 0.01*(c1*rcm(k)**c2/(c3*rcm(k)**c4 - &
330 LOG10(rhb)) + rcm(k)**3)**0.33 ! td changed to LOG10
331 ratio_r(k) = (reff(k)/rwet_priv(k))**3.0
334 c_stokes = 1.458E-6*tmp(i,j,l)**1.5/(tmp(i,j,l) + 110.4) ! Dynamic viscosity
335 free_path = 1.1E-3/p_mid(i,j,l2)/SQRT(tmp(i,j,l)) ! Free path as func of pres(mb) and temp(K); order of p_mid: top->sfc
337 c_cun = 1.0+free_path/rwet_priv(k)* &
338 (1.257 + 0.4*EXP(-1.1*rwet_priv(k)/free_path)) ! Slip correction
339 viscosity = c_stokes / c_cun ! Corrected dynamic viscosity (kg/m/s)
342 rho_priv(k) = ratio_r(k)*den(k) + (1.-ratio_r(k))*1000.
345 vd_cor(l) = 2./9.*g0*rho_priv(k)*rwet_priv(k)**2/viscosity ! Settling velocity, depends on temp
347 ! Update mixing ratio; order of delz: top->sfc
348 temp_tc=tc(i,j,l,k) ! temp_tc - for temporal storage [ug/kg]
349 vd_wk1 = dt_settl(k)*vd_cor(l)/delz(i,j,l2) ! fraction to leave level
351 tc(i,j,l,k) = tc(i,j,l,k)*(1.- vd_wk1)+transfer_to_below_level ! [ug/kg]
354 graset(i,j,k)=graset(i,j,k)+vd_cor(l)*temp_tc/ndt_settl(k) ! [ug/kg][m/s]
355 grasetvel(i,j,k)=vd_cor(l) ! [m/s]
357 transfer_to_below_level = (temp_tc*vd_wk1)*((delz(i,j,l2)*airden(i,j,l))/(delz(i,j,l2+1)*airden(i,j,l-1))) ! [ug/kg]
365 !$OMP END PARALLEL DO
367 END SUBROUTINE settling
369 END MODULE MODULE_GOCART_SETTLING