1 module module_mosaic_movesect3d
4 use module_data_mosaic_kind, only: r8
5 use module_data_mosaic_main, only: mw_air, ntot_used, pi
6 use module_data_mosaic_asecthp, only: lunerr, lunout
16 !-----------------------------------------------------------------------
17 !**********************************************************************************
18 ! following routines adapted from
19 ! fjaersky:/home/d37080/box/aqchem/pandis/ccboxwrf6/module_mosaic_movesect.F.saveaa
20 !**********************************************************************************
23 !-----------------------------------------------------------------------
24 subroutine move_sect_3d_x1( iphase_flag, iclm, jclm, k, m, rbox, &
25 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, &
26 drydens_aftgrow, drydens_pregrow, &
27 drymass_aftgrow, drymass_pregrow, &
28 adrydens_tmp, awetdens_tmp, adrydpav_tmp, awetdpav_tmp, &
29 adryqmas_tmp, it_mosaic, mmovesect_flag1, idiag_movesect )
31 ! routine transfers aerosol number and mass between sections
32 ! to account for continuous aerosol growth
33 ! this routine is called after the gas condensation module (MOSAIC) or
34 ! aqueous chemistry module has increased the mass within sections
36 ! moving-center algorithm or mass-number advection algorithm is used,
37 ! depending on value of mod(mmovesect_flag1,100)
38 ! section mean diameter is given by
39 ! vtot = ntot * (pi/6) * (dmean**3)
40 ! where vtot and ntot are total dry-volume and number for the section
41 ! if dmean is outside the section boundaries (dlo_sect & dhi_sect), then
42 ! all the mass and number in the section are transfered to the
43 ! section with dlo_sect(nnew) < dmean < dhi_sect(nnew)
45 ! mass mixing ratios are in rbox(massptr_aer(ll,n,itype,iphase))
46 ! units such that rbox*fact_apmassmr gives (g-AP/g-air)
47 ! number mixing ratios are in rbox(numptr_aer(n,itype,iphase))
48 ! units such that rbox*fact_apnumbmr gives (#/g-air)
49 ! these values are over-written with new values
51 ! the following are also updated:
52 ! adrydens_tmp(n,itype), adrydpav_tmp(n,itype),
53 ! awetdens_tmp(n,itype), awetdpav_tmp(n,itype)
54 ! adryqmas_tmp(n,itype)
56 ! the module_data_mosaic_asecthp densities are such that
57 ! dens_aer*fact_apdens give (g/cm^3)
58 ! the module_data_mosaic_asecthp diameters are such that
59 ! dlo/hi_sect*fact_apdiam give (cm)
60 ! the module_data_mosaic_asecthp volumes are such that
61 ! volumlo/hi_sect**fact_apdiam**3) give (cm^3)
64 ! iphase_flag = 1 - do transfer after trace-gas condensation/evaporation
65 ! = 2 - do transfer after aqueous chemistry
66 ! = -1/-2 - do some "first entry" tasks for the iphase_flag=+1/+2 cases
68 ! iclm, jclm, k = current i,j,k indices
69 ! m = current subarea index
71 ! drymass_pregrow(n,itype) = dry-mass for section n before the growth
72 ! drymass_aftgrow(n,itype) = dry-mass for section n after the growth
73 ! but before inter-section transfer
74 ! (units for both are same as rbox mass entries)
75 ! drydens_pregrow(n,itype) = dry-density for section n before the growth
76 ! drydens_aftgrow(n,itype) = dry-density for section n after the growth
77 ! but before inter-section transfer
78 ! (units for both are same as dens_aer)
80 ! (drymass_pregrow and drydens_pregrow are used by the linear-discrete
81 ! algorithm but not the moving-center algorithm)
83 ! method_movesect (from first two digits of movesect_flag1, which
84 ! is a "data_module" variable)
85 ! 50-59 - do 3d moving-center algorithm
86 ! 60-69 - do 3d linear-discrete algorithm
88 use module_data_mosaic_asecthp, only: &
89 maxd_acomp, maxd_asize, maxd_atype, &
90 ntype_aer, nsize_aer, nphase_aer, ai_phase, cw_phase, &
91 dens_aer, dcen_sect, &
92 smallmassaa_asecthp => smallmassaa, smallmassbb_asecthp => smallmassbb, &
93 volumcen_sect, volumlo_sect, volumhi_sect
98 integer, intent(in) :: iphase_flag, iclm, jclm, k, m, it_mosaic, &
99 mmovesect_flag1, idiag_movesect
101 real(r8), intent(inout) :: rbox(ntot_used)
103 real(r8), intent(in) :: fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam
105 real(r8), intent(in) :: drymass_pregrow(maxd_asize,maxd_atype)
106 real(r8), intent(in) :: drydens_pregrow(maxd_asize,maxd_atype)
107 real(r8), intent(in) :: drymass_aftgrow(maxd_asize,maxd_atype)
108 real(r8), intent(in) :: drydens_aftgrow(maxd_asize,maxd_atype)
110 real(r8), intent(inout) :: adrydens_tmp(maxd_asize,maxd_atype), awetdens_tmp(maxd_asize,maxd_atype)
111 real(r8), intent(inout) :: adrydpav_tmp(maxd_asize,maxd_atype), awetdpav_tmp(maxd_asize,maxd_atype)
112 real(r8), intent(inout) :: adryqmas_tmp(maxd_asize,maxd_atype)
113 ! adrydens_tmp = aerosol dry density (units same as dens_aer)
114 ! awetdens_tmp = aerosol wet density (units same as dens_aer)
115 ! adrydpav_tmp = aerosol mean dry diameter (units same as dlo_sect)
116 ! awetdpav_tmp = aerosol mean wet diameter (units same as dlo_sect)
117 ! adryqmas_tmp = aerosol total-dry-mass mixing ratio (units same as rbox)
120 integer iphase, isize, itype, &
121 l, ll, llhysw, llwater, lnew, lold, l3, &
122 method_movesect, n, nnew, nold
123 integer nnewsave(2,maxd_asize,maxd_atype)
124 integer itypenewsave(4,maxd_asize,maxd_atype)
127 real(r8) delta_water_conform1, delta_numb_conform1
129 real(r8) smallmassaa, smallmassbb
131 real(r8) dcen_stmp(maxd_asize,maxd_atype)
132 real(r8) densdefault(maxd_atype)
133 real(r8) drydenspp(maxd_asize,maxd_atype), drydensxx0(maxd_asize,maxd_atype), &
134 drydensxx(maxd_asize,maxd_atype), drydensyy(maxd_asize,maxd_atype)
135 real(r8) drymasspp(maxd_asize,maxd_atype), drymassxx0(maxd_asize,maxd_atype), &
136 drymassxx(maxd_asize,maxd_atype), drymassyy(maxd_asize,maxd_atype)
137 real(r8) dryvolxx(maxd_asize,maxd_atype), dryvolyy(maxd_asize,maxd_atype)
138 real(r8) rmassxx(maxd_acomp+2,maxd_asize,maxd_atype), &
139 rmassyy(maxd_acomp+2,maxd_asize,maxd_atype)
140 real(r8) rnumbpp(maxd_asize,maxd_atype), rnumbxx0(maxd_asize,maxd_atype), &
141 rnumbxx(maxd_asize,maxd_atype), rnumbyy(maxd_asize,maxd_atype)
142 real(r8) specdensxx(maxd_acomp)
143 real(r8) xferfracvol(2,4,maxd_asize,maxd_atype), xferfracnum(2,4,maxd_asize,maxd_atype)
144 real(r8) volumcen_stmp(maxd_asize,maxd_atype), &
145 volumlo_stmp(maxd_asize,maxd_atype), volumhi_stmp(maxd_asize,maxd_atype)
146 real(r8) wetvolxx(maxd_asize,maxd_atype), wetvolyy(maxd_asize,maxd_atype)
147 real(r8) wetmassxx(maxd_asize,maxd_atype), wetmassyy(maxd_asize,maxd_atype)
153 ! check for valid inputs
155 if (mmovesect_flag1 <= 0) return
156 if (ntype_aer <= 0) return
157 if (nphase_aer <= 0) return
160 ! get "method_movesect" from digits 1-2 of mmovesect_flag1
161 method_movesect = mod( max(0,mmovesect_flag1), 100 )
163 if ((method_movesect/10 .eq. 5) .or. &
164 (method_movesect/10 .eq. 6)) then
167 msg = '*** subr move_sect_3d error - ' // &
168 'illegal value for mmovesect_flag1'
169 call peg_error_fatal( lunerr, msg )
174 if (iabs(iphase_flag) .eq. 1) then
176 else if (iabs(iphase_flag) .eq. 2) then
178 ! if (nphase_aer .lt. 2) then
179 ! msg = '*** subr move_sect_3d error - ' // &
180 ! 'iphase_flag=2 (after aqueous chemistry) but nphase_aer < 2'
181 ! call peg_error_fatal( lunerr, msg )
182 ! else if (cw_phase .ne. 2) then
183 ! msg = '*** subr move_sect_3d error - ' // &
184 ! 'iphase_flag=2 (after aqueous chemistry) but cw_phase .ne. 2'
185 ! call peg_error_fatal( lunerr, msg )
187 msg = '*** subr move_sect_3d error - ' // &
188 'iphase_flag=2 (after aqueous chemistry) is not implemented'
189 call peg_error_fatal( lunerr, msg )
191 msg = '*** subr move_sect_3d error - ' // &
192 'iabs(iphase_flag) must be 1 or 2'
193 call peg_error_fatal( lunerr, msg )
197 ! when iphase_flag=-1/-2, call move_sect_3d_checkptrs then return
198 ! if ((ncorecnt .le. 0) .and. (k .le. 1)) then
199 if (iphase_flag .le. 0) then
200 write(msg,9040) 'method, idiag', method_movesect, idiag_movesect
201 call peg_message( lunout, msg )
202 call move_sect_3d_checkptrs( iphase_flag, iclm, jclm, k, m )
204 else if (it_mosaic .le. 1) then
205 ! otherwise call in on first time step
206 ! with movesect_3d, all the types must have the same sizes, species, ...
207 call move_sect_3d_checkptrs( -iphase_flag, iclm, jclm, k, m )
209 9040 format( '*** subr move_sect_3d - ', a, ' =', 2(1x,i6) )
213 if (idiag_movesect .ge. 70) then
215 call peg_message( lunout, msg )
216 write(msg,9060) mmovesect_flag1, iclm, jclm, k, m, it_mosaic
217 call peg_message( lunout, msg )
219 9060 format( '*** move_sect_3d diags - ', &
220 'msflag, ijkm, itime =', i7, 4i4, i7 )
224 smallmassaa = smallmassaa_asecthp
225 smallmassbb = smallmassbb_asecthp
227 ! smallmassaa & smallmassbb are now set in module_data_mosaic_asecthp
229 ! if bin mass mixrat < smallmassaa (1.e-22 g/g), then assume no growth
230 ! AND no water AND conform number so that size is within bin limits
232 ! if bin mass OR volume mixrat < smallmassbb (1.e-30 g/g), then
233 ! assume default density to avoid divide by zero
236 ! calc single particle sizes and volumes in (cm) and (cm^3)
237 fact_apvolu = fact_apdiam*fact_apdiam*fact_apdiam
238 ! write(*,'(/a,1p,5e12.4/)') 'fact_ap...', &
239 ! fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_apvolu
240 do itype = 1, ntype_aer
241 densdefault(itype) = dens_aer(1,itype)*fact_apdens ! use density of first component as default
242 do isize = 1, nsize_aer(itype)
243 dcen_stmp( isize,itype) = dcen_sect( isize,itype)*fact_apdiam
244 volumcen_stmp(isize,itype) = volumcen_sect(isize,itype)*fact_apvolu
245 volumlo_stmp( isize,itype) = volumlo_sect( isize,itype)*fact_apvolu
246 volumhi_stmp( isize,itype) = volumhi_sect( isize,itype)*fact_apvolu
251 ! process all types simultaneously
252 do itype = 1, ntype_aer
253 do isize = 1, nsize_aer(itype)
254 drydenspp(isize,itype) = drydens_pregrow(isize,itype)*fact_apdens
255 drydensxx(isize,itype) = drydens_aftgrow(isize,itype)*fact_apdens
257 drymasspp(isize,itype) = drymass_pregrow(isize,itype)*fact_apmassmr
258 drymassxx(isize,itype) = drymass_aftgrow(isize,itype)*fact_apmassmr
262 ! write(*,*) 'move_sect_3d_x1 before initial_conform'
263 call move_sect_3d_initial_conform( &
264 iphase_flag, iclm, jclm, k, m, iphase, &
265 method_movesect, idiag_movesect, llhysw, llwater, &
266 densdefault, densh2o, smallmassaa, smallmassbb, &
267 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_apvolu, &
268 delta_water_conform1, delta_numb_conform1, &
270 drydenspp, drymasspp, rnumbpp, &
271 drydensxx0, drymassxx0, rnumbxx0, &
272 drydensxx, drymassxx, dryvolxx, rmassxx, rnumbxx, &
273 wetmassxx, wetvolxx, specdensxx, &
274 volumcen_stmp, volumlo_stmp, volumhi_stmp )
276 if (method_movesect/10 .eq. 5) then
277 ! write(*,*) 'move_sect_3d_x1 before calc_movingcenter'
278 call move_sect_3d_calc_movingcenter( &
279 iphase_flag, iclm, jclm, k, m, iphase, &
280 method_movesect, idiag_movesect, llhysw, llwater, &
281 nnewsave, itypenewsave, &
282 densdefault, densh2o, smallmassaa, smallmassbb, &
283 drydensxx, drymassxx, dryvolxx, rmassxx, rnumbxx, &
284 wetmassxx, wetvolxx, &
285 xferfracvol, xferfracnum, &
286 volumcen_stmp, volumlo_stmp, volumhi_stmp )
288 call move_sect_3d_calc_masnumadvect( &
289 iphase_flag, iclm, jclm, k, m, iphase, &
290 method_movesect, idiag_movesect, llhysw, llwater, &
291 nnewsave, itypenewsave, &
292 densdefault, densh2o, smallmassaa, smallmassbb, &
293 drydenspp, drymasspp, rnumbpp, &
294 drydensxx0, drymassxx0, rnumbxx0, &
295 drydensxx, drymassxx, dryvolxx, rmassxx, rnumbxx, &
296 wetmassxx, wetvolxx, &
297 xferfracvol, xferfracnum, &
298 volumcen_stmp, volumlo_stmp, volumhi_stmp )
301 ! write(*,*) 'move_sect_3d_x1 before apply_moves'
302 call move_sect_3d_apply_moves( &
303 iphase_flag, iclm, jclm, k, m, iphase, &
304 method_movesect, idiag_movesect, llhysw, llwater, &
305 nnewsave, itypenewsave, &
306 densdefault, densh2o, smallmassaa, smallmassbb, &
307 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_apvolu, &
308 delta_water_conform1, delta_numb_conform1, &
310 drydenspp, drymasspp, rnumbpp, &
311 drymassxx, dryvolxx, rmassxx, rnumbxx, wetmassxx, wetvolxx, &
312 drymassyy, dryvolyy, rmassyy, rnumbyy, wetmassyy, wetvolyy, &
313 xferfracvol, xferfracnum, &
314 dcen_stmp, volumcen_stmp, volumlo_stmp, volumhi_stmp, &
315 adrydens_tmp, awetdens_tmp, adrydpav_tmp, awetdpav_tmp, &
320 end subroutine move_sect_3d_x1
323 !-----------------------------------------------------------------------
324 subroutine move_sect_3d_initial_conform( &
325 iphase_flag, iclm, jclm, k, m, iphase, &
326 method_movesect, idiag_movesect, llhysw, llwater, &
327 densdefault, densh2o, smallmassaa, smallmassbb, &
328 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_apvolu, &
329 delta_water_conform1, delta_numb_conform1, &
331 drydenspp, drymasspp, rnumbpp, &
332 drydensxx0, drymassxx0, rnumbxx0, &
333 drydensxx, drymassxx, dryvolxx, rmassxx, rnumbxx, &
334 wetmassxx, wetvolxx, specdensxx, &
335 volumcen_stmp, volumlo_stmp, volumhi_stmp )
338 ! routine does some initial tasks for the section movement
339 ! load rmassxx & rnumbxx from rbox
341 ! set drymassxx & dryvolxx from drymass_aftgrow & drydens_aftgrow,
342 ! OR compute them from rmassxx, specdensxx if need be
343 ! set wetmassxx & wetvolxx from dry values & water mass
344 ! conform rnumbxx so that the mean particle size of each section
345 ! (= dryvolxx/rnumbxx) is within the section limits
347 use module_data_mosaic_asecthp, only: &
348 maxd_acomp, maxd_asize, maxd_atype, &
349 nsize_aer, ntype_aer, ncomp_aer, ncomp_plustracer_aer, ai_phase, &
350 massptr_aer, numptr_aer, waterptr_aer, hyswptr_aer, &
356 integer iphase_flag, iclm, jclm, iphase, k, &
357 m, method_movesect, idiag_movesect, llhysw, llwater
358 real(r8) densh2o, smallmassaa, smallmassbb
359 real(r8) fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_apvolu
360 real(r8) delta_water_conform1, delta_numb_conform1
361 real(r8) densdefault(maxd_atype)
362 real(r8) drydenspp(maxd_asize,maxd_atype), drydensxx0(maxd_asize,maxd_atype), &
363 drydensxx(maxd_asize,maxd_atype)
364 real(r8) drymasspp(maxd_asize,maxd_atype), drymassxx0(maxd_asize,maxd_atype), &
365 drymassxx(maxd_asize,maxd_atype)
366 real(r8) dryvolxx(maxd_asize,maxd_atype)
367 real(r8) rbox(ntot_used)
368 real(r8) rmassxx(maxd_acomp+2,maxd_asize,maxd_atype)
369 real(r8) rnumbpp(maxd_asize,maxd_atype), rnumbxx0(maxd_asize,maxd_atype), &
370 rnumbxx(maxd_asize,maxd_atype)
371 real(r8) specdensxx(maxd_acomp)
372 real(r8) volumcen_stmp(maxd_asize,maxd_atype), &
373 volumlo_stmp(maxd_asize,maxd_atype), volumhi_stmp(maxd_asize,maxd_atype)
374 real(r8) wetvolxx(maxd_asize,maxd_atype)
375 real(r8) wetmassxx(maxd_asize,maxd_atype)
379 integer itype, l, ll, lnew, lold, l3, n, nnew, nold
381 real(r8) dummass, dumnum, dumnum_at_dhi, dumnum_at_dlo, dumr, &
382 dumvol, dumvol1p, dumwatrmass
386 ! note - all types must have same species in same order
387 ! and subr move_sect_3d_checkptrs checks for this
389 do ll = 1, ncomp_plustracer_aer(itype)
390 specdensxx(ll) = dens_aer(ll,itype)*fact_apdens
393 ! assure positive definite
395 rbox(l) = max( 0.0_r8, rbox(l) )
399 delta_water_conform1 = 0.0
400 delta_numb_conform1 = 0.0
403 ! main loop over types
405 do 1900 itype = 1, ntype_aer
407 ! load mixrats into working arrays and assure positive definite
408 llhysw = ncomp_plustracer_aer(itype) + 1
409 llwater = ncomp_plustracer_aer(itype) + 2
410 do n = 1, nsize_aer(itype)
411 do ll = 1, ncomp_plustracer_aer(itype)
412 l = massptr_aer(ll,n,itype,iphase)
413 rmassxx(ll,n,itype) = rbox(l)*fact_apmassmr
415 rmassxx(llhysw,n,itype) = 0.
417 if (iphase .eq. ai_phase) l = hyswptr_aer(n,itype)
418 if (l .gt. 0) rmassxx(llhysw,n,itype) = rbox(l)*fact_apmassmr
419 rmassxx(llwater,n,itype) = 0.
421 if (iphase .eq. ai_phase) l = waterptr_aer(n,itype)
422 if (l .gt. 0) rmassxx(llwater,n,itype) = rbox(l)*fact_apmassmr
424 rnumbxx(n,itype) = rbox(numptr_aer(n,itype,iphase))*fact_apnumbmr
425 rnumbxx0(n,itype) = rnumbxx(n,itype)
426 rnumbpp(n,itype) = rnumbxx(n,itype)
428 drydensxx0(n,itype) = drydensxx(n,itype)
429 drymassxx0(n,itype) = drymassxx(n,itype)
432 do 1390 n = 1, nsize_aer(itype)
435 ! if drydens_aftgrow < 0.1 g/cm^3, then bin had state="no_aerosol"
436 ! compute volume using default dry-densities, set water=0,
437 ! and conform the number
438 ! also do this if mass is extremely small (below smallmassaa)
439 ! OR if drydens_aftgrow > 20 g/cm^3 (which is unreal(r8))
441 if ( (drydensxx(n,itype) .lt. 0.1) .or. &
442 (drydensxx(n,itype) .gt. 20.0) .or. &
443 (drymassxx(n,itype) .le. smallmassaa) ) then
446 do ll = 1, ncomp_aer(itype)
447 dumr = rmassxx(ll,n,itype)
448 dummass = dummass + dumr
449 dumvol = dumvol + dumr/specdensxx(ll)
451 drymassxx(n,itype) = dummass
452 if (min(dummass,dumvol) .le. smallmassbb) then
453 drydensxx(n,itype) = densdefault(itype)
454 dumvol = dummass/densdefault(itype)
455 dumnum = dummass/(volumcen_stmp(n,itype)*densdefault(itype))
457 drydensxx(n,itype) = dummass/dumvol
458 dumnum = rnumbxx(n,itype)
459 dumnum_at_dhi = dumvol/volumhi_stmp(n,itype)
460 dumnum_at_dlo = dumvol/volumlo_stmp(n,itype)
461 dumnum = max( dumnum_at_dhi, min( dumnum_at_dlo, dumnum ) )
463 delta_numb_conform1 = delta_numb_conform1 + dumnum - rnumbxx(n,itype)
464 rnumbxx(n,itype) = dumnum
465 rnumbpp(n,itype) = rnumbxx(n,itype)
466 delta_water_conform1 = delta_water_conform1 - rmassxx(llwater,n,itype)
467 rmassxx(llwater,n,itype) = 0.
470 ! load dry/wet mass and volume into "xx" arrays
471 ! which hold values before inter-mode transferring
472 dryvolxx(n,itype) = drymassxx(n,itype)/drydensxx(n,itype)
473 dumwatrmass = rmassxx(llwater,n,itype)
474 wetmassxx(n,itype) = drymassxx(n,itype) + dumwatrmass
475 wetvolxx(n,itype) = dryvolxx(n,itype) + dumwatrmass/densh2o
482 end subroutine move_sect_3d_initial_conform
485 !-----------------------------------------------------------------------
486 subroutine move_sect_3d_calc_movingcenter( &
487 iphase_flag, iclm, jclm, k, m, iphase, &
488 method_movesect, idiag_movesect, llhysw, llwater, &
489 nnewsave, itypenewsave, &
490 densdefault, densh2o, smallmassaa, smallmassbb, &
491 drydensxx, drymassxx, dryvolxx, rmassxx, rnumbxx, &
492 wetmassxx, wetvolxx, &
493 xferfracvol, xferfracnum, &
494 volumcen_stmp, volumlo_stmp, volumhi_stmp )
496 ! routine calculates section movements for the moving-center approach
498 ! material in section n will be transfered to section nnewsave(1,n)
500 ! the nnewsave are calculated here
501 ! the actual transfer is done in another routine
503 use module_data_mosaic_aero, only: &
504 method_bcfrac, method_kappa, msectional_flag2
505 use module_data_mosaic_asecthp, only: &
506 dens_aer, hygro_aer, &
507 itype_md1_of_itype, itype_md2_of_itype, itype_of_itype_md1md2, &
508 lptr_bc_aer, massptr_aer, &
509 maxd_acomp, maxd_asize, maxd_atype, &
510 ncomp_aer, nsize_aer, ntype_aer, ntype_md1_aer, ntype_md2_aer, &
511 xcut_atype_md1, xcut_atype_md2
516 integer iphase_flag, iclm, jclm, iphase, k, &
517 m, method_movesect, idiag_movesect, llhysw, llwater
518 integer nnewsave(2,maxd_asize,maxd_atype)
519 integer itypenewsave(4,maxd_asize,maxd_atype)
520 real(r8) densh2o, smallmassaa, smallmassbb
521 real(r8) densdefault(maxd_atype)
522 real(r8) drydensxx(maxd_asize,maxd_atype)
523 real(r8) drymassxx(maxd_asize,maxd_atype)
524 real(r8) dryvolxx(maxd_asize,maxd_atype)
525 real(r8) rmassxx(maxd_acomp+2,maxd_asize,maxd_atype)
526 real(r8) rnumbxx(maxd_asize,maxd_atype)
527 real(r8) xferfracvol(2,4,maxd_asize,maxd_atype), xferfracnum(2,4,maxd_asize,maxd_atype)
528 real(r8) volumcen_stmp(maxd_asize,maxd_atype), &
529 volumlo_stmp(maxd_asize,maxd_atype), volumhi_stmp(maxd_asize,maxd_atype)
530 real(r8) wetmassxx(maxd_asize,maxd_atype)
531 real(r8) wetvolxx(maxd_asize,maxd_atype)
534 integer isize, itype, itype1, itype2, itypenew, itype1new, itype2new
536 integer jtype1, jtype2
537 integer ll, n, ndum, ndumb, nnew, nold
538 real(r8) dumnum, dumvol, dumvol1p, sixoverpi, third
539 real(r8) tmpa, tmpb, tmpc, tmpd, tmpe, tmpf
540 real(r8) tmp_kappa, tmp_wbc
541 character*160 fmtaa, msg
548 if (idiag_movesect .ge. 70) then
549 call peg_message( lunout, ' ' )
550 call peg_message( lunout, &
551 'move_sect_3d_calc_movingcenter diagnostics' )
552 call peg_message( lunout, ' ' )
556 ! main loop over types
558 do 1900 itype = 1, ntype_aer
561 ! compute mean size after growth (and corresponding section)
562 ! particles in section n will be transferred to section nnewsave(1,n)
564 do 1390 n = 1, nsize_aer(itype)
569 ! don't bother to transfer bins whose mass is extremely small
570 if (drymassxx(n,itype) .le. smallmassaa) goto 1290
572 dumvol = dryvolxx(n,itype)
573 dumnum = rnumbxx(n,itype)
575 ! check for number so small that particle volume is
576 ! above that of largest section
577 isize = nsize_aer(itype)
578 if ( dumnum .le. dumvol/volumhi_stmp(isize,itype) ) then
579 nnew = nsize_aer(itype)
581 ! or below that of smallest section
582 else if ( dumnum .ge. dumvol/volumlo_stmp(1,itype) ) then
587 ! dumvol1p is mean particle volume (cm3) for the section
588 dumvol1p = dumvol/dumnum
589 if ( dumvol1p .gt. volumhi_stmp(n,itype) ) then
590 do while ( ( nnew .lt. nsize_aer(itype) ) .and. &
591 ( dumvol1p .gt. volumhi_stmp(nnew,itype) ) )
595 else if ( dumvol1p .lt. volumlo_stmp(n,itype) ) then
596 do while ( ( nnew .gt. 1 ) .and. &
597 ( dumvol1p .lt. volumlo_stmp(nnew,itype) ) )
604 if ((ntype_aer <= 1) .or. (msectional_flag2 <=0)) then
605 goto 1290 ! here itypenew = itype
610 tmpb = 0.0 ! sum of mass
611 tmpc = 0.0 ! sum of volume*kappa
612 tmpd = 0.0 ! sum of volume
613 do ll = 1, ncomp_aer(itype)
614 tmpe = rmassxx(ll,n,itype)
616 ! if (ll == ibc_a) then ! this only works in mosaic box model, when the ordering
617 ! ! of species in aer(...) and massptr_aer(...) are the same
618 if (massptr_aer(ll,n,itype,iphase) == lptr_bc_aer(n,itype,iphase)) then
620 if (method_kappa == 12) cycle
621 ! in this case, tmpc & tmpd include non-bc species only
623 tmpf = tmpe/dens_aer(ll,itype)
624 tmpc = tmpc + tmpf*hygro_aer(ll,itype)
627 tmp_wbc = tmpa/max(tmpb,1.0e-35_r8)
628 tmp_kappa = tmpc/max(tmpd,1.0e-35_r8)
630 itype1new = ntype_md1_aer
631 do jtype1 = 1, ntype_md1_aer - 1
632 if (tmp_wbc <= xcut_atype_md1(jtype1)) then
638 itype2new = ntype_md2_aer
639 do jtype2 = 1, ntype_md2_aer - 1
640 if (tmp_kappa <= xcut_atype_md2(jtype2)) then
646 itypenew = itype_of_itype_md1md2(itype1new,itype2new)
647 itype1 = itype_md1_of_itype(itype)
648 itype2 = itype_md2_of_itype(itype)
650 if (idiag_movesect .ge. 70) then
651 write(msg,'(a,3i5,1p,2e10.2)') 'isz,ity,itynew,wbc,kap', n, itype, itypenew, tmp_wbc, tmp_kappa
652 call peg_message( lunout, msg )
655 ! what was this for ???
656 ! if ((itype1 == ntype_md1_aer) .and. (itype2 == 1)) then
657 ! if ((n == 11) .or. (n == 17)) then
658 ! write(*,'(a,2(2x,3i3),2f9.4)') 'is,it1/2, ...new, wbc, kap', &
659 ! n, itype1, itype2, &
660 ! nnew, itype1new, itype2new, tmp_wbc, tmp_kappa
666 nnewsave(:,n,itype) = 0
667 nnewsave(1,n,itype) = nnew
668 itypenewsave(:,n,itype) = 0
669 itypenewsave(1,n,itype) = itypenew
670 if (method_movesect == 51) itypenewsave(1,n,itype) = itype
672 xferfracvol(:,:,n,itype) = 0.0
673 xferfracvol(1,1,n,itype) = 1.0
674 xferfracnum(:,:,n,itype) = 0.0
675 xferfracnum(1,1,n,itype) = 1.0
681 if (idiag_movesect .ge. 70) then
683 do n = 1, nsize_aer(itype)
684 if (nnewsave(1,n,itype) .ne. n) ndum = ndum + 1
685 if (itypenewsave(1,n,itype) .ne. itype) ndumb = ndumb + 1
687 if (ndum .gt. 0 .and. ndumb .gt. 0) then
688 txt11 = 'movesectYS3'
689 else if (ndum .gt. 0) then
690 txt11 = 'movesectYS1'
691 else if (ndumb .gt. 0) then
692 txt11 = 'movesectYS2'
694 txt11 = 'movesectNO '
696 do itmpa = 1, nsize_aer(itype), 24
697 itmpb = min( itmpa+23, nsize_aer(itype) )
699 fmtaa = '( a, 4i3, i5, i6, 3x, 24i3 )'
700 write(msg,fmtaa) txt11, iclm, jclm, k, m, itype, &
701 ndum, (nnewsave(1,n,itype), n=itmpa,itmpb)
703 fmtaa = '( 37x, 24i3 )'
704 write(msg,fmtaa) (nnewsave(1,n,itype), n=itmpa,itmpb)
706 call peg_message( lunout, msg )
710 do itmpa = 1, nsize_aer(itype), 24
711 itmpb = min( itmpa+23, nsize_aer(itype) )
713 fmtaa = '( 26x, a, 24i3 )'
714 write(msg,fmtaa) txt11, (itypenewsave(1,n,itype), n=itmpa,itmpb)
716 fmtaa = '( 37x, 24i3 )'
717 write(msg,fmtaa) (itypenewsave(1,n,itype), n=itmpa,itmpb)
719 call peg_message( lunout, msg )
728 end subroutine move_sect_3d_calc_movingcenter
731 !-----------------------------------------------------------------------
732 subroutine move_sect_3d_calc_masnumadvect( &
733 iphase_flag, iclm, jclm, k, m, iphase, &
734 method_movesect, idiag_movesect, llhysw, llwater, &
735 nnewsave, itypenewsave, &
736 densdefault, densh2o, smallmassaa, smallmassbb, &
737 drydenspp, drymasspp, rnumbpp, &
738 drydensxx0, drymassxx0, rnumbxx0, &
739 drydensxx, drymassxx, dryvolxx, rmassxx, rnumbxx, &
740 wetmassxx, wetvolxx, &
741 xferfracvol, xferfracnum, &
742 volumcen_stmp, volumlo_stmp, volumhi_stmp )
744 ! routine calculates section movements for the mass-number-advection approach
746 ! material in section n will be transfered to sections
747 ! nnewsave(1,n) and nnewsave(2,n)
748 ! the fractions of mass/volume transfered to each are
749 ! xferfracvol(1,n) and xferfracvol(2,n)
750 ! the fractions of number transfered to each are
751 ! xferfracnum(1,n) and xferfracnum(2,n)
753 ! the nnewsave, xferfracvol, and xferfracnum are calculated here
754 ! the actual transfer is done in another routine
756 use module_data_mosaic_aero, only: &
757 method_bcfrac, method_kappa, msectional_flag2
758 use module_data_mosaic_asecthp, only: &
759 dens_aer, hygro_aer, &
760 itype_md1_of_itype, itype_md2_of_itype, itype_of_itype_md1md2, &
761 lptr_bc_aer, massptr_aer, &
762 maxd_acomp, maxd_asize, maxd_atype, &
763 ncomp_aer, nsize_aer, ntype_aer, ntype_md1_aer, ntype_md2_aer, &
764 xcut_atype_md1, xcut_atype_md2
769 integer iphase_flag, iclm, jclm, iphase, k, &
770 m, method_movesect, idiag_movesect, llhysw, llwater
771 integer nnewsave(2,maxd_asize,maxd_atype)
772 integer itypenewsave(4,maxd_asize,maxd_atype)
774 real(r8) densh2o, smallmassaa, smallmassbb
775 real(r8) densdefault(maxd_atype)
776 real(r8) drydenspp(maxd_asize,maxd_atype), drydensxx0(maxd_asize,maxd_atype), &
777 drydensxx(maxd_asize,maxd_atype)
778 real(r8) drymasspp(maxd_asize,maxd_atype), drymassxx0(maxd_asize,maxd_atype), &
779 drymassxx(maxd_asize,maxd_atype)
780 real(r8) dryvolxx(maxd_asize,maxd_atype)
781 real(r8) rmassxx(maxd_acomp+2,maxd_asize,maxd_atype)
782 real(r8) rnumbpp(maxd_asize,maxd_atype), rnumbxx0(maxd_asize,maxd_atype), &
783 rnumbxx(maxd_asize,maxd_atype)
784 real(r8) xferfracvol(2,4,maxd_asize,maxd_atype), xferfracnum(2,4,maxd_asize,maxd_atype)
785 real(r8) volumcen_stmp(maxd_asize,maxd_atype), &
786 volumlo_stmp(maxd_asize,maxd_atype), volumhi_stmp(maxd_asize,maxd_atype)
787 real(r8) wetvolxx(maxd_asize,maxd_atype)
788 real(r8) wetmassxx(maxd_asize,maxd_atype)
791 integer ierr, itype, itype1, itype2, itypenew, itype1new, itype2new
792 integer iforce_movecenter(maxd_asize,maxd_atype)
793 integer jtype1, jtype2
796 integer n, nnew, nnew2
798 real(r8) dum1, dum2, dum3
799 real(r8) dumaa, dumbb, dumgamma, dumratio
800 real(r8) dumfracnum, dumfracvol
803 real(r8) dumvbar_aft, dumvbar_pre
804 real(r8) dumvcutlo_nnew_pre, dumvcuthi_nnew_pre
805 real(r8) dumvlo_pre, dumvhi_pre, dumvdel_pre
806 real(r8) dumvtot_aft, dumvtot_pre
807 real(r8) dumzlo, dumzhi
808 real(r8) sixoverpi, third, tmpa
809 real(r8) tmpb, tmpc, tmpd, tmpe, tmpf, tmp_kappa, tmp_wbc
818 itypenewsave(:,:,:) = 0
821 ! compute mean size after growth (and corresponding section)
822 ! some of the particles in section n will be transferred to section nnewsave(1,n,itype)
824 ! if the aftgrow mass is extremely small,
825 ! OR if the aftgrow mean size is outside of
826 ! [dlo_sect(1,itype), dhi_sect(nsize_aer(itype),itype)]
827 ! then use the moving-center method_movesect for this bin
828 ! (don't try to compute the pregrow within-bin distribution)
830 do 4900 itype = 1, ntype_aer
832 if (idiag_movesect .ge. 70) then
833 call peg_message( lunout, ' ' )
834 write( msg, '(a,i5)' ) &
835 'move_sect_3d_calc_massnumadvect diagnostics - itype ', &
837 call peg_message( lunout, msg )
840 do 3900 n = 1, nsize_aer(itype)
843 iforce_movecenter(n,itype) = 0
846 itypenewsave(1,n,itype) = itype
848 ! the following lines set xferfrac values to be appropriate for
849 ! either no transfer or moving-center transfer
850 ! in these cases, nnewsave(1,n,itype)=n or nnew, and nnewsave(2,n,itype)=0
851 xferfracvol(:,:,n,itype) = 0.0
852 xferfracnum(:,:,n,itype) = 0.0
853 xferfracvol(1,kktypenew,n,itype) = 1.0
854 xferfracnum(1,kktypenew,n,itype) = 1.0
864 dumvcutlo_nnew_pre = volumlo_stmp(nnew,itype)*(dumvbar_pre/dumvbar_aft)
865 dumvcuthi_nnew_pre = volumhi_stmp(nnew,itype)*(dumvbar_pre/dumvbar_aft)
869 ! don't bother to transfer bins whose mass is extremely small
870 if (drymassxx(n,itype) .le. smallmassaa) then
871 iforce_movecenter(n,itype) = 1
875 dumvtot_aft = dryvolxx(n,itype)
876 dumntot = rnumbxx(n,itype)
878 ! check for particle volume above that of largest section
879 ! or below that of smallest section
880 if (dumntot .le. dumvtot_aft/volumhi_stmp(nsize_aer(itype),itype)) then
881 nnew = nsize_aer(itype)
882 iforce_movecenter(n,itype) = 2
884 else if (dumntot .ge. dumvtot_aft/volumlo_stmp(1,itype)) then
886 iforce_movecenter(n,itype) = 3
890 ! dumvbar_aft is mean particle volume (cm3) for the section
891 ! find the section that encloses this volume
892 dumvbar_aft = dumvtot_aft/dumntot
893 if (dumvbar_aft .gt. volumhi_stmp(n,itype)) then
894 do while ( (nnew .lt. nsize_aer(itype)) .and. &
895 (dumvbar_aft .gt. volumhi_stmp(nnew,itype)) )
899 else if (dumvbar_aft .lt. volumlo_stmp(n,itype)) then
900 do while ( (nnew .gt. 1) .and. &
901 (dumvbar_aft .lt. volumlo_stmp(nnew,itype)) )
907 1290 nnewsave(:,n,itype) = 0
908 nnewsave(1,n,itype) = nnew
910 if (iforce_movecenter(n,itype) .gt. 0) goto 3700
913 ! if drydenspp (pregrow) < 0.1 (because bin had state="no_aerosol" before
914 ! growth was computed, so its initial mass was very small)
915 ! then use the moving-center method_movesect for this bin
916 ! (don't try to compute the pregrow within-bin distribution)
917 ! also do this if pregrow mass is extremely small (below smallmassaa)
918 ! OR if drydenspp > 20 g/cm^3 (unphysical)
919 if ( (drydenspp(n,itype) .lt. 0.1) .or. &
920 (drydenspp(n,itype) .gt. 20.0) .or. &
921 (drymasspp(n,itype) .le. smallmassaa) ) then
922 iforce_movecenter(n,itype) = 11
926 dumvtot_pre = drymasspp(n,itype)/drydenspp(n,itype)
928 dumvlo_pre = volumlo_stmp(n,itype)
929 dumvhi_pre = volumhi_stmp(n,itype)
930 dumvdel_pre = dumvhi_pre - dumvlo_pre
932 ! if the pregrow mean size is outside of OR very close to the bin limits,
933 ! then use moving-center approach for this bin
934 dumv = dumvhi_pre - 0.01*dumvdel_pre
935 if (dumntot .le. dumvtot_pre/dumv) then
936 iforce_movecenter(n,itype) = 12
939 dumv = dumvlo_pre + 0.01*dumvdel_pre
940 if (dumntot .ge. dumvtot_pre/dumv) then
941 iforce_movecenter(n,itype) = 13
945 ! calculate the pregrow within-section size distribution
946 dumvbar_pre = dumvtot_pre/dumntot
947 dumgamma = (dumvhi_pre/dumvlo_pre) - 1.0
948 dumratio = dumvbar_pre/dumvlo_pre
950 if (dumratio .le. (1.0001 + dumgamma/3.0)) then
951 dumv = dumvlo_pre + 3.0*(dumvbar_pre-dumvlo_pre)
952 dumvhi_pre = min( dumvhi_pre, dumv )
953 dumvdel_pre = dumvhi_pre - dumvlo_pre
954 dumgamma = (dumvhi_pre/dumvlo_pre) - 1.0
955 dumratio = dumvbar_pre/dumvlo_pre
956 else if (dumratio .ge. (0.9999 + dumgamma*2.0/3.0)) then
957 dumv = dumvhi_pre + 3.0*(dumvbar_pre-dumvhi_pre)
958 dumvlo_pre = max( dumvlo_pre, dumv )
959 dumvdel_pre = dumvhi_pre - dumvlo_pre
960 dumgamma = (dumvhi_pre/dumvlo_pre) - 1.0
961 dumratio = dumvbar_pre/dumvlo_pre
964 dumbb = (dumratio - 1.0 - 0.5*dumgamma)*12.0/dumgamma
965 dumaa = 1.0 - 0.5*dumbb
967 ! calculate pregrow volumes corresponding to the nnew
969 dumvcutlo_nnew_pre = volumlo_stmp(nnew,itype)*(dumvbar_pre/dumvbar_aft)
970 dumvcuthi_nnew_pre = volumhi_stmp(nnew,itype)*(dumvbar_pre/dumvbar_aft)
972 ! if the [dumvlo_pre, dumvhi_pre] falls completely within
973 ! the [dumvcutlo_nnew_pre, dumvcuthi_nnew_pre] interval,
974 ! then all mass and number go to nnew
975 if (nnew .eq. 1) then
976 if (dumvhi_pre .le. dumvcuthi_nnew_pre) then
977 iforce_movecenter(n,itype) = 21
981 else if (nnew .eq. nsize_aer(itype)) then
982 if (dumvlo_pre .ge. dumvcutlo_nnew_pre) then
983 iforce_movecenter(n,itype) = 22
988 if ((dumvlo_pre .ge. dumvcutlo_nnew_pre) .and. &
989 (dumvhi_pre .le. dumvcuthi_nnew_pre)) then
990 iforce_movecenter(n,itype) = 23
991 else if (dumvlo_pre .lt. dumvcutlo_nnew_pre) then
997 if (iforce_movecenter(n,itype) .gt. 0) goto 3700
999 ! calculate the fraction of ntot and vtot that are within
1000 ! the [dumvcutlo_nnew_pre, dumvcuthi_nnew_pre] interval
1001 dumzlo = (dumvcutlo_nnew_pre - dumvlo_pre)/dumvdel_pre
1002 dumzhi = (dumvcuthi_nnew_pre - dumvlo_pre)/dumvdel_pre
1003 dumzlo = max( dumzlo, 0.0_r8 )
1004 dumzhi = min( dumzhi, 1.0_r8 )
1005 dum1 = dumzhi - dumzlo
1006 dum2 = (dumzhi**2 - dumzlo**2)*0.5
1007 dum3 = (dumzhi**3 - dumzlo**3)/3.0
1008 dumfracnum = dumaa*dum1 + dumbb*dum2
1009 dumfracvol = (dumvlo_pre/dumvbar_pre) * (dumaa*dum1 + &
1010 (dumaa*dumgamma + dumbb)*dum2 + (dumbb*dumgamma)*dum3)
1012 if ((dumfracnum .le. 0.0) .or. (dumfracvol .le. 0.0)) then
1013 iforce_movecenter(n,itype) = 31
1014 nnewsave(1,n,itype) = nnew2
1015 else if ((dumfracnum .ge. 1.0) .or. (dumfracvol .ge. 1.0)) then
1016 iforce_movecenter(n,itype) = 32
1018 if (iforce_movecenter(n,itype) .gt. 0) goto 3700
1020 nnewsave(2,n,itype) = nnew2
1022 ! at this point, iforce_movecenter=0, so bin will be transferred
1024 ! currently we do linear-discrete for size and moving-center for type
1025 ! thus for type, everything will go to a single
1026 ! itype = itypenewsave(1,n,itype)
1028 ! so the xferfrac are as follows
1029 ! xferfracxxx(1,ktypenew,n,itype) is amount going to
1030 ! isize = nnewsave(1,n,itype) and itype=itypenewsave(1,n,itype)
1031 ! xferfracxxx(2,ktypenew,n,itype) is amount going to
1032 ! isize = nnewsave(2,n,itype) and itype=itypenewsave(1,n,itype)
1033 xferfracvol(1,kktypenew,n,itype) = dumfracvol
1034 xferfracvol(2,kktypenew,n,itype) = 1.0 - dumfracvol
1035 xferfracnum(1,kktypenew,n,itype) = dumfracnum
1036 xferfracnum(2,kktypenew,n,itype) = 1.0 - dumfracnum
1040 ! determine new type
1041 tmpa = 0.0 ! bc mass
1042 tmpb = 0.0 ! sum of mass
1043 tmpc = 0.0 ! sum of volume*kappa
1044 tmpd = 0.0 ! sum of volume
1045 do ll = 1, ncomp_aer(itype)
1046 tmpe = rmassxx(ll,n,itype)
1048 ! if (ll == ibc_a) then ! this only works in mosaic box model, when the ordering
1049 ! ! of species in aer(...) and massptr_aer(...) are the same
1050 if (massptr_aer(ll,n,itype,iphase) == lptr_bc_aer(n,itype,iphase)) then
1052 if (method_kappa == 12) cycle
1053 ! in this case, tmpc & tmpd include non-bc species only
1055 tmpf = tmpe/dens_aer(ll,itype)
1056 tmpc = tmpc + tmpf*hygro_aer(ll,itype)
1059 tmp_wbc = tmpa/max(tmpb,1.0e-35_r8)
1060 tmp_kappa = tmpc/max(tmpd,1.0e-35_r8)
1062 itype1new = ntype_md1_aer
1063 do jtype1 = 1, ntype_md1_aer - 1
1064 if (tmp_wbc <= xcut_atype_md1(jtype1)) then
1070 itype2new = ntype_md2_aer
1071 do jtype2 = 1, ntype_md2_aer - 1
1072 if (tmp_kappa <= xcut_atype_md2(jtype2)) then
1078 itypenew = itype_of_itype_md1md2(itype1new,itype2new)
1079 itype1 = itype_md1_of_itype(itype)
1080 itype2 = itype_md2_of_itype(itype)
1082 itypenewsave(:,n,itype) = 0
1083 itypenewsave(1,n,itype) = itypenew
1084 if (method_movesect == 61) itypenewsave(1,n,itype) = itype
1088 if (idiag_movesect .lt. 70) goto 3800
1090 if (nnewsave(2,n,itype) .eq. 0) then
1091 if (nnewsave(1,n,itype) .eq. 0) then
1093 else if (nnewsave(1,n,itype) .eq. n) then
1098 else if (nnewsave(1,n,itype) .eq. 0) then
1099 if (nnewsave(2,n,itype) .eq. n) then
1104 else if (nnewsave(2,n,itype) .eq. n) then
1105 if (nnewsave(1,n,itype) .eq. n) then
1110 else if (nnewsave(1,n,itype) .eq. n) then
1117 if (drymasspp(n,itype) .gt. drymassxx(n,itype)) dumch1 = '-'
1120 call peg_message( lunout, msg )
1121 write(msg,97010) dumch1, dumch4, iclm, jclm, k, m, &
1122 n, nnewsave(1,n,itype), nnewsave(2,n,itype), &
1123 iforce_movecenter(n,itype), itypenewsave(1,n,itype)
1124 call peg_message( lunout, msg )
1125 write(msg,97020) 'pre mass, dens ', &
1126 drymasspp(n,itype), drydenspp(n,itype)
1127 call peg_message( lunout, msg )
1128 write(msg,97020) 'aft mass, dens, numb', &
1129 drymassxx(n,itype), drydensxx(n,itype), rnumbxx(n,itype)
1130 call peg_message( lunout, msg )
1131 if ((drydensxx(n,itype) .ne. drydensxx0(n,itype)) .or. &
1132 (drymassxx(n,itype) .ne. drymassxx0(n,itype)) .or. &
1133 (rnumbxx(n,itype) .ne. rnumbxx0(n,itype) )) then
1134 write(msg,97020) 'aft0 mas, dens, numb', &
1135 drymassxx0(n,itype), drydensxx0(n,itype), rnumbxx0(n,itype)
1136 call peg_message( lunout, msg )
1138 write(msg,97020) 'vlop0, vbarp, vhip0', &
1139 volumlo_stmp(n,itype), dumvbar_pre, volumhi_stmp(n,itype)
1140 call peg_message( lunout, msg )
1141 write(msg,97020) 'vlop , vbarp, vhip ', &
1142 dumvlo_pre, dumvbar_pre, dumvhi_pre
1143 call peg_message( lunout, msg )
1144 write(msg,97020) 'vloax, vbarax, vhiax', &
1145 dumvcutlo_nnew_pre, dumvbar_pre, dumvcuthi_nnew_pre
1146 call peg_message( lunout, msg )
1147 write(msg,97020) 'vloa0, vbara, vhia0', &
1148 volumlo_stmp(nnew,itype), dumvbar_aft, volumhi_stmp(nnew,itype)
1149 call peg_message( lunout, msg )
1150 write(msg,97020) 'dumfrvol, num, ratio', &
1151 dumfracvol, dumfracnum, dumratio
1152 call peg_message( lunout, msg )
1153 write(msg,97020) 'frvol,num1; vol,num2', &
1154 xferfracvol(1,kktypenew,n,itype), xferfracnum(1,kktypenew,n,itype), &
1155 xferfracvol(2,kktypenew,n,itype), xferfracnum(2,kktypenew,n,itype)
1156 call peg_message( lunout, msg )
1158 97010 format( 'movesect', 2a, 7x, 4i3, 4x, &
1159 'n,nnews', 3i3, 4x, 'iforce', i3.2, 4x, 'itypenew', i5 )
1160 97020 format( a, 1p, 4e13.4 )
1165 ! check for legal combinations of nnewsave(1,:,n,:) & nnewsave(2,:,n,:)
1168 ! both are non-zero AND iabs(nnew1-nnew2) != 1
1170 if (nnewsave(1,n,itype) .eq. nnewsave(2,n,itype)) then
1172 else if (nnewsave(1,n,itype)*nnewsave(2,n,itype) .ne. 0) then
1173 if (iabs(nnewsave(1,n,itype)-nnewsave(2,n,itype)) .ne. 1) ierr = 1
1175 if (ierr .gt. 0) then
1176 write(msg,97010) 'E', 'RROR', iclm, jclm, k, m, &
1177 n, nnewsave(1,n,itype), nnewsave(2,n,itype), iforce_movecenter(n,itype)
1178 call peg_message( lunout, msg )
1182 ! if method_movesect == 30-31 then force moving center
1183 ! this is just for testing purposes
1184 if ((method_movesect .ge. 30) .and. (method_movesect .le. 39)) then
1185 nnewsave(1,n,itype) = nnew
1186 nnewsave(2,n,itype) = 0
1187 xferfracvol(:,:,n,itype) = 0.0
1188 xferfracnum(:,:,n,itype) = 0.0
1189 xferfracvol(1,kktypenew,n,itype) = 1.0
1190 xferfracnum(1,kktypenew,n,itype) = 1.0
1193 3900 continue ! do isize = ...
1195 4900 continue ! do itype = ...
1198 end subroutine move_sect_3d_calc_masnumadvect
1201 !-----------------------------------------------------------------------
1202 subroutine move_sect_3d_apply_moves( &
1203 iphase_flag, iclm, jclm, k, m, iphase, &
1204 method_movesect, idiag_movesect, llhysw, llwater, &
1205 nnewsave, itypenewsave, &
1206 densdefault, densh2o, smallmassaa, smallmassbb, &
1207 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_apvolu, &
1208 delta_water_conform1, delta_numb_conform1, &
1210 drydenspp, drymasspp, rnumbpp, &
1211 drymassxx, dryvolxx, rmassxx, rnumbxx, wetmassxx, wetvolxx, &
1212 drymassyy, dryvolyy, rmassyy, rnumbyy, wetmassyy, wetvolyy, &
1213 xferfracvol, xferfracnum, &
1214 dcen_stmp, volumcen_stmp, volumlo_stmp, volumhi_stmp, &
1215 adrydens_tmp, awetdens_tmp, adrydpav_tmp, awetdpav_tmp, &
1218 ! routine performs the actual transfer of aerosol number and mass
1221 use module_data_mosaic_asecthp, only: &
1222 maxd_acomp, maxd_asize, maxd_atype, &
1223 nsize_aer, ntype_aer, ncomp_plustracer_aer, ai_phase, &
1224 massptr_aer, numptr_aer, waterptr_aer, hyswptr_aer
1229 integer iphase_flag, iclm, jclm, iphase, k, &
1230 m, method_movesect, idiag_movesect, llhysw, llwater
1231 integer nnewsave(2,maxd_asize,maxd_atype)
1232 integer itypenewsave(4,maxd_asize,maxd_atype)
1234 real(r8) densh2o, smallmassaa, smallmassbb
1235 real(r8) fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, fact_apvolu
1236 real(r8) delta_water_conform1, delta_numb_conform1
1237 real(r8) densdefault(maxd_atype)
1238 real(r8) drydenspp(maxd_asize,maxd_atype)
1239 real(r8) drymasspp(maxd_asize,maxd_atype)
1240 real(r8) drymassxx(maxd_asize,maxd_atype), drymassyy(maxd_asize,maxd_atype)
1241 real(r8) dryvolxx(maxd_asize,maxd_atype), dryvolyy(maxd_asize,maxd_atype)
1242 real(r8) rbox(ntot_used)
1243 real(r8) rmassxx(maxd_acomp+2,maxd_asize,maxd_atype), &
1244 rmassyy(maxd_acomp+2,maxd_asize,maxd_atype)
1245 real(r8) rnumbpp(maxd_asize,maxd_atype)
1246 real(r8) rnumbxx(maxd_asize,maxd_atype), rnumbyy(maxd_asize,maxd_atype)
1247 real(r8) xferfracvol(2,4,maxd_asize,maxd_atype), xferfracnum(2,4,maxd_asize,maxd_atype)
1248 real(r8) dcen_stmp(maxd_asize,maxd_atype), volumcen_stmp(maxd_asize,maxd_atype), &
1249 volumlo_stmp(maxd_asize,maxd_atype), volumhi_stmp(maxd_asize,maxd_atype)
1250 real(r8) wetvolxx(maxd_asize,maxd_atype), wetvolyy(maxd_asize,maxd_atype)
1251 real(r8) wetmassxx(maxd_asize,maxd_atype), wetmassyy(maxd_asize,maxd_atype)
1252 real(r8) adrydens_tmp(maxd_asize,maxd_atype), awetdens_tmp(maxd_asize,maxd_atype)
1253 real(r8) adrydpav_tmp(maxd_asize,maxd_atype), awetdpav_tmp(maxd_asize,maxd_atype)
1254 real(r8) adryqmas_tmp(maxd_asize,maxd_atype)
1257 integer itmpa, itype, itypenew, jj, kk, l, ll, n, ndum, nnew, nold
1258 integer jja, jjb, jjc
1260 real(r8) delta_numb_conform2, &
1261 dumbot, dumnum, dumnum_at_dhi, dumnum_at_dlo, &
1262 dumvol, dumvol1p, dumxfvol, dumxfnum, sixoverpi, third
1263 real(r8) dumpp(maxd_asize), dumxx(maxd_asize), dumyy(maxd_asize), &
1275 ! initialize "yy" arrays that hold values after inter-mode transferring
1276 ! "yy" = "xx" for sections that do not move at all
1277 ! "yy" = 0.0 for sections that do move (partially or completely)
1279 do 1950 itype = 1, ntype_aer
1280 do 1940 n = 1, nsize_aer(itype)
1282 itmpa = sum( itypenewsave(2:4,n,itype) )
1283 if ( (nnewsave(1,n,itype) .eq. n) .and. &
1284 (nnewsave(2,n,itype) .eq. 0) .and. &
1285 (itypenewsave(1,n,itype) .eq. itype) .and. &
1286 (itmpa .eq. 0) ) then
1287 ! if nnew == n AND itypenew == itype,
1288 ! then no material will be transferred out of section n,itype,
1289 ! and section can be intialized to its "old" values
1290 ! so initialize "yy" arrays with "xx" values
1291 drymassyy(n,itype) = drymassxx(n,itype)
1292 dryvolyy(n,itype) = dryvolxx(n,itype)
1293 wetmassyy(n,itype) = wetmassxx(n,itype)
1294 wetvolyy(n,itype) = wetvolxx(n,itype)
1295 rnumbyy(n,itype) = rnumbxx(n,itype)
1296 do ll = 1, ncomp_plustracer_aer(itype) + 2
1297 rmassyy(ll,n,itype) = rmassxx(ll,n,itype)
1301 ! if nnew /= n OR itypenew /= itype,
1302 ! then some material will be transferred out of section n,itype,
1303 ! and section must be initialized to zeroa
1304 ! so initialize "yy" arrays to zero
1305 drymassyy(n,itype) = 0.0
1306 dryvolyy(n,itype) = 0.0
1307 wetmassyy(n,itype) = 0.0
1308 wetvolyy(n,itype) = 0.0
1309 rnumbyy(n,itype) = 0.0
1310 do ll = 1, ncomp_plustracer_aer(itype) + 2
1311 rmassyy(ll,n,itype) = 0.0
1317 1940 continue ! n=isize loop
1318 1950 continue ! itype loop
1321 ! do the transfer of mass and number
1323 do 2950 itype = 1, ntype_aer
1324 do 2900 n = 1, nsize_aer(itype)
1326 ! check for no transfer out of n,itype
1327 itmpa = sum( itypenewsave(2:4,n,itype) )
1328 if ( (nnewsave(1,n,itype) .eq. n) .and. &
1329 (nnewsave(2,n,itype) .eq. 0) .and. &
1330 (itypenewsave(1,n,itype) .eq. itype) .and. &
1331 (itmpa .eq. 0) ) goto 2900
1334 nnew = nnewsave(jj,n,itype)
1335 if (nnew .le. 0) goto 2820
1338 itypenew = itypenewsave(kk,n,itype)
1339 if (itypenew .le. 0) goto 2810
1341 dumxfvol = xferfracvol(jj,kk,n,itype)
1342 dumxfnum = xferfracnum(jj,kk,n,itype)
1343 if ((dumxfvol .le. 0.0) .and. (dumxfnum .le. 0.0)) goto 2810
1345 do ll = 1, ncomp_plustracer_aer(itype) + 2
1346 rmassyy(ll,nnew,itypenew) = rmassyy(ll,nnew,itypenew) + rmassxx(ll,n,itype)*dumxfvol
1348 rnumbyy(nnew,itypenew) = rnumbyy(nnew,itypenew) + rnumbxx(n,itype)*dumxfnum
1350 drymassyy(nnew,itypenew) = drymassyy(nnew,itypenew) + drymassxx(n,itype)*dumxfvol
1351 dryvolyy( nnew,itypenew) = dryvolyy( nnew,itypenew) + dryvolxx( n,itype)*dumxfvol
1352 wetmassyy(nnew,itypenew) = wetmassyy(nnew,itypenew) + wetmassxx(n,itype)*dumxfvol
1353 wetvolyy( nnew,itypenew) = wetvolyy( nnew,itypenew) + wetvolxx( n,itype)*dumxfvol
1358 2900 continue ! n=isize loop
1359 2950 continue ! itype loop
1362 ! transfer among sections is completed
1363 ! - check for conservation of mass/volume/number
1364 ! - conform number again
1365 ! - compute/store densities and mean sizes
1366 ! - if k=1, save values for use by dry deposition routine
1367 ! - copy new mixrats back to rbox array
1369 call move_sect_3d_conserve_check( &
1370 1, iphase_flag, iclm, jclm, k, m, iphase, &
1371 method_movesect, idiag_movesect, llhysw, llwater, &
1372 nnewsave, itypenewsave, &
1373 densdefault, densh2o, smallmassaa, smallmassbb, &
1374 fact_apmassmr, fact_apnumbmr, &
1375 delta_water_conform1, delta_numb_conform1, &
1377 drymassxx, dryvolxx, rmassxx, rnumbxx, wetmassxx, wetvolxx, &
1378 drymassyy, dryvolyy, rmassyy, rnumbyy, wetmassyy, wetvolyy )
1380 delta_numb_conform2 = 0.0
1382 do 3950 itype = 1, ntype_aer
1383 do 3900 n = 1, nsize_aer(itype)
1385 dumvol = dryvolyy(n,itype)
1386 if (min(drymassyy(n,itype),dumvol) .le. smallmassbb) then
1387 dumvol = drymassyy(n,itype)/densdefault(itype)
1388 dumnum = drymassyy(n,itype)/(volumcen_stmp(n,itype)*densdefault(itype))
1389 delta_numb_conform2 = delta_numb_conform2 + dumnum - rnumbyy(n,itype)
1390 rnumbyy(n,itype) = dumnum
1391 adrydens_tmp(n,itype) = densdefault(itype)/fact_apdens
1392 awetdens_tmp(n,itype) = densdefault(itype)/fact_apdens
1393 adrydpav_tmp(n,itype) = dcen_stmp(n,itype)/fact_apdiam
1394 awetdpav_tmp(n,itype) = dcen_stmp(n,itype)/fact_apdiam
1396 dumnum = rnumbyy(n,itype)
1397 dumnum_at_dhi = dumvol/volumhi_stmp(n,itype)
1398 dumnum_at_dlo = dumvol/volumlo_stmp(n,itype)
1399 dumnum = max( dumnum_at_dhi, min( dumnum_at_dlo, dumnum ) )
1400 delta_numb_conform2 = delta_numb_conform2 + dumnum - rnumbyy(n,itype)
1401 rnumbyy(n,itype) = dumnum
1402 adrydens_tmp(n,itype) = drymassyy(n,itype)/dumvol/fact_apdens
1403 dumvol1p = dumvol/dumnum
1404 adrydpav_tmp(n,itype) = ((dumvol1p*sixoverpi)**third) / fact_apdiam
1405 awetdens_tmp(n,itype) = wetmassyy(n,itype)/wetvolyy(n,itype)/fact_apdens
1406 dumvol1p = wetvolyy(n,itype)/dumnum
1407 awetdpav_tmp(n,itype) = min( 100.0_r8*dcen_stmp(n,itype), &
1408 (dumvol1p*sixoverpi)**third ) / fact_apdiam
1410 adryqmas_tmp(n,itype) = drymassyy(n,itype)/fact_apmassmr
1412 do ll = 1, ncomp_plustracer_aer(itype)
1413 l = massptr_aer(ll,n,itype,iphase)
1414 rbox(l) = rmassyy(ll,n,itype)/fact_apmassmr
1417 if (iphase .eq. ai_phase) then
1418 l = waterptr_aer(n,itype)
1419 if (l .gt. 0) rbox(l) = rmassyy(llwater,n,itype)/fact_apmassmr
1420 l = hyswptr_aer(n,itype)
1421 if (l .gt. 0) rbox(l) = rmassyy(llhysw,n,itype)/fact_apmassmr
1423 rbox(numptr_aer(n,itype,iphase)) = rnumbyy(n,itype)/fact_apnumbmr
1425 3900 continue ! n=isize loop
1426 3950 continue ! itype loop
1428 delta_numb_conform1 = delta_numb_conform1 + delta_numb_conform2
1430 call move_sect_3d_conserve_check( &
1431 2, iphase_flag, iclm, jclm, k, m, iphase, &
1432 method_movesect, idiag_movesect, llhysw, llwater, &
1433 nnewsave, itypenewsave, &
1434 densdefault, densh2o, smallmassaa, smallmassbb, &
1435 fact_apmassmr, fact_apnumbmr, &
1436 delta_water_conform1, delta_numb_conform1, &
1438 drymassxx, dryvolxx, rmassxx, rnumbxx, wetmassxx, wetvolxx, &
1439 drymassyy, dryvolyy, rmassyy, rnumbyy, wetmassyy, wetvolyy )
1443 if (idiag_movesect .lt. 70) goto 4900
1445 do 4800 itype = 1, ntype_aer
1448 call peg_message( lunout, msg )
1449 write(msg,97005) itype
1450 call peg_message( lunout, msg )
1453 do n = 1, nsize_aer(itype)
1454 if (nnewsave(1,n,itype)+nnewsave(2,n,itype) .ne. n) ndum = ndum + 1
1458 if (ndum .gt. 0) dumch4 = 'SOME'
1460 call peg_message( lunout, msg )
1461 write(msg,97010) dumch4, iclm, jclm, k, m, ndum
1462 call peg_message( lunout, msg )
1463 do jjb = 1, nsize_aer(itype), 10
1464 jjc = min( jjb+9, nsize_aer(itype) )
1465 write(msg,97011) (nnewsave(1,n,itype), nnewsave(2,n,itype), n=jjb,jjc)
1466 call peg_message( lunout, msg )
1469 ! write(msg,97020) 'rnumbold', (rnumbxx(n,itype), n=1,nsize_aer(itype))
1470 ! call peg_message( lunout, msg )
1471 ! write(msg,97020) 'rnumbnew', (rnumbyy(n,itype), n=1,nsize_aer(itype))
1472 ! call peg_message( lunout, msg )
1474 ! write(msg,97020) 'drvolold', (dryvolxx(n,itype), n=1,nsize_aer(itype))
1475 ! call peg_message( lunout, msg )
1476 ! write(msg,97020) 'drvolnew', (dryvolyy(n,itype), n=1,nsize_aer(itype))
1477 ! call peg_message( lunout, msg )
1479 dumbot = log( volumhi_stmp(1,itype)/volumlo_stmp(1,itype) )
1480 do n = 1, nsize_aer(itype)
1484 if ( (drydenspp(n,itype) .gt. 0.5) .and. &
1485 (drymasspp(n,itype) .gt. smallmassaa) ) then
1486 dumvol = drymasspp(n,itype)/drydenspp(n,itype)
1487 if ((rnumbpp(n,itype) .ge. 1.0e-35) .and. &
1488 (dumvol .ge. 1.0e-35)) then
1489 dumvol1p = dumvol/rnumbpp(n,itype)
1490 dumpp(n) = 1.0 + log(dumvol1p/volumlo_stmp(1,itype))/dumbot
1493 if ((rnumbxx(n,itype) .ge. 1.0e-35) .and. &
1494 (dryvolxx(n,itype) .ge. 1.0e-35)) then
1495 dumvol1p = dryvolxx(n,itype)/rnumbxx(n,itype)
1496 dumxx(n) = 1.0 + log(dumvol1p/volumlo_stmp(1,itype))/dumbot
1498 if ((rnumbyy(n,itype) .ge. 1.0e-35) .and. &
1499 (dryvolyy(n,itype) .ge. 1.0e-35)) then
1500 dumvol1p = dryvolyy(n,itype)/rnumbyy(n,itype)
1501 dumyy(n) = 1.0 + log(dumvol1p/volumlo_stmp(1,itype))/dumbot
1505 ! write(msg,97030) 'lnvolold', (dumxx(n,itype), n=1,nsize_aer(itype))
1506 ! call peg_message( lunout, msg )
1507 ! write(msg,97030) 'lnvolnew', (dumyy(n,itype), n=1,nsize_aer(itype))
1508 ! call peg_message( lunout, msg )
1512 if (jja .eq. 1) then
1514 dumout(:) = rnumbxx(:,itype)
1515 else if (jja .eq. 2) then
1517 dumout(:) = rnumbyy(:,itype)
1518 else if (jja .eq. 3) then
1520 dumout(:) = dryvolxx(:,itype)
1521 else if (jja .eq. 4) then
1523 dumout(:) = dryvolyy(:,itype)
1524 else if (jja .eq. 5) then
1526 dumout(:) = dumxx(:)
1527 else if (jja .eq. 6) then
1529 dumout(:) = dumyy(:)
1530 else if (jja .eq. 7) then
1532 dumout(:) = dumpp(:)
1533 else if (jja .eq. 8) then
1535 dumout(:) = wetvolxx(:,itype)
1536 else if (jja .eq. 9) then
1538 dumout(:) = wetvolyy(:,itype)
1539 else if (jja .eq. 10) then
1541 dumout(:) = wetmassxx(:,itype)
1542 else if (jja .eq. 11) then
1544 dumout(:) = wetmassyy(:,itype)
1545 else if (jja .eq. 12) then
1547 dumout(:) = drymassxx(:,itype)
1548 else if (jja .eq. 13) then
1550 dumout(:) = drymassyy(:,itype)
1552 do jjb = 1, nsize_aer(itype), 10
1553 jjc = min( jjb+9, nsize_aer(itype) )
1554 if ((jja .le. 4) .or. (jja .ge. 8)) then
1555 if (jjc == nsize_aer(itype)) then
1556 write(msg,97020) dumch8, (dumout(n), n=jjb,jjc), &
1557 sum( dumout(1:jjc) )
1559 write(msg,97020) dumch8, (dumout(n), n=jjb,jjc)
1562 write(msg,97030) dumch8, (dumout(n), n=jjb,jjc)
1564 call peg_message( lunout, msg )
1569 97005 format( 'movesectapply - itype =', i6 )
1570 97010 format( 'movesectapply', a, 4i3, i6 )
1571 !97011 format( 5x, 10(3x,2i3) )
1572 !97020 format( a, 1p, 10e9.1 )
1573 !97030 format( a, 10f9.3 )
1574 97011 format( 5x, 10(5x,2i3) )
1575 97020 format( a, 1p, 11e11.3 )
1576 97030 format( a, 10f11.5 )
1578 4800 continue ! itype loop
1582 end subroutine move_sect_3d_apply_moves
1585 !-----------------------------------------------------------------------
1586 subroutine move_sect_3d_conserve_check( ipass, &
1587 iphase_flag, iclm, jclm, k, m, iphase, &
1588 method_movesect, idiag_movesect, llhysw, llwater, &
1589 nnewsave, itypenewsave, &
1590 densdefault, densh2o, smallmassaa, smallmassbb, &
1591 fact_apmassmr, fact_apnumbmr, &
1592 delta_water_conform1, delta_numb_conform1, &
1594 drymassxx, dryvolxx, rmassxx, rnumbxx, wetmassxx, wetvolxx, &
1595 drymassyy, dryvolyy, rmassyy, rnumbyy, wetmassyy, wetvolyy )
1597 ! routine checks for conservation of number, mass, and volume
1598 ! by the move_sect_3d algorithm
1599 ! note - move_sections does separate conserve check for each type
1600 ! - move_sect_3d does a single conserve check for all types,
1601 ! because number & mass are transferred among types
1604 ! initialize all thesum(jj,ll) to zero
1605 ! computes thesum(1,ll) from rmassxx, rnumbxx, ...
1606 ! computes thesum(2,ll) from rmassyy, rnumbyy, ...
1607 ! compares thesum(1,ll) with thesum(2,ll)
1608 ! computes thesum(3,ll) from rbox before section movement
1610 ! computes thesum(4,ll) from rbox after section movement
1611 ! compares thesum(3,ll) with thesum(4,ll)
1613 ! currently only implemented for condensational growth (iphase_flag=1)
1615 use module_data_mosaic_asecthp, only: &
1616 maxd_acomp, maxd_asize, maxd_atype, &
1617 nsize_aer, ntype_aer, ncomp_plustracer_aer, ai_phase, &
1618 massptr_aer, numptr_aer, waterptr_aer, hyswptr_aer, &
1624 integer ipass, iphase_flag, iclm, jclm, iphase, k, &
1625 m, method_movesect, idiag_movesect, llhysw, llwater
1626 integer nnewsave(2,maxd_asize,maxd_atype)
1627 integer itypenewsave(2,maxd_asize,maxd_atype)
1628 real(r8) densh2o, smallmassaa, smallmassbb
1629 real(r8) fact_apmassmr, fact_apnumbmr
1630 real(r8) delta_water_conform1, delta_numb_conform1
1631 real(r8) densdefault(maxd_atype)
1632 real(r8) drymassxx(maxd_asize,maxd_atype), drymassyy(maxd_asize,maxd_atype)
1633 real(r8) dryvolxx(maxd_asize,maxd_atype), dryvolyy(maxd_asize,maxd_atype)
1634 real(r8) rbox(ntot_used)
1635 real(r8) rmassxx(maxd_acomp+2,maxd_asize,maxd_atype), &
1636 rmassyy(maxd_acomp+2,maxd_asize,maxd_atype)
1637 real(r8) rnumbxx(maxd_asize,maxd_atype), rnumbyy(maxd_asize,maxd_atype)
1638 real(r8) wetvolxx(maxd_asize,maxd_atype), wetvolyy(maxd_asize,maxd_atype)
1639 real(r8) wetmassxx(maxd_asize,maxd_atype), wetmassyy(maxd_asize,maxd_atype)
1642 integer ii, itype, itmpa, itmpb, jj, jtype, l, ll, llworst, llworstb, n
1643 integer nerr, nerrmax
1645 data nerr, nerrmax / 0, 999 /
1647 real(r8) dumbot, dumtop, dumtoler, dumerr, dumworst, dumworstb
1648 real(r8) duma, dumb, dumc, dume
1649 real(r8) dumerrsv(maxd_acomp+7)
1650 real(r8) thesum(4,maxd_acomp+7)
1652 character*8 dumname(maxd_acomp+7)
1653 character*160 fmtaa, msg
1656 if (ipass .eq. 2) goto 2000
1659 do ll = 1, ncomp_plustracer_aer(itype)+7
1665 do itype = 1, ntype_aer
1666 do n = 1, nsize_aer(itype)
1667 do ll = 1, ncomp_plustracer_aer(itype)+2
1668 thesum(1,ll) = thesum(1,ll) + rmassxx(ll,n,itype)
1669 thesum(2,ll) = thesum(2,ll) + rmassyy(ll,n,itype)
1671 ll = ncomp_plustracer_aer(itype)+3
1672 thesum(1,ll) = thesum(1,ll) + rnumbxx(n,itype)
1673 thesum(2,ll) = thesum(2,ll) + rnumbyy(n,itype)
1674 ll = ncomp_plustracer_aer(itype)+4
1675 thesum(1,ll) = thesum(1,ll) + drymassxx(n,itype)
1676 thesum(2,ll) = thesum(2,ll) + drymassyy(n,itype)
1677 ll = ncomp_plustracer_aer(itype)+5
1678 thesum(1,ll) = thesum(1,ll) + dryvolxx(n,itype)
1679 thesum(2,ll) = thesum(2,ll) + dryvolyy(n,itype)
1680 ll = ncomp_plustracer_aer(itype)+6
1681 thesum(1,ll) = thesum(1,ll) + wetmassxx(n,itype)
1682 thesum(2,ll) = thesum(2,ll) + wetmassyy(n,itype)
1683 ll = ncomp_plustracer_aer(itype)+7
1684 thesum(1,ll) = thesum(1,ll) + wetvolxx(n,itype)
1685 thesum(2,ll) = thesum(2,ll) + wetvolyy(n,itype)
1691 ! calc sum over bins for each species
1692 ! for water, account for loss in initial conform (delta_water_conform1)
1695 do itype = 1, ntype_aer
1696 do n = 1, nsize_aer(itype)
1697 do ll = 1, ncomp_plustracer_aer(itype)+3
1698 duma = fact_apmassmr
1699 if (ll .le. ncomp_plustracer_aer(itype)) then
1700 l = massptr_aer(ll,n,itype,iphase)
1701 else if (ll .eq. ncomp_plustracer_aer(itype)+1) then
1703 if (iphase .eq. ai_phase) l = hyswptr_aer(n,itype)
1704 else if (ll .eq. ncomp_plustracer_aer(itype)+2) then
1706 if (iphase .eq. ai_phase) l = waterptr_aer(n,itype)
1708 l = numptr_aer(n,itype,iphase)
1709 duma = fact_apnumbmr
1712 thesum(ipass+2,ll) = thesum(ipass+2,ll) + rbox(l)*duma
1718 if (ipass .eq. 2) then
1719 ll = ncomp_plustracer_aer(itype)+2
1720 thesum(3,ll) = thesum(3,ll) + delta_water_conform1
1721 ll = ncomp_plustracer_aer(itype)+3
1722 thesum(3,ll) = thesum(3,ll) + delta_numb_conform1
1726 ! now compare either sum1-sum2 or sum3-sum4
1727 ! on ipass=1, jj=1, so compare sum1 & sum2
1728 ! on ipass=2, jj=3, so compare sum3 & sum4
1731 do ll = 1, ncomp_plustracer_aer(itype)+7
1733 write(dumname(ll),'(i4.4)') ll
1734 ! if (ll .le. ncomp_plustracer_aer(itype)) dumname(ll) = &
1735 ! species(massptr_aer(ll,1,itype,iphase))(1:4)
1736 if (ll .le. ncomp_plustracer_aer(itype)) dumname(ll) = name_aer(ll,1)(1:4)
1737 if (ll .eq. ncomp_plustracer_aer(itype)+1) dumname(ll) = 'hysw'
1738 if (ll .eq. ncomp_plustracer_aer(itype)+2) dumname(ll) = 'watr'
1739 if (ll .eq. ncomp_plustracer_aer(itype)+3) dumname(ll) = 'numb'
1740 if (ll .eq. ncomp_plustracer_aer(itype)+4) dumname(ll) = 'drymass'
1741 if (ll .eq. ncomp_plustracer_aer(itype)+5) dumname(ll) = 'dryvol'
1742 if (ll .eq. ncomp_plustracer_aer(itype)+6) dumname(ll) = 'wetmass'
1743 if (ll .eq. ncomp_plustracer_aer(itype)+7) dumname(ll) = 'wetvol'
1752 do ll = 1, ncomp_plustracer_aer(itype)+7
1753 dumtop = thesum(jj+1,ll) - thesum(jj,ll)
1754 dumbot = max( abs(thesum(jj,ll)), abs(thesum(jj+1,ll)), 1.0e-35_r8 )
1755 dumerr = dumtop/dumbot
1757 ! rce 21-jul-2006 - encountered some cases when delta_*_conform1 is negative
1758 ! and large in magnitude relative to thesum, which causes the mass
1759 ! conservation to be less accurate due to roundoff
1760 ! following section recomputes relative error with delta_*_conform1
1761 ! added onto each of thesum
1762 ! also increased dumtoler slightly
1763 if (ipass .eq. 2) then
1765 if (ll .eq. ncomp_plustracer_aer(itype)+2) then
1766 dumc = delta_water_conform1
1767 else if (ll .eq. ncomp_plustracer_aer(itype)+3) then
1768 dumc = delta_numb_conform1
1770 if (dumc .lt. 0.0) then
1771 duma = thesum(3,ll) - dumc
1772 dumb = thesum(4,ll) - dumc
1773 dumtop = dumb - duma
1774 dumbot = max( abs(duma), abs(dumb), 1.0e-35_r8 )
1775 dume = dumtop/dumbot
1776 if (abs(dume) .lt. abs(dumerr)) dumerr = dume
1779 dumerrsv(ll) = dumerr
1781 if (abs(dumerr) .gt. abs(dumworst)) then
1783 dumworstb = dumworst
1790 if (abs(dumworst) .gt. dumtoler) then
1792 if (nerr .le. nerrmax) then
1794 call peg_message( lunout, msg )
1795 write(msg,97110) iclm, jclm, k, m, ipass, llworst
1796 call peg_message( lunout, msg )
1797 write(msg,'(a)') ' jtype, ii, nnew(ii,1:n,jtype)'
1798 call peg_message( lunout, msg )
1800 do jtype = 1, ntype_aer
1802 do itmpa = 1, nsize_aer(jtype), 24
1803 itmpb = min( itmpa+23, nsize_aer(jtype) )
1804 if (itmpa == 1) then
1805 fmtaa = '(i4,i2,2x,24i4)'
1806 write(msg,fmtaa) jtype, ii, &
1807 (nnewsave(ii,n,jtype), n=itmpa,itmpb)
1810 write(msg,fmtaa) (nnewsave(ii,n,jtype), n=itmpa,itmpb)
1812 call peg_message( lunout, msg )
1818 if (ll .eq. 0) ll = ncomp_plustracer_aer(itype)+2
1819 write(msg,97130) 'name/relerrA/thesum', jj, '/thesum', jj+1, &
1820 dumname(ll), dumworst, thesum(jj,ll), thesum(jj+1,ll)
1821 call peg_message( lunout, msg )
1823 if ( (ll .eq. ncomp_plustracer_aer(itype)+3) .and. &
1824 (abs(dumworstb) .gt. dumtoler) ) then
1825 ll = max( 1, llworstb )
1826 dumtop = thesum(jj+1,ll) - thesum(jj,ll)
1827 dumbot = max( abs(thesum(jj,ll)), abs(thesum(jj+1,ll)), 1.0e-35_r8 )
1828 dumerr = dumtop/dumbot
1829 write(msg,97130) 'name/relerrB/thesum', jj, '/thesum', jj+1, &
1830 dumname(ll), dumerr, thesum(jj,ll), thesum(jj+1,ll)
1831 call peg_message( lunout, msg )
1836 ! following added on 10-mar-2010
1837 do ll = 1, ncomp_plustracer_aer(itype)+7
1838 ! exit ! this deactivates it
1839 if (abs(dumerrsv(ll)) .le. dumtoler) cycle
1841 if (nerr .le. nerrmax) then
1842 write(msg,97130) 'name/relerrC/thesum', jj, '/thesum', jj+1, &
1843 dumname(ll), dumworst, thesum(jj,ll), thesum(jj+1,ll)
1844 call peg_message( lunout, msg )
1848 97110 format( 'movesect conserve ERROR - i/j/k/m/pass/llworst', &
1850 97120 format( 64i3 )
1851 97130 format( a, i1, a, i1, 2x, a, 1p, 3e16.7 )
1855 end subroutine move_sect_3d_conserve_check
1858 !-----------------------------------------------------------------------
1859 subroutine move_sect_3d_checkptrs( iphase_flag, iclm, jclm, k, m )
1861 ! checks for valid number and water pointers
1863 use module_data_mosaic_asecthp, only: &
1864 ai_phase, ntype_aer, nsize_aer, nphase_aer, &
1865 ncomp_aer, ncomp_plustracer_aer, &
1866 numptr_aer, waterptr_aer, mastercompptr_aer
1871 integer iphase_flag, iclm, jclm, k, ll, m
1874 integer l, itype, iphase, n, ndum
1877 do 1900 itype = 1, ntype_aer
1878 do 1800 iphase = 1, nphase_aer
1881 do n = 1, nsize_aer(itype)
1882 l = numptr_aer(n,itype,iphase)
1883 if ((l .lt. 1) .or. (l .gt. ntot_used)) then
1884 msg = '*** subr move_sect_3d error - ' // &
1885 'numptr_amode not defined'
1886 call peg_message( lunerr, msg )
1887 write(msg,9030) 'mode, numptr =', n, l
1888 call peg_message( lunerr, msg )
1889 write(msg,9030) 'iphase, itype =', iphase, itype
1890 call peg_message( lunerr, msg )
1891 call peg_error_fatal( lunerr, msg )
1893 ! checks involving nspec_amode and nspec_amode_nontracer
1894 ! being the same for all sections are no longer needed
1896 if (iphase .eq. ai_phase) l = waterptr_aer(n,itype)
1897 if ((l .ge. 1) .and. (l .le. ntot_used)) ndum = ndum + 1
1899 if ((ndum .ne. 0) .and. (ndum .ne. nsize_aer(itype))) then
1900 msg = '*** subr move_sect_3d error - ' // &
1901 'waterptr_aer must be on/off for all modes'
1902 call peg_message( lunerr, msg )
1903 write(msg,9030) 'iphase, itype =', iphase, itype
1904 call peg_message( lunerr, msg )
1905 call peg_error_fatal( lunerr, msg )
1907 9030 format( a, 6(1x,i6) )
1910 if (nsize_aer(itype) /= nsize_aer(1)) then
1911 write(msg,9030) 'nsize diffs', &
1912 1, itype, nsize_aer(1), nsize_aer(itype)
1913 else if (ncomp_aer(itype) /= ncomp_aer(1)) then
1914 write(msg,9030) 'ncomp diffs', &
1915 1, itype, ncomp_aer(1), ncomp_aer(itype)
1916 else if (ncomp_plustracer_aer(itype) /= ncomp_plustracer_aer(1)) then
1917 write(msg,9030) 'ncomp_plustracer diffs', &
1918 1, itype, ncomp_plustracer_aer(1), ncomp_plustracer_aer(itype)
1920 do ll = 1, ncomp_plustracer_aer(1)
1921 if (mastercompptr_aer(ll,itype) /= mastercompptr_aer(ll,1)) then
1922 write(msg,9030) 'mastercompptrcomp diffs', &
1923 1, itype, ll, mastercompptr_aer(ll,1), mastercompptr_aer(ll,itype)
1926 if (msg /= ' ') then
1927 call peg_message( lunerr, msg )
1928 call peg_error_fatal( lunerr, msg )
1935 end subroutine move_sect_3d_checkptrs
1938 !-----------------------------------------------------------------------
1939 subroutine test_move_sect_3d( iphase_flag_inp, iclm, jclm, k, m, &
1940 it_mosaic, mmovesect_flag1, idiag_movesect )
1942 ! routine runs tests on move_sect_3d, using a matrix of
1943 ! pregrow and aftgrow masses for each section
1945 use module_data_mosaic_asecthp, only: &
1946 maxd_atype, maxd_asize, &
1947 ntype_aer, nsize_aer, ncomp_plustracer_aer, &
1948 ai_phase, cw_phase, &
1949 massptr_aer, numptr_aer, waterptr_aer, &
1950 dens_aer, volumlo_sect
1955 integer, intent(in) :: iphase_flag_inp, iclm, jclm, k, m, it_mosaic, &
1956 mmovesect_flag1, idiag_movesect
1959 integer iphase_flag, ii, iphase, itype, jj, &
1961 integer, save :: ientryno = 0
1963 real(r8) dumnumb, dumvolpre, dumvolaft
1964 real(r8) adrydens_tmp(maxd_asize,maxd_atype), awetdens_tmp(maxd_asize,maxd_atype)
1965 real(r8) adrydpav_tmp(maxd_asize,maxd_atype), awetdpav_tmp(maxd_asize,maxd_atype)
1966 real(r8) adryqmas_tmp(maxd_asize,maxd_atype)
1967 real(r8) fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam
1968 real(r8) tmp_drymass_pregrow(maxd_asize,maxd_atype)
1969 real(r8) tmp_drymass_aftgrow(maxd_asize,maxd_atype)
1970 real(r8) tmp_drydens_pregrow(maxd_asize,maxd_atype)
1971 real(r8) tmp_drydens_aftgrow(maxd_asize,maxd_atype)
1972 real(r8) rbox(ntot_used)
1976 integer maxvolfactpre, maxvolfactaft
1977 parameter (maxvolfactpre=15, maxvolfactaft=23)
1979 real(r8) dumvolfactpre(maxvolfactpre)
1980 data dumvolfactpre / &
1981 2.0, 0.0, 1.0e-20, 0.5, 0.9, &
1982 1.0, 1.01, 1.1, 2.0, 4.0, 7.9, 7.99, 8.0, &
1985 real(r8) dumvolfactaft(maxvolfactaft)
1986 data dumvolfactaft / &
1987 4.0, 0.0, 1.0e-20, 0.01, 0.02, 0.05, 0.1, 0.5, 0.9, &
1988 1.0, 1.01, 1.1, 2.0, 4.0, 7.9, 7.99, 8.0, &
1989 8.1, 16.0, 32., 64., 128., 256. /
1990 ! 7.9, 0.0, 1.0e-20, 0.01, 0.02, 0.05, 0.1, 0.5, 0.9, &
1991 ! 1.0, 1.01, 1.1, 2.0, 4.0, 7.9, 7.99, 8.0, &
1992 ! 8.1, 16.0, 32., 64., 128., 256. /
1996 ! check for valid inputs
1999 if (mmovesect_flag1 .le. 0) return
2000 if (nsize_aer(1) .le. 0) return
2002 ientryno = ientryno + 1
2003 if (ientryno .gt. 1) return
2005 write(*,*) '*** doing move_sect_3d_checkptrs ***'
2006 call move_sect_3d_checkptrs( -1, iclm, jclm, k, m )
2008 if (idiag_movesect .ne. 80) return
2010 write(*,*) '*** executing test_move_sect_3d ***'
2014 ! make test calls to move_sect_3d
2016 do 3900 iphase_flag = 1, 1
2019 if (iabs(iphase_flag) .eq. 2) iphase = cw_phase
2021 do 3800 itype = 1, ntype_aer
2023 do 2900 nn = 1, nsize_aer(itype)
2025 do 2800 ii = 1, maxvolfactpre
2027 do 2700 jj = 1, maxvolfactaft
2029 !----------------------------------------------------------
2030 ! following lines produce a small subset of the ii/jj/nn tests
2032 ! following limits ii/jj to 1 and "matching dumvolfact"
2033 ! if (dumvolfactpre(ii) /= dumvolfactpre(1)) goto 2700
2034 ! if (dumvolfactaft(jj) /= dumvolfactaft(1)) goto 2700
2035 ! following limits dumvolfactpre to 4.0
2036 ! if (abs(dumvolfactpre(ii) - 4.0) > 1.0e-4) goto 2800
2037 ! following limits nn
2038 ! if (nn /= 4) goto 2900
2039 !----------------------------------------------------------
2041 ! zero out rbox and dryxxx_yyygrow arrays
2042 do n = 1, nsize_aer(itype)
2043 do ll = 1, ncomp_plustracer_aer(itype)
2044 rbox(massptr_aer(ll,n,itype,iphase)) = 0.0
2047 if (iphase .eq. ai_phase) l = waterptr_aer(n,itype)
2048 if (l .gt. 0) rbox(l) = 0.0
2049 l = numptr_aer(n,itype,iphase)
2050 if (l .gt. 0) rbox(l) = 0.0
2051 tmp_drymass_pregrow(n,itype) = 0.0
2052 tmp_drymass_aftgrow(n,itype) = 0.0
2053 tmp_drydens_pregrow(n,itype) = -1.0
2054 tmp_drydens_aftgrow(n,itype) = -1.0
2057 ! fill in values for section nn
2059 dumnumb = 1.0e7/mw_air ! 1.0e7 #/mol-air = 3.45e5 #/g-air = 345 #/mg-air
2060 rbox(numptr_aer(n,itype,iphase)) = dumnumb
2062 l = massptr_aer(ll,n,itype,iphase)
2064 dumvolpre = volumlo_sect(n,itype)*dumvolfactpre(ii)*dumnumb
2065 tmp_drydens_pregrow(n,itype) = dens_aer(ll,itype)
2066 tmp_drymass_pregrow(n,itype) = dumvolpre*tmp_drydens_pregrow(n,itype)
2067 if (ii .eq. 1) tmp_drydens_pregrow(n,itype) = -1.0
2069 dumvolaft = volumlo_sect(n,itype)*dumvolfactaft(jj)*dumnumb
2070 tmp_drydens_aftgrow(n,itype) = dens_aer(ll,itype)
2071 tmp_drymass_aftgrow(n,itype) = dumvolaft*tmp_drydens_aftgrow(n,itype)
2072 if (jj .eq. 1) tmp_drydens_aftgrow(n,itype) = -1.0
2074 rbox(l) = tmp_drymass_aftgrow(n,itype) ! g/g-air
2077 call peg_message( lunout, msg )
2078 write(msg,98010) nn, ii, jj
2079 call peg_message( lunout, msg )
2080 write(msg,98011) dumvolfactpre(ii), dumvolfactaft(jj)
2081 call peg_message( lunout, msg )
2083 fact_apmassmr = 1.0 ! units are g-AP/g-air already
2084 fact_apnumbmr = 1.0 ! units are #/g-air already
2085 fact_apdens = 1.0 ! units are g/cm3 already
2086 fact_apdiam = 1.0 ! units are cm already
2088 ! make test call to move_sect_3d
2089 call move_sect_3d_x1( iphase_flag, iclm, jclm, k, m, rbox, &
2090 fact_apmassmr, fact_apnumbmr, fact_apdens, fact_apdiam, &
2091 tmp_drydens_aftgrow, tmp_drydens_pregrow, &
2092 tmp_drymass_aftgrow, tmp_drymass_pregrow, &
2093 adrydens_tmp, awetdens_tmp, adrydpav_tmp, awetdpav_tmp, &
2094 adryqmas_tmp, it_mosaic, mmovesect_flag1, idiag_movesect )
2097 call peg_message( lunout, msg )
2098 write(msg,98010) nn, ii, jj
2099 call peg_message( lunout, msg )
2100 write(msg,98011) dumvolfactpre(ii), dumvolfactaft(jj)
2101 call peg_message( lunout, msg )
2110 98010 format( 'test_move_sect_3d output - nn, ii, jj =', 3i3 )
2111 98011 format( 'volfactpre, volfactaft =', 1p, 2e12.4 )
2114 write(*,*) '*** leaving test_move_sect_3d at end ***'
2116 end subroutine test_move_sect_3d
2119 !-----------------------------------------------------------------------
2122 end module module_mosaic_movesect3d