1 MODULE module_mosaic_wetscav
5 !===========================================================================
6 !===========================================================================
7 subroutine wetscav_cbmz_mosaic (id,ktau,dtstep,ktauc,config_flags, &
8 dtstepc,alt,t_phy,p8w,t8w,p_phy,chem,rho_phy,cldfra, &
9 qlsink,precr,preci,precs,precg,qsrflx, &
10 gas_aqfrac, numgas_aqfrac, &
11 ids,ide, jds,jde, kds,kde, &
12 ims,ime, jms,jme, kms,kme, &
13 its,ite, jts,jte, kts,kte )
15 ! wet removal by grid-resolved precipitation
16 ! scavenging of cloud-phase aerosols and gases by collection, freezing, ...
17 ! scavenging of interstitial-phase aerosols by impaction
18 ! scavenging of gas-phase gases by mass transfer and reaction
20 !----------------------------------------------------------------------
21 USE module_configure, only: grid_config_rec_type
22 USE module_state_description
23 USE module_data_mosaic_asect
25 !----------------------------------------------------------------------
28 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
30 INTEGER, INTENT(IN ) :: &
31 ids,ide, jds,jde, kds,kde, &
32 ims,ime, jms,jme, kms,kme, &
33 its,ite, jts,jte, kts,kte, &
34 id, ktau, ktauc, numgas_aqfrac
35 REAL, INTENT(IN ) :: dtstep,dtstepc
37 ! all advected chemical species
39 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, num_chem ), &
40 INTENT(INOUT ) :: chem
42 ! fraction of gas species in cloud water
43 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, numgas_aqfrac ), &
44 INTENT(IN ) :: gas_aqfrac
48 ! input from meteorology
49 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ) , &
55 qlsink,precr,preci,precs,precg, &
57 REAL, DIMENSION( ims:ime, jms:jme, num_chem ), &
58 INTENT(OUT ) :: qsrflx ! column change due to scavening
60 call wetscav (id,ktau,dtstep,ktauc,config_flags, &
61 dtstepc,alt,t_phy,p8w,t8w,p_phy,chem,rho_phy,cldfra, &
62 qlsink,precr,preci,precs,precg,qsrflx, &
63 gas_aqfrac, numgas_aqfrac, &
64 ntype_aer, nsize_aer, ncomp_aer, &
65 massptr_aer, dens_aer, numptr_aer, &
66 maxd_acomp, maxd_asize,maxd_atype, maxd_aphase, ai_phase, cw_phase, &
67 volumcen_sect, volumlo_sect, volumhi_sect, &
68 waterptr_aer, dens_water_aer, &
69 scavimptblvol, scavimptblnum, nimptblgrow_mind, nimptblgrow_maxd, dlndg_nimptblgrow, &
70 ids,ide, jds,jde, kds,kde, &
71 ims,ime, jms,jme, kms,kme, &
72 its,ite, jts,jte, kts,kte )
74 end subroutine wetscav_cbmz_mosaic
77 !===========================================================================
78 !===========================================================================
79 subroutine wetscav_mozart_mosaic (id,ktau,dtstep,ktauc,config_flags, &
80 dtstepc,alt,t_phy,p8w,t8w,p_phy,chem,rho_phy,cldfra, &
81 qlsink,precr,preci,precs,precg,qsrflx, &
82 gas_aqfrac, numgas_aqfrac, &
83 ids,ide, jds,jde, kds,kde, &
84 ims,ime, jms,jme, kms,kme, &
85 its,ite, jts,jte, kts,kte )
87 ! wet removal by grid-resolved precipitation
88 ! scavenging of cloud-phase aerosols and gases by collection, freezing, ...
89 ! scavenging of interstitial-phase aerosols by impaction
90 ! scavenging of gas-phase gases by mass transfer and reaction
92 !----------------------------------------------------------------------
93 USE module_configure, only: grid_config_rec_type
94 USE module_state_description
95 USE module_data_mosaic_asect
97 !----------------------------------------------------------------------
100 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
102 INTEGER, INTENT(IN ) :: &
103 ids,ide, jds,jde, kds,kde, &
104 ims,ime, jms,jme, kms,kme, &
105 its,ite, jts,jte, kts,kte, &
106 id, ktau, ktauc, numgas_aqfrac
107 REAL, INTENT(IN ) :: dtstep,dtstepc
109 ! all advected chemical species
111 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, num_chem ), &
112 INTENT(INOUT ) :: chem
114 ! fraction of gas species in cloud water
115 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, numgas_aqfrac ), &
116 INTENT(IN ) :: gas_aqfrac
120 ! input from meteorology
121 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ) , &
127 qlsink,precr,preci,precs,precg, &
129 REAL, DIMENSION( ims:ime, jms:jme, num_chem ), &
130 INTENT(OUT ) :: qsrflx ! column change due to scavening
132 call wetscav (id,ktau,dtstep,ktauc,config_flags, &
133 dtstepc,alt,t_phy,p8w,t8w,p_phy,chem,rho_phy,cldfra, &
134 qlsink,precr,preci,precs,precg,qsrflx, &
135 gas_aqfrac, numgas_aqfrac, &
136 ntype_aer, nsize_aer, ncomp_aer, &
137 massptr_aer, dens_aer, numptr_aer, &
138 maxd_acomp, maxd_asize,maxd_atype, maxd_aphase, ai_phase, cw_phase, &
139 volumcen_sect, volumlo_sect, volumhi_sect, &
140 waterptr_aer, dens_water_aer, &
141 scavimptblvol, scavimptblnum, nimptblgrow_mind, nimptblgrow_maxd, dlndg_nimptblgrow, &
142 ids,ide, jds,jde, kds,kde, &
143 ims,ime, jms,jme, kms,kme, &
144 its,ite, jts,jte, kts,kte )
146 end subroutine wetscav_mozart_mosaic
148 !===========================================================================
149 !===========================================================================
150 subroutine wetscav (id,ktau,dtstep,ktauc,config_flags, &
151 dtstepc,alt,t_phy,p8w,t8w,p_phy,chem,rho_phy,cldfra, &
152 qlsink,precr,preci,precs,precg,qsrflx, &
153 gas_aqfrac, numgas_aqfrac, &
154 ntype_aer, nsize_aer, ncomp_aer, &
155 massptr_aer, dens_aer, numptr_aer, &
156 maxd_acomp, maxd_asize,maxd_atype, maxd_aphase, ai_phase, cw_phase, &
157 volumcen_sect, volumlo_sect, volumhi_sect, &
158 waterptr_aer, dens_water_aer, &
159 scavimptblvol, scavimptblnum, nimptblgrow_mind, nimptblgrow_maxd, dlndg_nimptblgrow, &
160 ids,ide, jds,jde, kds,kde, &
161 ims,ime, jms,jme, kms,kme, &
162 its,ite, jts,jte, kts,kte )
164 ! wet removal by grid-resolved precipitation
165 ! scavenging of cloud-phase aerosols and gases by collection, freezing, ...
166 ! scavenging of interstitial-phase aerosols by impaction
167 ! scavenging of gas-phase gases by mass transfer and reaction
169 !----------------------------------------------------------------------
170 USE module_configure, only: grid_config_rec_type
171 USE module_state_description
172 USE module_model_constants, only: g, rhowater, mwdry
173 USE module_dep_simple, only: is_aerosol
177 !======================================================================
179 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
181 INTEGER, INTENT(IN ) :: &
182 ids,ide, jds,jde, kds,kde, &
183 ims,ime, jms,jme, kms,kme, &
184 its,ite, jts,jte, kts,kte, &
185 id, ktau, ktauc, numgas_aqfrac
186 REAL, INTENT(IN ) :: dtstep,dtstepc
188 ! all advected chemical species
190 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, num_chem ), &
191 INTENT(INOUT ) :: chem
193 ! fraction of gas species in cloud water
194 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, numgas_aqfrac ), &
195 INTENT(IN ) :: gas_aqfrac
198 ! input from meteorology
200 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ) , &
206 qlsink,precr,preci,precs,precg, &
208 integer, intent(in) :: maxd_atype, maxd_asize, maxd_acomp, maxd_aphase
209 integer, intent(in) :: ai_phase, cw_phase
210 integer, intent(in) :: ntype_aer
211 integer, intent(in) :: nsize_aer( maxd_atype ), & ! number of size bins
212 ncomp_aer( maxd_atype ), & ! number of chemical components
213 massptr_aer( maxd_acomp, maxd_asize, maxd_atype, maxd_aphase), & ! index for mixing ratio
214 waterptr_aer( maxd_asize, maxd_atype ), & ! index for aerosol water
215 numptr_aer( maxd_asize, maxd_atype, maxd_aphase ) ! index for the number mixing ratio
216 real, intent(in) :: dens_aer( maxd_acomp, maxd_atype ), & ! material density (g/cm3)
217 dens_water_aer ! water density (g/m3)
218 real, intent(in) :: volumcen_sect( maxd_asize, maxd_atype ), & ! single-particle volumes (cm3)
219 volumlo_sect( maxd_asize, maxd_atype ), & ! at section center, lower boundary,
220 volumhi_sect( maxd_asize, maxd_atype ) ! upper boundary
222 real, intent(in) :: dlndg_nimptblgrow
223 integer, intent(in) :: nimptblgrow_mind, nimptblgrow_maxd
224 real, intent(in) :: scavimptblnum(4, nimptblgrow_mind:nimptblgrow_maxd, maxd_asize, maxd_atype), &
225 scavimptblvol(4, nimptblgrow_mind:nimptblgrow_maxd, maxd_asize, maxd_atype)
226 REAL, DIMENSION( ims:ime, jms:jme, num_chem ), &
227 INTENT(OUT ) :: qsrflx ! column change due to scavening
232 integer :: i,j,k,l,m,n
233 integer :: lmasscw,lnumcw
235 logical :: isprx(ims:ime,kms:kme,jms:jme)
237 real :: pdel(ims:ime,kms:kme,jms:jme)
238 real :: delpf(kms:kme)
241 real :: fac_pwght_ls(kms:kme) !
242 real :: fapincld, fapoutcld, faptot
244 real :: fapx(ims:ime,kms:kme,jms:jme)
246 real :: pf_above, pf_below, pdel_fac
247 real :: pf_ls(kms:kme)
249 real :: pfsmall_ls ! l-s precip fluxes (kg/m2/s) smaller than this
250 ! are ignored (treated as zero)
252 real :: pfx(ims:ime,kms:kme,jms:jme)
253 real :: pfx_inrain(ims:ime,kms:kme,jms:jme)
254 real :: sumfa, sumpf, sumpffa
255 REAL :: dqdt( ims:ime, kms:kme, jms:jme, num_chem )
256 logical dotend(num_chem)
263 ! scavenging cloud-phase aerosol assuming precip falls to surface
267 pdel(i,k,j)=p8w(i,k,j)-p8w(i,k+1,j)
273 scale=1.0-dtstepc*qlsink(i,k,j)
274 scale=max(0.0,min(1.0,scale)) ! make sure 0 <= scale <= 1
275 if (qlsink(i,k,j) > 0.0) then
276 pdel_fac = pdel(i,k,j)/g
280 lmasscw=massptr_aer(l,m,n,cw_phase)
281 if (lmasscw < param_first_scalar) cycle
282 qsrflx(i,j,lmasscw)=qsrflx(i,j,lmasscw)+chem(i,k,j,lmasscw)*(scale-1.)*pdel_fac ! aerosol mass (ug/m2)
283 chem(i,k,j,lmasscw)=chem(i,k,j,lmasscw)*scale
285 lnumcw=numptr_aer(m,n,cw_phase)
286 if (lnumcw < param_first_scalar) cycle
287 qsrflx(i,j,lnumcw)=qsrflx(i,j,lnumcw)+chem(i,k,j,lnumcw)*(scale-1.)*pdel_fac ! aerosol number (1/m2)
288 chem(i,k,j,lnumcw)=chem(i,k,j,lnumcw)*scale
295 ! scavenging of gases in cloud-water
296 ! only if not MOZART (--> Neu and Prather used)
297 if ( .NOT. (config_flags%chem_opt == mozart_mosaic_4bin_aq_kpp) ) then
298 do 290 l = param_first_scalar, min( num_chem, numgas_aqfrac )
299 if ( is_aerosol(l) ) goto 290
303 fracscav = dtstepc*qlsink(i,k,j)*gas_aqfrac(i,k,j,l)
304 if (fracscav > 0.0) then ! make sure fracscav > 0
305 fracscav = min(1.0,fracscav) ! make sure fracscav <= 1
306 scale = 1.0 - fracscav
307 pdel_fac = pdel(i,k,j)/(g*mwdry)
308 qsrflx(i,j,l) = qsrflx(i,j,l)+chem(i,k,j,l)*(scale-1.)*pdel_fac ! mmol/m2
309 chem(i,k,j,l) = chem(i,k,j,l)*scale
316 ! below-cloud scavenging
318 ! precip rates -- 1.0 kgwtr/m2/s = 1.0e-3 m3wtr/m2/s = 1.0e-3 m/s
319 ! 7.06e-5 kg/m2/s = 7.06e-8 m/s = 0.01 inch/h
320 ! 3.17e-5 kg/m2/s = 3.17e-8 m/s = 1 m/y = global annual average
321 ! 1.00e-7 kg/m2/s = 1.00e-10 m/s is a very small precip rate!
326 isprx(:,:,:) = .false.
328 pfx_inrain(:,:,:) = 0.0
335 !----------------------------------------------------------------------
336 ! compute l-s precip rates
338 ! pf_ls(k) = precip flux at center of level
342 pf_below = precr(i,k,j) + preci(i,k,j) + precs(i,k,j) + precg(i,k,j) ! total precip rate
343 if (pf_below < pfsmall_ls) pf_below = 0.0
344 delpf(k) = pf_below - pf_above
345 pf_ls(k) = 0.5*(pf_below + pf_above)
346 if (pf_ls(k) < pfsmall_ls) pf_ls(k) = 0.0
349 ! compute fac_pwght_ls which is an average of cloud fractional area in and
350 ! above the current level, weighted by precip production in each level
351 ! basically this reflect the cloud area at levels where precip is produced
354 ! compute change from (k-1/k) interface to level k center
355 delpfhalf = 0.5*delpf(k)
356 if (delpfhalf > 0.0) then
357 fac_pwght_ls(k) = max( cldfra(i,k,j), fapmin_ls )
358 sumpffa = delpfhalf * fac_pwght_ls(k)
361 fac_pwght_ls(k) = fapmin_ls
366 ! compute change from level (k+1) center to (k+1/k) interface
367 delpfhalf = 0.5*delpf(k+1)
368 if (delpfhalf > 0.0) then
369 sumpffa = sumpffa + delpfhalf*max( cldfra(i,k+1,j), fapmin_ls )
370 sumpf = sumpf + delpfhalf
371 fac_pwght_ls(k) = max( (sumpffa/sumpf), fapmin_ls )
373 fac_pwght_ls(k) = fac_pwght_ls(k+1)
374 sumpffa = max( (sumpffa + delpfhalf*fac_pwght_ls(k)), 0.0 )
375 sumpf = max( (sumpf + delpfhalf), 0.0 )
377 ! compute change from (k-1/k) interface to level k center
378 delpfhalf = 0.5*delpf(k)
379 if (delpfhalf > 0.0) then
380 sumpffa = sumpffa + delpfhalf*max( cldfra(i,k,j), fapmin_ls )
381 sumpf = sumpf + delpfhalf
382 fac_pwght_ls(k) = max( (sumpffa/sumpf), fapmin_ls )
384 ! here, fac_pwght_ls(k) is unchanged from its value computed just above
385 sumpffa = max( (sumpffa + delpfhalf*fac_pwght_ls(k)), 0.0 )
386 sumpf = max( (sumpf + delpfhalf), 0.0 )
392 !----------------------------------------------------------------------
393 !----------------------------------------------------------------------
396 !----------------------------------------------------------------------
397 ! loop through levels
399 do 4900 k = kte, kts,-1
402 !----------------------------------------------------------------------
403 ! for each cloud/precip type (ls, dp, sh), compute
404 ! fapx = fractional area with precip
405 ! pfx = precip flux based on entire grid-cell area (kg/m2/s)
406 ! pfx_inrain = precip flux within the precip fractional area (kg/m2/s)
412 ! assume faptot = total (in + out-of-cloud) precip area
413 ! = 0.5*fac_pwght_ls(k)
414 ! then fapincld = in-cloud precip area
415 ! = min( faptot, cloud area )
416 ! fapoutcld = out-of-cloud precip area
417 ! = max( 0.0, faptot-fapincld )
418 ! also pfoutcld = out-of-cloud precip flux = fraction of total precip flux
419 ! = pf_ls(k)*(fapoutcld/faptot)
420 if (pf_ls(k) > 0.0) then
421 faptot= 0.5*fac_pwght_ls(k)
422 fapincld = min( faptot, cldfra(i,k,j) )
423 fapoutcld = max( 0.0, faptot-fapincld )
424 pfoutcld = pf_ls(k)*(fapoutcld/faptot)
425 if (pfoutcld >= pfsmall_ls) then
426 isprx(i,k,j) = .true.
427 pfx(i,k,j) = pfoutcld
428 fapx(i,k,j) = fapoutcld
429 pfx_inrain(i,k,j) = pf_ls(k)/faptot
430 sumpf = sumpf + pfx(i,k,j)
431 sumfa = sumfa + fapx(i,k,j)
435 4900 continue ! "k = 1, pver"
437 5900 continue ! "i = 1, ncol"
440 call aerimpactscav (ims,ime,kms,kme,jms,jme,its,ite,kts,kte,jts,jte, num_chem, &
441 ntype_aer, nsize_aer, ncomp_aer, massptr_aer, dens_aer, numptr_aer, &
442 maxd_acomp, maxd_asize,maxd_atype, maxd_aphase, ai_phase, &
443 volumcen_sect, volumlo_sect, volumhi_sect, &
444 waterptr_aer, dens_water_aer, &
445 scavimptblvol, scavimptblnum, &
446 nimptblgrow_mind, nimptblgrow_maxd, dlndg_nimptblgrow, &
447 dtstepc, t_phy, p_phy, pdel, chem, &
448 isprx, fapx, pfx, pfx_inrain, &
449 dqdt, dotend, qsrflx )
451 ! only if not MOZART (--> Neu and Prather used)
452 if ( .NOT. (config_flags%chem_opt == mozart_mosaic_4bin_aq_kpp) ) then
453 call gasrainscav (ims,ime,kms,kme,jms,jme,its,ite,kts,kte,jts,jte, num_chem, &
455 dtstepc, t_phy, p_phy, pdel, chem, &
456 isprx, fapx, pfx, pfx_inrain, &
457 dqdt, dotend, qsrflx )
467 chem(i,k,j,n) = chem(i,k,j,n) + dqdt(i,k,j,n)*dtstepc
472 end subroutine wetscav
476 !===========================================================================
477 !===========================================================================
478 subroutine aerimpactscav (ims,ime,kms,kme,jms,jme,its,ite,kts,kte,jts,jte,num_chem, &
479 ntype_aer, nsize_aer, ncomp_aer, massptr_aer, dens_aer, numptr_aer, &
480 maxd_acomp, maxd_asize,maxd_atype, maxd_aphase, ai_phase, &
481 volumcen_sect, volumlo_sect, volumhi_sect, &
482 waterptr_aer, dens_water_aer, &
483 scavimptblvol, scavimptblnum, nimptblgrow_mind, nimptblgrow_maxd, dlndg_nimptblgrow, &
484 deltat, t, pmid, pdel, chem, &
485 isprx, fapx, pfx, pfx_inrain, &
486 dqdt, dotend, qsrflx )
489 !-----------------------------------------------------------------------
492 ! Does below cloud scavenging of aerosols through impaction-interception
494 ! Removal rates for aersol number, (surface - still to do), and volume
495 ! are computed for each mode using precalculated lookup tables.
496 ! The tables account for variables in wet-dgnum, wet density,
497 ! air temperature, and air pressure.
501 !-----------------------------------------------------------------------
502 USE module_model_constants, only: g,rhowater, mwdry
503 USE module_state_description, only: param_first_scalar
507 !-----------------------------------------------------------------------
511 ! abbreviations & acronyms
512 ! TMR = tracer mixing ratio
515 integer, intent(in) :: num_chem ! number of chemical species
516 integer, intent(in) :: ims,ime ! column dimension
517 integer, intent(in) :: kms,kme ! level dimension
518 integer, intent(in) :: jms,jme ! column dimension
519 integer, intent(in) :: its,ite ! column identifier
520 integer, intent(in) :: kts,kte ! level identifier
521 integer, intent(in) :: jts,jte ! column identifier
522 real, intent(in) :: deltat ! model timestep
524 real, intent(in) :: t(ims:ime,kms:kme,jms:jme) ! temperature
525 real, intent(in) :: pmid(ims:ime,kms:kme,jms:jme) ! pressure at model levels
526 real, intent(in) :: pdel(ims:ime,kms:kme,jms:jme) ! pressure thickness of levels
527 real, intent(in) :: chem(ims:ime,kms:kme,jms:jme,num_chem) ! chem array
529 logical, intent(in) :: isprx(ims:ime,kms:kme,jms:jme) ! true if precip at i,k
530 real, intent(in) :: fapx(ims:ime,kms:kme,jms:jme) ! frac. area for precip
531 real, intent(in) :: pfx(ims:ime,kms:kme,jms:jme) ! grid-avg precip
533 real, intent(in) :: pfx_inrain(ims:ime,kms:kme,jms:jme) ! in-rain-area precip flux (kg/m2/s)
535 real, intent(inout) :: dqdt(ims:ime,kms:kme,jms:jme,num_chem) ! TMR tendency array
536 logical, intent(inout) :: dotend(num_chem) ! flag for doing scav
537 real, intent(inout) :: qsrflx(ims:ime,jms:jme,num_chem)
538 ! changes to column tracer burdens by wet scavenging over current timestep
539 ! this routine adds on the contribution from aerosol impaction and brownian
540 ! diffusion scavenging by precipitation
541 integer, intent(in) :: maxd_atype, maxd_asize, maxd_acomp, maxd_aphase
542 integer, intent(in) :: ai_phase
543 integer, intent(in) :: ntype_aer
544 integer, intent(in) :: nsize_aer( maxd_atype ), & ! number of size bins
545 ncomp_aer( maxd_atype ), & ! number of chemical components
546 massptr_aer( maxd_acomp, maxd_asize, maxd_atype, maxd_aphase), & ! index for mixing ratio
547 waterptr_aer( maxd_asize, maxd_atype ), & ! index for aerosol water
548 numptr_aer( maxd_asize, maxd_atype, maxd_aphase ) ! index for the number mixing ratio
549 real, intent(in) :: volumcen_sect( maxd_asize, maxd_atype ), & ! single-particle volumes (cm3)
550 volumlo_sect( maxd_asize, maxd_atype ), & ! at section center, lower boundary,
551 volumhi_sect( maxd_asize, maxd_atype ) ! upper boundary
552 real, intent(in) :: dens_aer( maxd_acomp, maxd_atype ), & ! material density (g/cm3)
553 dens_water_aer ! water density (g/m3)
555 real, intent(in) :: dlndg_nimptblgrow
556 integer, intent(in) :: nimptblgrow_mind, nimptblgrow_maxd
557 real, intent(in) :: scavimptblnum(4, nimptblgrow_mind:nimptblgrow_maxd, maxd_asize, maxd_atype), &
558 scavimptblvol(4, nimptblgrow_mind:nimptblgrow_maxd, maxd_asize, maxd_atype)
560 !--------------------------Local Variables------------------------------
562 integer :: i,j ! Work index
563 integer :: jgrow, jp ! Work index
564 integer :: k ! Work index
565 integer :: l, ll, m, n ! Work index
567 logical :: ispr_anywhere
569 real :: dry_mass, dry_volu, dry_volu_1p
571 real :: dumfhi, dumflo
572 real :: dumimpactamt0, dumimpactamt3, dumimpactamtsum
573 real :: dumimpactratea0, dumimpactratea3
574 real :: dumimpactrateb0, dumimpactrateb3
575 real :: dumdgratio, dumrate, dumwetdens
576 real :: dumlogdens, dumlogptot, dumlogtemp
578 real :: dumscavratenum, dumscavratevol
581 real :: scavimptbl1, scavimptbl2, scavimptbl3, scavimptbl4
583 real :: wet_mass, wet_volu
584 real, save :: third = 0.33333333
586 !-----------------------------------------------------------------------
589 ! if (ncol .ne. -987654321) return
591 ! precip rates -- 1.0 kgwtr/m2/s = 1.0e-3 m3wtr/m2/s = 1.0e-3 m/s
592 ! = 1.0 mm/s = 3600 mm/h
594 ispr_anywhere = .false.
599 do 4900 k = kte,kts,-1
601 ! skip this level if no precip
602 if ( isprx(i,k,j) ) then
603 ispr_anywhere = .true.
609 dumlogtemp = log( t(i,k,j) )
610 ! dumlogptot = log( pressure in dynes/cm2 )
611 dumlogptot = log( 10.0*pmid(i,k,j) )
613 ! compute removal amounts for each aerosol mode
614 do 3900 n=1,ntype_aer
615 do 3900 m=1,nsize_aer(n)
618 do ll = 1, ncomp_aer(n)
619 l = massptr_aer(ll,m,n,ai_phase)
620 if (l < param_first_scalar) cycle
621 duma = max( chem(i,k,j,l)*1.0e-6, 0.0 )
622 dry_mass = dry_mass + duma ! g-AP/kg-air
623 dry_volu = dry_volu + duma/dens_aer(ll,n) ! cm3-AP/kg-air
625 ! If no aerosol is present at this size and type, there is nothing
626 ! to scavenge so go onto the next size bin. wig, 25-Oct-2005
627 if( dry_volu < 1.0e-26 ) goto 3900
630 l = waterptr_aer(m,n)
631 if (l >= param_first_scalar) then
632 duma = max( chem(i,k,j,l)*1.0e-6, 0.0 )
636 wet_mass = dry_mass + duma
637 wet_volu = dry_volu + duma/dens_water_aer
639 ! calc dry volume of 1 particle
640 dumnumb = chem(i,k,j,numptr_aer(m,n,ai_phase))
641 if (dry_volu > volumhi_sect(m,n)*dumnumb) then
642 dry_volu_1p = volumhi_sect(m,n)
643 else if (dry_volu < volumlo_sect(m,n)*dumnumb) then
644 dry_volu_1p = volumlo_sect(m,n)
646 dry_volu_1p = dry_volu/dumnumb
648 ! interpolate table values using
649 ! dumdgratio = [(actual-wet-diam)/(base-dry-diam)]
650 ! = [(actual-wet-volu)/(base-dry-volu)]**1/3
651 if (wet_volu <= 1.0e9*dry_volu) then
652 duma = wet_volu/dry_volu
656 dumdgratio = ((dry_volu_1p/volumcen_sect(m,n))*duma)**third
658 ! dumwetdens = wet aerosol density in g/cm3
659 dumwetdens = wet_mass/wet_volu
660 dumlogdens = log( dumwetdens )
664 ! compute impaction scavenging removal amount for volume
667 if ((dumdgratio .ge. 0.99) .and. (dumdgratio .le. 1.01)) then
668 scavimptbl1 = scavimptblvol(1,0,m,n)
669 scavimptbl2 = scavimptblvol(2,0,m,n)
670 scavimptbl3 = scavimptblvol(3,0,m,n)
671 scavimptbl4 = scavimptblvol(4,0,m,n)
674 xgrow = log( dumdgratio ) / dlndg_nimptblgrow
676 if (xgrow .lt. 0.) jgrow = jgrow - 1
677 if (jgrow .lt. nimptblgrow_mind) then
678 jgrow = nimptblgrow_mind
681 jgrow = min( jgrow, nimptblgrow_maxd-1 )
684 dumfhi = xgrow - jgrow
687 scavimptbl1 = dumflo*scavimptblvol(1,jgrow,m,n) + &
688 dumfhi*scavimptblvol(1,jgrow+1,m,n)
690 scavimptbl2 = dumflo*scavimptblvol(2,jgrow,m,n) + &
691 dumfhi*scavimptblvol(2,jgrow+1,m,n)
693 scavimptbl3 = dumflo*scavimptblvol(3,jgrow,m,n) + &
694 dumfhi*scavimptblvol(3,jgrow+1,m,n)
696 scavimptbl4 = dumflo*scavimptblvol(4,jgrow,m,n) + &
697 dumfhi*scavimptblvol(4,jgrow+1,m,n)
700 ! apply temperature and pressure corrections
701 dumimpactratea3 = exp( scavimptbl1 + scavimptbl2*dumlogtemp + &
702 scavimptbl3*dumlogptot + scavimptbl4*dumlogdens )
704 ! dumimpactratea3 = impaction scav rate (1/h) for precip = 1 mm/h
705 ! dumimpactrateb3 = impaction scav rate (1/s) for precip = pfx_inrain
706 ! (dumimpactratea3/3600) = impaction scav rate (1/s) for precip = 1 mm/h
707 ! (pfx_inrain*3600) = in-rain-area precip rate (mm/h)
708 ! dumimpactrateb3 = (dumimpactratea3/3600) * (pfx_inrain*3600)
709 ! dumimpactamt3 = fraction of aerosol removed from entire grid cell
711 dumimpactamtsum = 0.0
712 dumimpactrateb3 = dumimpactratea3 * pfx_inrain(i,k,j)
713 dumimpactamt3 = (1. - exp(-deltat*dumimpactrateb3)) * fapx(i,k,j)
714 dumimpactamtsum = dumimpactamtsum + dumimpactamt3
715 dumimpactamt3 = min( dumimpactamtsum, 1.0 )
718 ! dump = 10.0*pmid(i,k)
719 ! call calc_1_impact_rate( dgncur_awet(i,k,j,m,n), &
720 ! sigmag_amode(n), dumwetdens, &
722 ! dumscavratenum, dumscavratevol, lun )
725 ! if (dumscavratevol > 1.0e-35) &
726 ! dumr = (dumimpactratea3/dumscavratevol) - 1.0
727 ! write(lun,9440) nstep, lchnk, i, k, jp, &
728 ! (dumtemp-273.16), dumpress*.001
729 ! write(lun,9442) 'rhowet, dgnwet, dgratio, xgrow', &
730 ! dumwetdens, dgncur_awet(i,k,n), dumdgratio, xgrow
731 ! write(lun,9442) 'exa&approx vol rt, relerr, amt', &
732 ! dumscavratevol, dumimpactratea3, dumr, dumimpactamt3
733 ! write(lun,9442) 'pfx_inrain(1:3) ', &
734 ! (pfx_inrain(jp,i,k), jp=1,3)
735 ! write(lun,9442) 'fapx(1:3) ', &
736 ! (fapx(jp,i,k), jp=1,3)
737 !9440 format( / 'ns,lc,i,k,jp, T(C), p(mb)', i6, 2i4, 2i3, 2f7.1 )
738 !9442 format( a, 4(1pe11.3) )
739 ! end diagnostic output
743 ! compute impaction scavenging removal amount to number
745 if (numptr_aer(m,n,ai_phase) < param_first_scalar) then
746 dumimpactamt0 = dumimpactamt3
750 ! interpolate table values using log of (actual-wet-size)/(base-dry-size)
751 if ((dumdgratio .ge. 0.99) .and. (dumdgratio .le. 1.01)) then
752 scavimptbl1 = scavimptblnum(1,0,m,n)
753 scavimptbl2 = scavimptblnum(2,0,m,n)
754 scavimptbl3 = scavimptblnum(3,0,m,n)
755 scavimptbl4 = scavimptblnum(4,0,m,n)
758 scavimptbl1 = dumflo*scavimptblnum(1,jgrow,m,n) + &
759 dumfhi*scavimptblnum(1,jgrow+1,m,n)
761 scavimptbl2 = dumflo*scavimptblnum(2,jgrow,m,n) + &
762 dumfhi*scavimptblnum(2,jgrow+1,m,n)
764 scavimptbl3 = dumflo*scavimptblnum(3,jgrow,m,n) + &
765 dumfhi*scavimptblnum(3,jgrow+1,m,n)
767 scavimptbl4 = dumflo*scavimptblnum(4,jgrow,m,n) + &
768 dumfhi*scavimptblnum(4,jgrow+1,m,n)
771 ! apply temperature and pressure corrections
772 dumimpactratea0 = exp( scavimptbl1 + scavimptbl2*dumlogtemp + &
773 scavimptbl3*dumlogptot + scavimptbl4*dumlogdens )
776 dumimpactrateb0 = dumimpactratea0 * pfx_inrain(i,k,j)
777 dumimpactamt0 = dumimpactamt0 + &
778 (1. - exp( -deltat*dumimpactrateb0 )) * fapx(i,k,j)
779 dumimpactamt0 = min( dumimpactamt0, 1.0 )
783 ! if (dumscavratenum > 1.0e-35) &
784 ! dumr = (dumimpactratea0/dumscavratenum) - 1.0
785 ! write(lun,9442) 'exa&approx num rt, relerr, amt', &
786 ! dumscavratenum, dumimpactratea0, dumr, dumimpactamt0
787 ! end diagnostic output
795 pdel_dt_fac = deltat*pdel(i,k,j)/g
796 dumrate = -dumimpactamt3/(deltat*(1.0 + 1.0e-8))
797 dumrate = min(0.0,max(-1.0/deltat,dumrate)) ! make sure -1 <= dumrate*deltat <= 0
798 do ll = 1, ncomp_aer(n)
799 l = massptr_aer(ll,m,n,ai_phase)
800 if (l < param_first_scalar) cycle
801 dqdt(i,k,j,l) = chem(i,k,j,l)*dumrate
802 qsrflx(i,j,l) = qsrflx(i,j,l) + dqdt(i,k,j,l)*pdel_dt_fac ! aerosol mass (ug/m2)
804 l = waterptr_aer(m,n)
805 if (l >= param_first_scalar) then
806 dqdt(i,k,j,l) = chem(i,k,j,l)*dumrate
807 qsrflx(i,j,l) = qsrflx(i,j,l) + dqdt(i,k,j,l)*pdel_dt_fac ! aerosol water mass (ug/m2)
809 l = numptr_aer(m,n,ai_phase)
810 if (l >= param_first_scalar) then
811 dumrate = -dumimpactamt0/(deltat*(1.0 + 1.0e-8))
812 dqdt(i,k,j,l) = chem(i,k,j,l)*dumrate
813 qsrflx(i,j,l) = qsrflx(i,j,l) + dqdt(i,k,j,l)*pdel_dt_fac ! aerosol number (1/m2)
818 3900 continue ! "n = 1, ntot_amode"
820 4900 continue ! "k = 1, pver"
822 5900 continue ! "i = 1, ncol"
826 if ( ispr_anywhere ) then
829 do ll = 1, ncomp_aer(n)
830 if (massptr_aer(ll,m,n,ai_phase) >= param_first_scalar) &
831 dotend(massptr_aer(ll,m,n,ai_phase)) = .true.
833 if (waterptr_aer(m,n) >= param_first_scalar) &
834 dotend(waterptr_aer(m,n)) = .true.
835 if (numptr_aer(m,n,ai_phase) >= param_first_scalar) &
836 dotend(numptr_aer(m,n,ai_phase)) = .true.
843 end subroutine aerimpactscav
847 !===========================================================================
848 !===========================================================================
849 subroutine initwet( ntype_aer, nsize_aer, ncomp_aer, massptr_aer, &
850 dens_aer, numptr_aer, maxd_acomp, maxd_asize,maxd_atype, &
851 maxd_aphase, dcen_sect, sigmag_aer, waterptr_aer, dens_water_aer, &
852 scavimptblvol, scavimptblnum, nimptblgrow_mind, nimptblgrow_maxd, &
854 !-----------------------------------------------------------------------
857 ! Computes lookup table for aerosol impaction/interception scavenging rates
861 !-----------------------------------------------------------------------
864 integer, intent(in) :: maxd_atype, maxd_asize, maxd_acomp, maxd_aphase
865 integer, intent(in) :: ntype_aer
866 integer, intent(in) :: nsize_aer( maxd_atype ) ! number of size bins
867 integer, intent(in) :: ncomp_aer( maxd_atype ) ! number of chemical components
868 integer, intent(in) :: massptr_aer( maxd_acomp, maxd_asize, maxd_atype, maxd_aphase) ! index for mixing ratio
869 integer, intent(in) :: waterptr_aer( maxd_asize, maxd_atype ) ! index for aerosol water
870 integer, intent(in) :: numptr_aer( maxd_asize, maxd_atype, maxd_aphase ) ! index for the number mixing ratio
871 real, intent(in) :: dens_aer( maxd_acomp, maxd_atype ) ! material density (g/cm3)
872 real, intent(in) :: dens_water_aer ! water density (g/m3)
873 real, intent(in) :: sigmag_aer(maxd_asize, maxd_atype)
874 real, intent(in) :: dcen_sect( maxd_asize, maxd_atype )
875 ! "base" volume-mean diameter (cm) == section center diameter
876 ! scav rates for aerosol number and volume are pre-calculated for a range of volume-mean diameters
877 ! as well as aerosol densities and air pressure and temperature
878 ! for specific time/location/aerosol properties, these rates are interpolated, and
879 ! the size interpolation uses [(actual volume-mean diameter)/(base volume-mean diameter)]
881 real, intent(out) :: dlndg_nimptblgrow
882 integer, intent(in) :: nimptblgrow_mind, nimptblgrow_maxd
883 real, intent(out) :: scavimptblnum(4, nimptblgrow_mind:nimptblgrow_maxd, maxd_asize, maxd_atype)
884 real, intent(out) :: scavimptblvol(4, nimptblgrow_mind:nimptblgrow_maxd, maxd_asize, maxd_atype)
888 parameter (nnfit_maxd=27)
890 integer i, j, m, n, jgrow, jdens, jpress, jtemp, ll, mode, nnfit
893 real dg0, dg0_base, press, rhodryaero, rhowetaero, rmserr, &
894 scavratenum, scavratevol, sigmag, &
895 temp, wetdiaratio, wetvolratio
896 real aafitnum(4), xxfitnum(4,nnfit_maxd), yyfitnum(nnfit_maxd)
897 real aafitvol(4), xxfitvol(4,nnfit_maxd), yyfitvol(nnfit_maxd)
901 dlndg_nimptblgrow = log( 1.25d00 )
903 do 7900 n=1,ntype_aer
904 do 7900 m=1,nsize_aer(n)
906 sigmag = sigmag_aer(m,n)
907 dg0_base = dcen_sect(m,n)*exp( -1.5*((log(sigmag))**2) )
909 ! for setting up the lookup table, use the dry density of the first
910 ! chemical component of the aerosol type (which currently will be so4)
911 rhodryaero = dens_aer(1,n)
913 do 7800 jgrow = nimptblgrow_mind, nimptblgrow_maxd
915 wetdiaratio = exp( jgrow*dlndg_nimptblgrow )
916 dg0 = dg0_base*wetdiaratio
918 wetvolratio = exp( jgrow*dlndg_nimptblgrow*3. )
919 rhowetaero = 1.0 + (rhodryaero-1.0)/wetvolratio
920 rhowetaero = min( rhowetaero, rhodryaero )
923 ! compute impaction scavenging rates at 9 temp-press pairs and save
927 do 5900 jtemp = -1, 1
928 temp = 273.16 + 25.*jtemp
930 do 5900 jpress = -1, 1
931 press = 0.75e6 + 0.25e6*jpress
934 rhowetaero = rhodryaero**(0.5*jdens)
936 call calc_1_impact_rate( &
937 dg0, sigmag, rhowetaero, temp, press, &
938 scavratenum, scavratevol, lunerr )
941 if (nnfit .gt. nnfit_maxd) then
942 call wrf_error_fatal('*** subr. aerosol_impact_setup -- nnfit too big')
945 xxfitnum(1,nnfit) = 1.
946 xxfitnum(2,nnfit) = log( temp )
947 xxfitnum(3,nnfit) = log( press )
948 xxfitnum(4,nnfit) = log( rhowetaero )
949 yyfitnum(nnfit) = log( scavratenum )
951 xxfitvol(1,nnfit) = 1.
952 xxfitvol(2,nnfit) = log( temp )
953 xxfitvol(3,nnfit) = log( press )
954 xxfitvol(4,nnfit) = log( rhowetaero )
955 yyfitvol(nnfit) = log( scavratevol )
960 ! do linear regression
961 ! log(scavrate) = a1 + a2*log(temp) + a3*log(press) + a4*log(wetdens)
963 call mlinft( xxfitnum, yyfitnum, aafitnum, nnfit, 4, 4, rmserr )
964 call mlinft( xxfitvol, yyfitvol, aafitvol, nnfit, 4, 4, rmserr )
967 scavimptblnum(i,jgrow,m,n) = aafitnum(i)
968 scavimptblvol(i,jgrow,m,n) = aafitvol(i)
976 end subroutine initwet
980 !===========================================================================
981 !===========================================================================
982 subroutine calc_1_impact_rate( &
983 dg0, sigmag, rhoaero, temp, press, &
984 scavratenum, scavratevol, lunerr )
986 ! routine computes a single impaction scavenging rate
987 ! for precipitation rate of 1 mm/h
989 ! dg0 = geometric mean diameter of aerosol number size distrib. (cm)
990 ! sigmag = geometric standard deviation of size distrib.
991 ! rhoaero = density of aerosol particles (g/cm^3)
992 ! temp = temperature (K)
993 ! press = pressure (dyne/cm^2)
994 ! scavratenum = number scavenging rate (1/h)
995 ! scavratevol = volume or mass scavenging rate (1/h)
996 ! lunerr = logical unit for error message
1002 real dg0, sigmag, rhoaero, temp, press, scavratenum, scavratevol
1006 parameter (nrainsvmax=50)
1007 real rrainsv(nrainsvmax), xnumrainsv(nrainsvmax),&
1008 vfallrainsv(nrainsvmax)
1011 parameter (naerosvmax=51)
1012 real aaerosv(naerosvmax), &
1013 ynumaerosv(naerosvmax), yvolaerosv(naerosvmax)
1015 integer i, ja, jr, na, nr
1016 real a, aerodiffus, aeromass, ag0, airdynvisc, airkinvisc
1017 real anumsum, avolsum, boltzmann, cair, chi
1018 real d, dr, dum, dumfuchs, dx
1019 real ebrown, eimpact, eintercept, etotal, freepath, gravity
1020 real pi, precip, precipmmhr, precipsum
1021 real r, rainsweepout, reynolds, rhi, rhoair, rhowater, rlo, rnumsum
1022 real scavsumnum, scavsumnumbb
1023 real scavsumvol, scavsumvolbb
1024 real schmidt, sqrtreynolds, sstar, stokes, sx
1025 real taurelax, vfall, vfallstp
1026 real x, xg0, xg3, xhi, xlo, xmuwaterair
1032 nr = 1 + nint( (rhi-rlo)/dr )
1033 if (nr .gt. nrainsvmax) then
1034 call wrf_error_fatal('*** subr. calc_1_impact_rate -- nr > nrainsvmax')
1038 precip = precipmmhr/36000. ! cm/s
1043 xg3 = xg0 + 3.*sx*sx
1049 dx = max( 0.2*sx, 0.01 )
1050 xlo = xg3 - max( 4.*sx, 2.*dx )
1051 xhi = xg3 + max( 4.*sx, 2.*dx )
1053 na = 1 + nint( (xhi-xlo)/dx )
1054 if (na .gt. naerosvmax) then
1055 call wrf_error_fatal('*** subr. calc_1_impact_rate -- na > naerosvmax')
1059 cair = press/(8.31436e7*temp)
1061 rhoair = 28.966*cair
1062 ! molecular freepath
1063 freepath = 2.8052e-10/cair
1064 ! boltzmann constant
1065 boltzmann = 1.3807e-16
1070 ! air dynamic viscosity
1071 airdynvisc = 1.8325e-4 * (416.16/(temp+120.)) * &
1072 ((temp/296.16)**1.5)
1073 ! air kinemaic viscosity
1074 airkinvisc = airdynvisc/rhoair
1075 ! ratio of water viscosity to air viscosity (from Slinn)
1081 ! compute rain drop number concentrations
1082 ! rrainsv = raindrop radius (cm)
1083 ! xnumrainsv = raindrop number concentration (#/cm^3)
1084 ! (number in the bin, not number density)
1085 ! vfallrainsv = fall velocity (cm/s)
1091 xnumrainsv(i) = exp( -r/2.7e-2 )
1094 if (d .le. 0.007) then
1095 vfallstp = 2.88e5 * d**2.
1096 else if (d .le. 0.025) then
1097 vfallstp = 2.8008e4 * d**1.528
1098 else if (d .le. 0.1) then
1099 vfallstp = 4104.9 * d**1.008
1100 else if (d .le. 0.25) then
1101 vfallstp = 1812.1 * d**0.638
1103 vfallstp = 1069.8 * d**0.235
1106 vfall = vfallstp * sqrt(1.204e-3/rhoair)
1107 vfallrainsv(i) = vfall
1108 precipsum = precipsum + vfall*(r**3)*xnumrainsv(i)
1110 precipsum = precipsum*pi*1.333333
1114 xnumrainsv(i) = xnumrainsv(i)*(precip/precipsum)
1115 rnumsum = rnumsum + xnumrainsv(i)
1119 ! compute aerosol concentrations
1120 ! aaerosv = particle radius (cm)
1121 ! fnumaerosv = fraction of total number in the bin (--)
1122 ! fvolaerosv = fraction of total volume in the bin (--)
1131 ynumaerosv(i) = exp( -0.5*dum*dum )
1132 yvolaerosv(i) = ynumaerosv(i)*1.3333*pi*a*a*a
1133 anumsum = anumsum + ynumaerosv(i)
1134 avolsum = avolsum + yvolaerosv(i)
1138 ynumaerosv(i) = ynumaerosv(i)/anumsum
1139 yvolaerosv(i) = yvolaerosv(i)/avolsum
1144 ! compute scavenging
1149 ! outer loop for rain drop radius
1154 vfall = vfallrainsv(jr)
1156 reynolds = r * vfall / airkinvisc
1157 sqrtreynolds = sqrt( reynolds )
1160 ! inner loop for aerosol particle radius
1172 dumfuchs = 1. + 1.246*dum + 0.42*dum*exp(-0.87/dum)
1173 taurelax = 2.*rhoaero*a*a*dumfuchs/(9.*rhoair*airkinvisc)
1175 aeromass = 4.*pi*a*a*a*rhoaero/3.
1176 aerodiffus = boltzmann*temp*taurelax/aeromass
1178 schmidt = airkinvisc/aerodiffus
1179 stokes = vfall*taurelax/r
1181 ebrown = 4.*(1. + 0.4*sqrtreynolds*(schmidt**0.3333333)) / &
1184 dum = (1. + 2.*xmuwaterair*chi) / &
1185 (1. + xmuwaterair/sqrtreynolds)
1186 eintercept = 4.*chi*(chi + dum)
1188 dum = log( 1. + reynolds )
1189 sstar = (1.2 + dum/12.) / (1. + dum)
1191 if (stokes .gt. sstar) then
1192 dum = stokes - sstar
1193 eimpact = (dum/(dum+0.6666667)) ** 1.5
1196 etotal = ebrown + eintercept + eimpact
1197 etotal = min( etotal, 1.0 )
1199 rainsweepout = xnumrainsv(jr)*4.*pi*r*r*vfall
1201 scavsumnumbb = scavsumnumbb + rainsweepout*etotal*ynumaerosv(ja)
1202 scavsumvolbb = scavsumvolbb + rainsweepout*etotal*yvolaerosv(ja)
1206 scavsumnum = scavsumnum + scavsumnumbb
1207 scavsumvol = scavsumvol + scavsumvolbb
1210 scavratenum = scavsumnum*3600.
1211 scavratevol = scavsumvol*3600.
1216 end subroutine calc_1_impact_rate
1220 !===========================================================================
1221 !===========================================================================
1222 subroutine gasrainscav (ims,ime,kms,kme,jms,jme,its,ite,kts,kte,jts,jte,num_chem, &
1224 deltat, t, pmid, pdel, &
1226 isprx, fapx, pfx, pfx_inrain, &
1227 dqdt, dotend, qsrflx )
1230 !-----------------------------------------------------------------------
1233 ! Does below cloud scavenging of gases by rain
1236 ! Irreversible uptake of h2so4 and msa
1237 ! Reactive uptake of so2 and h2o2. This is assumed to be rate limited
1238 ! by the mass transfer to rain (and not by aqueous reaction)
1240 ! Authors: R. Easter
1242 !-----------------------------------------------------------------------
1243 USE module_model_constants, only: g,rhowater, mwdry
1244 use module_configure, only: grid_config_rec_type, &
1245 param_first_scalar, &
1246 p_so2, p_h2o2, p_sulf,p_h2so4, p_msa, &
1247 p_hno3, p_hcl, p_nh3
1251 !-----------------------------------------------------------------------
1255 ! abbreviations & acronyms
1256 ! TMR = tracer mixing ratio
1258 ! dp-cnv = deep convective
1259 ! sh-cnv = shallow convective
1261 integer, intent(in) :: num_chem ! number of chemical species
1262 integer, intent(in) :: ims,ime ! column dimension
1263 integer, intent(in) :: kms,kme ! level dimension
1264 integer, intent(in) :: jms,jme ! column dimension
1265 integer, intent(in) :: its,ite ! column identifier
1266 integer, intent(in) :: kts,kte ! level identifier
1267 integer, intent(in) :: jts,jte ! column identifier
1268 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
1270 real, intent(in) :: deltat ! model timestep
1272 real, intent(in) :: t(ims:ime,kms:kme,jms:jme) ! temperature
1273 real, intent(in) :: pmid(ims:ime,kms:kme,jms:jme) ! pressure at model levels
1274 real, intent(in) :: pdel(ims:ime,kms:kme,jms:jme) ! pressure thickness of levels
1275 real, intent(in) :: chem(ims:ime,kms:kme,jms:jme,num_chem) ! TMR array including chemistry
1277 logical, intent(in) :: isprx(ims:ime,kms:kme,jms:jme) ! true if precip at i,k
1278 real, intent(in) :: fapx(ims:ime,kms:kme,jms:jme) ! frac. area for precip
1279 real, intent(in) :: pfx(ims:ime,kms:kme,jms:jme) ! grid-avg precip
1281 real, intent(in) :: pfx_inrain(ims:ime,kms:kme,jms:jme) ! precip flux (kg/m2/s)
1283 real, intent(out) :: dqdt(ims:ime,kms:kme,jms:jme,num_chem) ! TMR tendency array
1284 logical, intent(inout) :: dotend(num_chem) ! flag for doing scav
1285 real, intent(inout) :: qsrflx(ims:ime,jms:jme,num_chem)
1286 ! changes to column tracer burdens by wet scavenging over current timestep
1287 ! this routine adds on the contribution from gas scavenging
1288 ! by mass transfer to rain
1290 !--------------------------Local Variables------------------------------
1292 integer :: i, j, k ! x, y, z work index
1293 integer :: jp ! precip type index
1295 logical :: ispr_anywhere
1297 integer, parameter :: ng = 7
1298 integer, parameter :: ig_so2 = 1
1299 integer, parameter :: ig_h2o2 = 2
1300 integer, parameter :: ig_h2so4 = 3
1301 integer, parameter :: ig_msa = 4
1302 integer, parameter :: ig_hno3 = 5
1303 integer, parameter :: ig_hcl = 6
1304 integer, parameter :: ig_nh3 = 7
1305 integer :: ig, lg, lg_ptr(ng)
1307 real :: amtscav(ng), amtscav_sub(ng)
1309 real :: fracscav(ng), fracscav_sub(ng)
1311 real :: dum, dumamt, dumprecipmmh, dumpress, dumtemp
1314 real :: scavrate_hno3
1315 real :: scavrate(ng), scavrate_factor(ng)
1317 !-----------------------------------------------------------------------
1320 ! if (ncol .ne. -987654321) return
1322 ! precip rates -- 1.0 kgwtr/m2/s = 1.0e-3 m3wtr/m2/s = 1.0e-3 m/s
1323 ! = 1.0 mm/s = 3600 mm/h
1325 ispr_anywhere = .false.
1326 deltatinv = 1.0/(deltat*(1.0d0 + 1.0d-15))
1328 p1st = param_first_scalar
1330 lg_ptr(ig_so2 ) = p_so2
1331 lg_ptr(ig_h2o2 ) = p_h2o2
1332 lg_ptr(ig_h2so4) = p_sulf
1333 lg_ptr(ig_h2so4) = p_h2so4
1334 lg_ptr(ig_msa ) = p_msa
1335 lg_ptr(ig_hno3 ) = p_hno3
1336 lg_ptr(ig_hcl ) = p_hcl
1337 lg_ptr(ig_nh3 ) = p_nh3
1339 scavrate_factor(ig_so2 ) = 1.08
1340 scavrate_factor(ig_h2o2 ) = 1.38
1341 scavrate_factor(ig_h2so4) = 0.80
1342 scavrate_factor(ig_msa ) = 0.80
1343 scavrate_factor(ig_hno3 ) = 1.00
1344 scavrate_factor(ig_hcl ) = 1.15
1345 scavrate_factor(ig_nh3 ) = 1.59
1353 ! skip this level if no precip
1354 if ( isprx(i,k,j) ) then
1355 ispr_anywhere = .true.
1361 ! skip this level if below freezing
1363 if (dumtemp .le. 273.16) goto 4900
1364 dumpress = 10.0*pmid(i,k,j)
1370 if (lg .ge. p1st) then
1371 r_gc(ig) = max( chem(i,k,j,lg), 0.0 )
1372 ! activate this after gas_aqfrac is added to arguments
1373 ! if (lg .le. numgas_aqfrac) &
1374 ! fracgas(ig) = gas_aqfrac(lg)
1380 if ( .not. isprx(i,k,j) ) goto 3600
1382 ! precip rate in mm/h over rainy portion of the subarea
1383 dumprecipmmh = pfx_inrain(i,k,j)*3600.0
1385 ! rain scavenging rate for hno3 (power law fit to schwarz and levine,
1386 ! with temperature and pressure adjustments) -- units are (1/s)
1387 scavrate_hno3 = 6.262e-5*(dumprecipmmh**0.7366) &
1388 * ((dumtemp/298.0)**1.12) &
1389 * ((1.013e6/dumpress)**.75)
1392 scavrate(ig) = scavrate_hno3*scavrate_factor(ig)
1393 fracscav_sub(ig) = (1. - exp(-scavrate(ig)*deltat)) &
1394 *fracgas(ig)*fapx(i,k,j)
1395 amtscav_sub(ig) = r_gc(ig)*min( fracscav_sub(ig), 1.0 )
1398 ! for so2 & h2o2, assume aqueous oxidation is fast, so reactive
1399 ! uptake is limited by the smaller of the two mass transfer rates
1400 dumamt = min( amtscav_sub(ig_so2), amtscav_sub(ig_h2o2) )
1401 fracscav_sub(ig_so2 ) = dumamt/max( r_gc(ig_so2 ), 1.0e-30 )
1402 fracscav_sub(ig_h2o2) = dumamt/max( r_gc(ig_h2o2), 1.0e-30 )
1403 amtscav_sub(ig_so2 ) = r_gc(ig_so2 )*min( fracscav_sub(ig_so2 ), 1.0 )
1404 amtscav_sub(ig_h2o2) = r_gc(ig_h2o2)*min( fracscav_sub(ig_h2o2), 1.0 )
1406 ! for nh3, limit uptake by uptake of all acid gases combined
1407 dumamt = 2.0*amtscav_sub(ig_so2) &
1408 + 2.0*amtscav_sub(ig_h2so4) + amtscav_sub(ig_msa) &
1409 + amtscav_sub(ig_hno3) + amtscav_sub(ig_hcl)
1410 dumamt = min( dumamt, amtscav_sub(ig_nh3) )
1411 fracscav_sub(ig_nh3) = dumamt/max( r_gc(ig_nh3), 1.0e-30 )
1412 amtscav_sub(ig_nh3 ) = r_gc(ig_nh3 )*min( fracscav_sub(ig_nh3 ), 1.0 )
1415 fracscav(ig) = fracscav(ig) + fracscav_sub(ig)
1419 ! write(lun,9440) nstep, lchnk, i, k, jp, &
1420 ! (dumtemp-273.16), dumpress*.001
1421 ! write(lun,9442) 'pfx, pfx_inrain, fapx ', &
1422 ! pfx(jp,i,k), pfx_inrain(jp,i,k), fapx(jp,i,k)
1423 ! write(lun,9442) 'scavrate_so2, h2o2, msa, h2so4 ', &
1424 ! scavrate(ig_so2), scavrate(ig_h2o2), &
1425 ! scavrate(ig_msa), scavrate(ig_h2so4)
1426 ! write(lun,9442) 'rso2gc, rso2g, rh2o2gc, rh2o2g ', &
1427 ! r_gc(ig_so2), r_gc(ig_so2)*fracgas(ig)so2), &
1428 ! r_gc(ig_h2o2), r_gc(ig_h2o2)*fracgas(ig)h2o2),
1429 ! write(lun,9442) 'amtscav_sub so2, h2o2 ', &
1430 ! amtscav_sub(ig_so2), amtscav_sub(ig_h2o2)
1431 ! write(lun,9442) 'fracscav_sub so2, h2o2, msa, h2so4 ', &
1432 ! fracscav_sub(ig_so2), fracscav_sub(ig_h2o2), &
1433 ! fracscav_sub(ig_msa), fracscav_sub(ig_h2so4)
1434 !9440 format( / 'ns,lc,i,k,jp, T(C), p(mb)', i6, 2i4, 2i3, 2f7.1 )
1435 !9442 format( a, 4(1pe11.3) )
1436 ! end diagnostic output
1442 ! compute tendencies
1444 pdel_fac = (pdel(i,k,j)/(g*mwdry))
1447 fracscav(ig) = max(0.0,min(1.0,fracscav(ig))) ! make sure 0 <= fracscav <= 1
1448 amtscav(ig) = fracscav(ig)*r_gc(ig)
1450 if (lg .ge. p1st) then
1451 dqdt(i,k,j,lg) = -deltatinv*amtscav(ig)
1452 qsrflx(i,j,lg) = qsrflx(i,j,lg) - pdel_fac*amtscav(ig) ! mmol/m2
1456 4900 continue ! "k = 1, pver"
1458 5900 continue ! "i = 1, ncol"
1462 if ( ispr_anywhere ) then
1464 if (lg_ptr(ig) .ge. p1st) dotend(lg_ptr(ig)) = .true.
1470 end subroutine gasrainscav
1474 !===========================================================================
1475 !===========================================================================
1476 subroutine mlinft( x, y, a, n, m, mmaxd, rmserr )
1478 ! fits y = a(1)*x(1) + a(2)*x(2) + ... + a(m)*x(m)
1480 ! x - array containing x values
1481 ! x(i,k) is parameter i, observation k
1482 ! y - array containing y values
1483 ! y(k) is observation
1484 ! a - array !ontaining the regression coefficients
1485 ! n - number of observations
1486 ! m - number of parameters
1487 ! mmaxd - first dimension of the x array
1488 ! rmserr - root mean square residual
1489 ! rmserr = sqrt( avg-sq-err )
1490 ! avg-sq-err = (sum of residuals squared)/(number of values)
1491 ! residual = y - (a1*x1 + a2*x2 + ... + am*xm)
1497 real x(mmaxd,n), y(n), a(mmaxd), rmserr
1500 integer i, j, jflag, k
1501 real aa(10,10), bb(10), errsq, resid, ydum
1517 aa(i,j) = aa(i,j) + x(i,k)*x(j,k)
1519 bb(i) = bb(i) + x(i,k)*y(k)
1525 ! write(13,9300) i, (aa(i,j), j=1,m), bb(i)
1527 !9300 format( i5, 5f15.2 )
1529 ! subr linsolv( a, x, b, n, m1, m2, jflag )
1530 call linsolv( aa, a, bb, m, 10, 10, jflag )
1537 ydum = ydum + a(i)*x(i,k)
1540 errsq = errsq + resid*resid
1542 rmserr = sqrt( errsq/n )
1545 end subroutine mlinft
1549 !===========================================================================
1550 !===========================================================================
1551 subroutine linsolv( a, x, b, n, m1, m2, jflag )
1553 ! solves linear eqn system a*x = b using gaussian-elimination
1554 ! with partial pivoting
1556 ! n = order of the system
1557 ! m1, m2 = fortran dimensions of a array
1558 ! jflag = completion flag
1559 ! 1 - system solved successfully
1560 ! 0 - system is singular or close to it, and could not be solved.
1561 ! computation was halted to avoid overflow or divide by zero.
1563 ! *** note *** rsmall should be defined as close to but somewhat larger
1564 ! than the smallest single precision real on the computer.
1566 ! initial coding on 29-aug-86 by r.c. easter
1567 ! change on 4-feb-89 by r.c.easter -- added jflag to parameter list
1568 ! and checking for singularity
1573 integer n, m1, m2, jflag
1574 real a(m1,m2), x(n), b(n)
1577 integer i, imax, iup, j, k
1578 real amax, asmall, dmy, rsmall
1579 parameter (rsmall = 1.0e-16)
1584 ! reduce coef. matrix to upper triangular form
1588 ! find pivot element, and
1589 ! move pivot row into row k if necessary
1592 amax = abs( a(imax,k) )
1594 if (abs(a(i,k)) .gt. amax) then
1599 if (amax .eq. 0.) return
1601 if (imax .ne. k) then
1615 asmall = abs(a(k,k))
1617 if (a(i,k) .ne. 0.0) then
1618 if (asmall .le. abs(rsmall*a(i,k))) return
1622 a(i,j) = a(i,j) - dmy*a(k,j)
1624 b(i) = b(i) - dmy*b(k)
1637 dmy = dmy - a(i,j)*x(j)
1639 asmall = abs(a(i,i))
1640 if (abs(a(i,i)) .le. abs(rsmall*dmy)) return
1647 end subroutine linsolv
1649 END MODULE module_mosaic_wetscav