1 module module_mosaic_aerdynam_intr
10 !-----------------------------------------------------------------------
12 ! *** eventually need to pass some performance stats back to mosaic driver
14 subroutine aerosoldynamics( & !intent-ins
17 ktau, ktauc, dtchem, &
18 tempbox, presbox, airdenbox, relhumbox, &
20 rbox, iter_mesa, jaerosolstate, & !intent-inouts
23 ! subroutine aerosoldynamics( it, t_out, t_in, & !intent-ins
24 ! pr_atm, rh, te, cair_mol_m3, &
25 ! cnn, jaerosolstate, dp_wet_a, & !intent-inouts
26 ! aH2O_a, gam_ratio, iter_MESA ) !intent-outs
28 use module_data_mosaic_kind, only: r8
29 use module_data_mosaic_main, only: &
30 mw_air, m_partmc_mosaic, ntot_max, ntot_used
31 use module_data_mosaic_aero, only : &
32 dens_aer_mac, mw_aer_mac, mw_comp_a, &
33 jhyst_undefined, msectional, msize_framework, &
34 naer, nbin_a, nbin_a_max, ngas_aerchtot, no_aerosol, nsalt
36 use module_mosaic_aerchem_intr, only: aerchemistry
37 use module_mosaic_sect_intr, only: sectional_interface_1
41 integer, intent(in) :: idiagbb_host
42 integer, intent(in) :: id, ii, jj, kk
43 integer, intent(in) :: ktau, ktauc
44 ! integer, intent(in) :: it
45 integer, intent(inout), dimension(nbin_a_max) :: jaerosolstate
46 ! integer, intent(out), dimension(nbin_a_max) :: iter_mesa
47 integer, intent(inout), dimension(nbin_a_max) :: iter_mesa
49 real(r8), intent(in) :: dtchem ! chemistry time step (s)
50 ! real(r8), intent(in) :: t_out, t_in
51 ! real(r8), intent(in) :: pr_atm, rh, te, cair_mol_m3
52 real(r8), intent(in) :: tempbox ! temperature (deg k)
53 real(r8), intent(in) :: presbox ! pressure (pa)
54 real(r8), intent(in) :: airdenbox ! air density (kg/m3)
55 real(r8), intent(in) :: relhumbox ! relative humidity (0-1)
56 real(r8), intent(in) :: swdownbox !
58 ! real(r8), intent(inout), dimension(ntot_max) :: cnn
59 real(r8), intent(inout), dimension(ntot_used) :: rbox
61 real(r8), intent(inout), dimension(nbin_a_max) :: dp_dry_a
62 real(r8), intent(inout), dimension(nbin_a_max) :: dp_wet_a
63 ! real(r8), intent(out), dimension(nbin_a_max) :: aH2O_a, gam_ratio
66 integer :: it_host, it_mosaic
67 integer, dimension(6) :: hostgridinfox
68 integer, dimension(nbin_a_max) :: jaerosolstate_bgn
69 integer, dimension(nbin_a_max) :: jhyst_leg, jhyst_leg_sv1
71 logical :: ldiag1, ldiag2
73 real(r8) :: cair_mol_cc, cair_mol_m3
74 real(r8) :: fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr
79 real(r8), dimension(ngas_aerchtot) :: gas_avg ! average gas conc. over dtchem time step (nmol/m3)
80 real(r8), dimension(ngas_aerchtot) :: gas_netprod_otrproc
81 ! gas_netprod_otrproc = gas net production rate from other processes
82 ! such as gas-phase chemistry and emissions (nmol/m3/s)
83 ! NOTE - currently in the mosaic box model, gas_netprod_otrproc is set to zero for all
84 ! species, so mosaic_aerchemistry does not apply production and condensation together
85 real(r8), dimension(nbin_a_max) :: aH2O_a
86 real(r8), dimension(nbin_a_max) :: gam_ratio
87 real(r8), dimension(nbin_a_max) :: dens_dry_a_bgn, dens_dry_a
88 ! real(r8), dimension(nbin_a_max) :: dp_dry_a, dp_dry_a_sv1
89 real(r8), dimension(nbin_a_max) :: dp_dry_a_sv1
90 real(r8), dimension(nbin_a_max) :: mass_dry_a_bgn, mass_dry_a
91 real(r8), dimension(nbin_a_max) :: sigmag_a, sigmag_a_sv1
93 real(r8), allocatable, dimension(:) :: rbox_sv1
94 ! real(r8), allocatable, dimension(:) :: rbox, rbox_sv1
96 if (idiagbb_host >= 100) then
97 ldiag1 = .true. ; ldiag2 = .true.
99 ldiag1 = .false. ; ldiag2 = .false.
103 call dump_aerdy( 'dya', & !intent-ins
105 ktau, ktauc, dtchem, &
106 tempbox, presbox, airdenbox, relhumbox, &
107 rbox, iter_mesa, jaerosolstate, & !intent-inouts
110 if ( ldiag1 ) write(*,*) 'aerosoldynamics start'
111 if ( (m_partmc_mosaic <= 0) .and. &
112 (msize_framework == msectional) ) then
113 if ( .not. allocated( rbox_sv1 ) ) allocate( rbox_sv1(1:ntot_used) )
114 ! allocate( rbox_sv1(1:ntot_used) )
116 ! allocate( rbox(1:ntot_used) )
118 ! dtchem = t_out - t_in
121 hostgridinfox(1) = id
122 hostgridinfox(2) = ii
123 hostgridinfox(3) = jj
124 hostgridinfox(4) = kk
125 hostgridinfox(5:6) = 0
128 rh = relhumbox*100.0_r8 ! rh - convert 0-1 value to %
130 pr_atm = presbox / 1.01325e5_r8 ! air pressure - convert Pa to atm
131 pr_atm = presbox / 1.032e5_r8 ! *** this is used in module_mosaic_therm ***
133 cair_mol_m3 = airdenbox*1.0e3_r8/mw_air ! air conc - convert kg/m3 to mol/m3
134 cair_mol_cc = cair_mol_m3*1.e-6_r8 ! air conc - convert mol/m3 to mol/cm3
136 iter_mesa(1:nbin_a_max) = 0
137 jaerosolstate(1:nbin_a_max) = no_aerosol
138 jaerosolstate_bgn(1:nbin_a_max) = no_aerosol
139 jhyst_leg(1:nbin_a_max) = jhyst_undefined
140 jhyst_leg_sv1(1:nbin_a_max) = jhyst_undefined
142 gas_avg(1:ngas_aerchtot) = 0.0_r8
143 gas_netprod_otrproc(1:ngas_aerchtot) = 0.0_r8
145 ah2o_a(1:nbin_a_max) = 0.0_r8
146 gam_ratio(1:nbin_a_max) = 0.0_r8
147 dens_dry_a(1:nbin_a_max) = 0.0_r8
148 dens_dry_a_bgn(1:nbin_a_max) = 0.0_r8
149 dp_wet_a(1:nbin_a_max) = 0.0_r8
150 dp_dry_a(1:nbin_a_max) = 0.0_r8
151 dp_dry_a_sv1(1:nbin_a_max) = 0.0_r8
152 mass_dry_a(1:nbin_a_max) = 0.0_r8
153 mass_dry_a_bgn(1:nbin_a_max) = 0.0_r8
154 sigmag_a(1:nbin_a_max) = 0.0_r8
155 sigmag_a_sv1(1:nbin_a_max) = 0.0_r8
158 ! map variables from cnn array to rbox (and other) arrays
159 if ( ldiag1 ) write(*,*) 'aerosoldynamics call map 0'
160 call aerodynam_map_mosaic_species( 0, &
161 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr, &
163 ! call aerodynam_map_mosaic_species( 0, cair_mol_cc, cair_mol_m3, &
164 ! fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr, &
165 ! cnn, rbox, jaerosolstate, jhyst_leg, dp_dry_a, sigmag_a )
168 if ( (m_partmc_mosaic <= 0) .and. &
169 (msize_framework == msectional) ) then
170 rbox_sv1(1:ntot_used) = rbox(1:ntot_used)
171 dp_dry_a_sv1(1:nbin_a) = dp_dry_a(1:nbin_a)
172 sigmag_a_sv1(1:nbin_a) = sigmag_a(1:nbin_a)
173 jhyst_leg_sv1(1:nbin_a) = jhyst_leg(1:nbin_a)
178 call dump_aerdy( 'dyc', & !intent-ins
180 ktau, ktauc, dtchem, &
181 tempbox, presbox, airdenbox, relhumbox, &
182 rbox, iter_mesa, jaerosolstate, & !intent-inouts
185 if ( ldiag1 ) write(*,*) 'aerosoldynamics call aerchem'
188 hostgridinfox, it_host, it_mosaic, dtchem, & !intent-ins
189 pr_atm, rh, te, cair_mol_m3, cair_mol_cc, swdownbox, &
190 jaerosolstate, jaerosolstate_bgn, jhyst_leg, & !intent-inouts
191 rbox, dp_dry_a, dp_wet_a, sigmag_a, &
192 gas_avg, gas_netprod_otrproc, &
193 mass_dry_a_bgn, mass_dry_a, dens_dry_a_bgn, dens_dry_a, &
194 aH2O_a, gam_ratio, iter_mesa ) !intent-outs
198 call dump_aerdy( 'dye', & !intent-ins
200 ktau, ktauc, dtchem, &
201 tempbox, presbox, airdenbox, relhumbox, &
202 rbox, iter_mesa, jaerosolstate, & !intent-inouts
205 ! for sectional framework, calculate
206 ! transfer of particles betweens due to growth/shrinkage
207 ! new particle nucleation (optional)
208 ! particle coagulation (optional)
209 if ( (m_partmc_mosaic <= 0) .and. &
210 (msize_framework == msectional) ) then
212 if ( ldiag1 ) write(*,*) 'aerosoldynamics call sectiface'
213 call sectional_interface_1( &
215 id, ii, jj, kk, ktau, ktauc, dtchem, &
217 it_mosaic, jaerosolstate_bgn, jaerosolstate, &
218 jhyst_leg, jhyst_leg_sv1, &
219 dp_dry_a, dp_dry_a_sv1, &
220 sigmag_a, sigmag_a_sv1, &
221 mass_dry_a_bgn, mass_dry_a, dens_dry_a_bgn, dens_dry_a, &
222 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr, &
223 pr_atm, rh, te, cair_mol_m3, cair_mol_cc )
225 ! deallocate( rbox_sv1 )
227 !else if (msize_framework == mmodal) then
228 ! do similar calculations for modal framework, but this not yet implemented
232 ! map variables back to cnn array from rbox (and other) arrays
233 ! not need in wrfchem
234 ! call aerodynam_map_mosaic_species( 1, cair_mol_cc, cair_mol_m3, &
235 ! fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr, &
236 ! cnn, rbox, jaerosolstate, jhyst_leg, dp_dry_a, sigmag_a )
240 if ( ldiag1 ) write(*,*) 'aerosoldynamics end'
244 call dump_aerdy( 'dyz', & !intent-ins
246 ktau, ktauc, dtchem, &
247 tempbox, presbox, airdenbox, relhumbox, &
248 rbox, iter_mesa, jaerosolstate, & !intent-inouts
252 end subroutine aerosoldynamics
256 !-----------------------------------------------------------------------
257 subroutine aerodynam_map_mosaic_species( imap, &
258 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr, &
260 ! subroutine aerodynam_map_mosaic_species( imap, cair_mol_cc, cair_mol_m3, &
261 ! fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr, &
262 ! cnn, rbox, jaerosolstate, jhyst_leg, dp_dry_a, sigmag_a )
265 ! in the mosaic offline box model, this subr. maps between cnn array and rbox array
266 ! and does a few other things
267 ! in wrfchem, this subr. just does a few other things
270 use module_data_mosaic_kind
271 ! use module_data_mosaic_main, only: &
273 ! kdpdry_a, kjhyst_a, knum_a, ksigmag_a, kwater_a, &
274 ! mw_air, naer_tot, ngas_max, ntot_max, ntot_used
275 use module_data_mosaic_aero, only: &
278 ! jhyst_lo, jhyst_up, jhyst_undefined, &
279 ! mhyst_method, mhyst_force_lo, mhyst_force_up, &
280 ! mhyst_uporlo_jhyst, mhyst_uporlo_waterhyst, &
281 ! mmovesect_flag1, mw_aer_mac, &
282 ! naer, naercomp, nbin_a, nbin_a_max, &
283 ! all_solid, all_liquid, mixed, no_aerosol
284 use module_data_mosaic_asecthp, only: &
285 dcen_sect, sigmag_aer, isize_of_ibin, itype_of_ibin
287 ! dens_aer, dens_water_aer, &
288 ! hygro_aer, hyswptr_aer, &
289 ! isize_of_ibin, itype_of_ibin, &
290 ! massptr_aer, ncomp_aer
294 integer, intent(in) :: imap
295 ! integer, intent(in), dimension(nbin_a_max) :: jaerosolstate
296 ! integer, intent(inout), dimension(nbin_a_max) :: jhyst_leg
298 ! real(r8), intent(in) :: cair_mol_cc, cair_mol_m3
299 real(r8), intent(inout) :: fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_gasmr
300 ! real(r8), intent(inout) :: cnn(ntot_max)
301 ! real(r8), intent(inout) :: rbox(ntot_used)
302 real(r8), intent(inout), dimension(nbin_a_max) :: sigmag_a
306 integer :: ibin, iphase, isize, itype
307 ! integer :: l, ll, noffset
308 ! real(r8) :: conv_diam, conv_drym, conv_gas, conv_numb, conv_watr
309 ! real(r8) :: tmpa, tmph, tmpj, tmpr
310 character(len=256) :: errmsg
312 if ((imap < 0) .or. (imap > 1)) then
314 '*** aerchem_map_mosaic_cnn_rbox fatal error - bad imap =', imap
315 call wrf_error_fatal(trim(adjustl(errmsg)))
319 ! set rbox units factors
321 ! note that the movesect and coag routines expect the aerosol mass units
322 ! for rbox to be mass mixing ratios or mass concentrations
323 ! they do not apply any molecular weight factors, so they cannot
324 ! work with molar mixing ratios or molar concentrations
326 ! for trace gases, rbox = [umol/mol-air = ppmv], rbox*fact_gasmr = [mol/mol-air]
327 fact_gasmr = 1.0e-6_r8
329 ! for aerosol mass, rbox = [ug-AP/kg-air], rbox*fact_apmassmr = [g-AP/g-air]
330 fact_apmassmr = 1.0e-9_r8
332 ! for aerosol numb, rbox = [#/kg-air], rbox*fact_apnumbmr = [#/g-air]
333 fact_apnumbmr = 1.0e-3_r8
335 ! aerosol densities in mosaic aerchem and sectional routines = [g/cm^3]
336 ! (mosaic densities)*fact_apdens = [g/cm^3]
339 ! aerosol diameters in mosaic aerchem and sectional routines = [cm]
340 ! (mosaic diameters)*fact_apdiam = [cm]
344 ! factors for converting cnn values to rbox (and dp_dry_a_ values
345 ! tmpa = cair_mol_m3*mw_air ! air_density in ]g/m^3]
347 ! cnn is [molecules/cm^3-air], rbox = cnn*conv_gas is [umol/mol-air]
348 ! conv_gas = 1.0_r8/(avogad*cair_mol_cc*fact_gasmr)
350 ! cnn is [#/cm^3-air], rbox = cnn*conv_numb is [#/kg-air] when iunits_flagaa=4
351 ! conv_numb = 1.0e6_r8 /(fact_apnumbmr*tmpa)
353 ! cnn is [umol/m^3-air], rbox = cnn*conv_drym*mw_aer is [ug/kg-air] when iunits_flagaa=4
354 ! conv_drym = 1.0e-6_r8/(fact_apmassmr*tmpa)
356 ! cnn is [kg/m^3-air], rbox = cnn*conv_watr is [ug/kg-air] when iunits_flagaa=4
357 ! conv_watr = 1.0e3_r8 /(fact_apmassmr*tmpa)
359 ! cnn is [um], dp_dry_a = cnn*conv_apdiam is [cm]
360 ! conv_diam = 1.0e-4_r8/fact_apdiam
363 if (imap == 1) goto 20000
367 ! imap = 0 --> map from cnn to rbox
369 ! rbox(1:ntot_used) = 0.0_r8
372 ! rbox(l) = cnn(l)*conv_gas
376 isize = isize_of_ibin(ibin)
377 itype = itype_of_ibin(ibin)
378 ! noffset = ngas_max + (ibin-1)*naer_tot
380 ! rbox may or may not be able to hold dp_dry_a and sigma_g
381 ! (yes in box model, no in wrfchem)
382 ! so do not used rbox for holding dp_dry_a and sigma_g
383 ! dp_dry_a(ibin) = cnn(kdpdry_a +noffset)*conv_diam
384 ! sigmag_a(ibin) = cnn(ksigmag_a+noffset)
385 sigmag_a(ibin) = sigmag_aer(isize,itype)
387 ! rbox(knum_a +noffset) = cnn(knum_a +noffset)*conv_numb
388 ! rbox(kwater_a +noffset) = cnn(kwater_a +noffset)*conv_watr
390 ! l = noffset + (naer_tot-naer) + ll
391 ! rbox(l) = cnn(l)*(conv_drym*mw_aer_mac(ll))
394 ! if (mhyst_method == mhyst_uporlo_waterhyst) then
395 ! cnn and rbox hold water_a_hyst (in water conc units)
396 ! SO convert cnn value to rbox value
397 ! AND set jhyst_leg to undefined
398 ! rbox(kjhyst_a +noffset) = cnn(kjhyst_a+noffset)*conv_watr
399 ! jhyst_leg(ibin) = jhyst_undefined
401 ! cnn holds jhyst_leg, which can have three possible values
402 ! rbox will eventually hold a surrogate for water_a_hyst
403 ! SO set jhyst_leg directly from cnn
404 ! AND set rbox value to zero
405 ! rbox(kjhyst_a +noffset) = 0.0_r8
406 ! tmpa = cnn(noffset + kjhyst_a)
407 ! if (tmpa < -0.5_r8) then
408 ! jhyst_leg(ibin) = jhyst_undefined
409 ! else if (tmpa < 0.5_r8) then
410 ! jhyst_leg(ibin) = jhyst_lo
412 ! jhyst_leg(ibin) = jhyst_up
423 ! imap = 1 --> map from rbox to cnn
426 ! cnn(l) = rbox(l)/conv_gas
429 ! do ibin = 1, nbin_a
430 ! isize = isize_of_ibin(ibin)
431 ! itype = itype_of_ibin(ibin)
432 ! noffset = ngas_max + (ibin-1)*naer_tot
434 ! cnn(kdpdry_a +noffset) = dp_dry_a(ibin)/conv_diam
435 ! cnn(ksigmag_a+noffset) = sigmag_a(ibin)
437 ! cnn(knum_a +noffset) = rbox(knum_a +noffset)/conv_numb
438 ! cnn(kwater_a +noffset) = rbox(kwater_a +noffset)/conv_watr
440 ! l = noffset + (naer_tot-naer) + ll
441 ! cnn(l) = rbox(l)/(conv_drym*mw_aer_mac(ll))
444 ! if (mhyst_method == mhyst_uporlo_waterhyst) then
445 ! cnn and rbox hold water_a_hyst (in water conc units)
446 ! SO convert rbox value to cnn value
447 ! AND leave jhyst_leg to unchanged
448 ! cnn(kjhyst_a+noffset) = rbox(kjhyst_a+noffset)/conv_watr
450 ! cnn holds jhyst_leg, which can have three possible values
451 ! rbox will eventually hold a surrogate for water_a_hyst
452 ! SO set cnn directly from jhyst_leg
453 ! AND leave rbox value unchanged
454 ! cnn(kjhyst_a+noffset) = jhyst_leg(ibin)*1.0_r8
460 end subroutine aerodynam_map_mosaic_species
464 !-----------------------------------------------------------------------
465 subroutine dump_aerdy( dumpchaa, & !intent-ins
467 ktau, ktauc, dtchem, &
468 tempbox, presbox, airdenbox, relhumbox, &
469 rbox, iter_mesa, jaerosolstate, & !intent-inouts
472 use module_data_mosaic_kind, only: r8
473 use module_data_mosaic_main, only: &
475 use module_data_mosaic_aero, only : &
477 use module_data_mosaic_asecthp, only : &
478 nsize_aer, ntype_aer, numptr_aer, lptr_bc_aer, lptr_oc_aer, lptr_oin_aer
480 use module_mosaic_aerchem_intr, only: aerchemistry
481 use module_mosaic_sect_intr, only: sectional_interface_1
484 !Subroutine arguments
485 character(len=*), intent(in) :: dumpchaa
487 integer, intent(in) :: id, ii, jj, kk
488 integer, intent(in) :: ktau, ktauc
489 integer, intent(inout), dimension(nbin_a_max) :: jaerosolstate
490 integer, intent(inout), dimension(nbin_a_max) :: iter_mesa
492 real(r8), intent(in) :: dtchem ! chemistry time step (s)
493 real(r8), intent(in) :: tempbox ! temperature (deg k)
494 real(r8), intent(in) :: presbox ! pressure (pa)
495 real(r8), intent(in) :: airdenbox ! air density (kg/m3)
496 real(r8), intent(in) :: relhumbox ! relative humidity (0-1)
498 real(r8), intent(inout), dimension(ntot_used) :: rbox
500 real(r8), intent(inout), dimension(nbin_a_max) :: dp_dry_a
501 real(r8), intent(inout), dimension(nbin_a_max) :: dp_wet_a
504 integer :: isize, itype
506 character(len=80) :: fmtaa
508 if (ii*jj*kk /= 1) return
510 fmtaa = '(2a,1p,e10.3,7e11.3)'
511 if (nsize_aer(1)*ntype_aer > 8) fmtaa = '(2a,1p,e10.3,7e11.3/(7x,1p,e10.3,7e11.3))'
513 ! number output units = #/cm3 = (rbox #/kg-air)*(airden kg-air/m3)*(1e-6 m3/cm3)
514 tmpa = airdenbox*1.0e-6_r8
515 write(131,fmtaa) dumpchaa, ' num', &
516 ( ( rbox(numptr_aer(isize,itype,1))*tmpa, &
517 isize=1,nsize_aer(itype) ), itype=1,ntype_aer )
519 ! mass output units = nmol/m3 = (rbox ug/kg-air)*(airden kg-air/m3)*(1e3 ng/ug)/(molecwght ng/nmol)
520 ! and mosaic molecwght = 1.0 for oin, oc, and bc
521 tmpa = airdenbox*1.0e3_r8
522 write(131,fmtaa) dumpchaa, ' oin', &
523 ( ( rbox(lptr_oin_aer(isize,itype,1))*tmpa, &
524 isize=1,nsize_aer(itype) ), itype=1,ntype_aer )
525 write(131,fmtaa) dumpchaa, ' oc ', &
526 ( ( rbox(lptr_oc_aer(isize,itype,1))*tmpa, &
527 isize=1,nsize_aer(itype) ), itype=1,ntype_aer )
528 write(131,fmtaa) dumpchaa, ' bc ', &
529 ( ( rbox(lptr_bc_aer(isize,itype,1))*tmpa, &
530 isize=1,nsize_aer(itype) ), itype=1,ntype_aer )
533 end subroutine dump_aerdy
537 end module module_mosaic_aerdynam_intr