1 PROGRAM create_p3_lookuptable_1
3 !______________________________________________________________________________________
5 ! This program creates the lookup tables (that are combined into the single file
6 ! 'p3_lookupTable_1.dat') for the microphysical processes, used by the P3 microphysics scheme.
7 ! Note, 'p3_lookupTable_2.dat', used in ice-ice interactions for the multi-ice-category
8 ! configuration, are created by a separate program, 'create_lookupTable_2.f90').
10 ! This code is used to generate lookupTable_1 for either 2momI or 3momI, depending on
11 ! the specified value of the parameter 'log_3momI'.
13 ! All other parameter settings are linked uniquely to the version number.
15 !--------------------------------------------------------------------------------------
17 ! Last modified: 2022 June
18 !______________________________________________________________________________________
20 !______________________________________________________________________________________
22 ! To generate 'p3_lookupTable_1.dat' using this code, do the following steps :
24 ! 1. Break up this code into two parts (-top.f90 and -bottom.90). Search for the string
25 ! 'RUNNING IN PARALLEL MODE' and follow instructions.
26 ! For 2momI, need to comment do/enddo for 'i_rhor_loop' for parallelization (search for
27 ! 'i_rhor_loop' label); for 3momI, the 'i_rhor_loop' needs to be uncomment.
28 ! (In the future, a script will be written to automate this.)
30 ! 2. Copy the 3 pieces of text below to create indivudual executable shell scripts.
32 ! 3. Run script 1 (./go_1-compile.ksh). This script will recreate several
33 ! versions of the full code, concatenating the -top.f90 and the -bottom.90 with
34 ! the following code (e.g.) in between (looping through values of i_rhor (for 2momI) or
35 ! i_Znorm (for 3momI):
37 ! i_rhor = 1 ! 2-moment-ice
38 ! i_Znorm = 1 ! 3-moment-ice
40 ! Each version of full_code.f90 is then compiled, with a unique executable name.
41 ! Note, this is done is place the outer i1 loop in order to parallelized .
43 ! 4. Run script 2 (./go_2-submit.csh) This create temporary work directories,
44 ! moves each executable to each work directory, and runs the executables
45 ! simultaneously. (Note, it is assumed that the machine on which this is done
46 ! has multiple processors, though it is not necessary.)
48 ! 5. Run script 3 (./go_3-concatenate.ksh). This concatenates the individual
49 ! partial tables (the output in each working directory) into a single, final
50 ! file 'p3_lookupTable_1.dat' Once it is confirmed that the table is correct,
51 ! the work directories and their contents can be removed.
53 ! Note: For testing or to run in serial, ompile with double-precision
54 ! (e.g. ifort -r8 create_p3_lookupTable_1.f90)
55 ! gfortran -fdefault-real-8 create_p3_lookupTable_1.f90)
56 !______________________________________________________________________________________
58 !--------------------------------------------------------------------------------------------
59 ! Parallel script 1 (of 3): [copy text below (uncommented) to file 'go_1-compile.ksh']
60 ! - creates individual parallel codes, compiles each
62 !-----------------------------
67 ! for i_rhor in 01 02 03 04 05
70 ! rm cfg_input full_code.f90
71 ! cat > cfg_input << EOF
74 ! cat create_p3_lookupTable_1-top.f90 cfg_input create_p3_lookupTable_1-bottom.f90 > full_code.f90
75 ! echo 'Compiling 'exec_${i_rhor}
76 ! ifort -r8 full_code.f90
77 ! mv a.out exec_${i_rhor}
81 ! rm cfg_input full_code.f90
83 !-----------------------------
88 ! for i_Znorm in 01 02 03 04 05 06 07 08 09 10 11
91 ! rm cfg_input full_code.f90
92 ! cat > cfg_input << EOF
93 ! i_Znorm = ${i_Znorm}
95 ! cat create_p3_lookupTable_1-top.f90 cfg_input create_p3_lookupTable_1-bottom.f90 > full_code.f90
96 ! echo 'Compiling 'exec_${i_Znorm}
97 ! ifort -r8 full_code.f90
98 ! mv a.out exec_${i_Znorm}
102 ! rm cfg_input full_code.f90
104 !--------------------------------------------------------------------------------------------
105 !# Parallel script 2 (of 3): [copy text below (uncommented) to file 'go_2-submit.ksh']
106 !# - creates individual work directories, launches each executable
110 ! for exec in `ls exec_*`
112 ! echo Submitting: ${exec}
113 ! mkdir ${exec}-workdir
114 ! mv ${exec} ${exec}-workdir
120 !--------------------------------------------------------------------------------------------
121 !# Parallel script 3 (of 3): [copy text below (uncommented) to file 'go_3-concatenate.ksh]
122 !# - concatenates the output of each parallel job into a single output file.
128 ! for i in `ls exec*/*dat`
131 ! cat lt_total $i > lt_total_tmp
132 ! mv lt_total_tmp lt_total
135 ! mv lt_total p3_lookupTable_1.dat
137 ! echo 'Done. Work directories and contents can now be removed.'
138 ! echo 'Be sure to re-name the file with the appropriate extension, with the version number'
139 ! echo 'corresponding to that in the header. (e.g. 'p3_lookupTable_1.dat-v5.3-3momI')'
141 !--------------------------------------------------------------------------------------------
146 character(len=20), parameter :: version = '5.4'
147 logical, parameter :: log_3momI = .true. !switch to create table for 2momI (.false.) or 3momI (.true.)
150 integer :: i_Znorm ! index for normalized (by Q) Z (passed in through script; [1 .. n_Znorm])
151 integer :: i_rhor ! index for rho_rime (passed in through script; [1 .. n_rhor])
152 integer :: i_Fr ! index for rime-mass-fraction loop [1 .. n_Fr]
153 integer :: i_Qnorm ! index for normalized (by N) Q loop [1 .. n_Qnorm]
154 integer :: i_Drscale ! index for scaled mean rain size loop [1 .. n_Drscale]
156 ! NOTE: n_Znorm (number of i_Znorm values) is currently equal to 80. It is not actually used herein and therefore not declared.
157 ! Rather, the outer (i_Znorm) "loop" is treated by individual complilations/execuations with specified values of i_Znorm,
158 ! with resulting sub-tables subsequently concatenated. The same is true for the second (i_rhor) "loop"; however, n_rhor
159 ! is used to decare the ranges of other arrays, hence it is declared/initialized here
161 integer, parameter :: n_Znorm = 10 ! number of indices for i_Znorm loop (1nd "loop") [not used in parallelized version]
162 integer, parameter :: n_rhor = 5 ! number of indices for i_rhor loop (2nd "loop")
163 integer, parameter :: n_Fr = 4 ! number of indices for i_Fr loop (3rd loop)
164 integer, parameter :: n_Qnorm = 50 ! number of indices for i_Qnorm loop (4th loop)
165 integer, parameter :: n_Drscale = 30 ! number of indices for scaled mean rain size (5th [inner] loop)
167 integer, parameter :: num_int_bins = 40000 ! number of bins for numerical integration of ice processes
168 integer, parameter :: num_int_coll_bins = 1500 ! number of bins for numerical integration of ice-ice and ice-rain collection
170 real, parameter :: mu_i_min = 0.
171 real, parameter :: mu_i_max = 20.
173 integer :: i,ii,iii,jj,kk,kkk,dumii,i_iter,n_iter_psdSolve
175 real :: N,q,qdum,dum1,dum2,cs1,ds1,lam,n0,lamf,qerror,del0,c0,c1,c2,dd,ddd,sum1,sum2, &
176 sum3,sum4,xx,a0,b0,a1,b1,dum,bas1,aas1,aas2,bas2,gammq,gamma,d1,d2,delu,lamold, &
177 cap,lamr,dia,amg,dv,n0dum,sum5,sum6,sum7,sum8,dg,cg,bag,aag,dcritg,dcrits, &
178 dcritr,Fr,csr,dsr,duml,dum3,rhodep,cgpold,m1,m2,m3,dt,mu_r,initlamr,lamv, &
179 rdumii,lammin,lammax,pi,g,p,t,rho,mu,mu_i,ds,cs,bas,aas,dcrit,mu_dum,gdum, &
180 Z_value,sum9,mom3,mom6,intgrR1,intgrR2,intgrR3,intgrR4,dum4,cs2,ds2
182 ! function to compute mu for triple moment
183 real :: compute_mu_3moment
185 ! function to return diagnostic value of shape paramter, mu_i
186 real :: diagnostic_mui
188 ! outputs from lookup table (i.e. "f1prxx" read by access_lookup_table in s/r p3_main)
189 real, dimension(n_Qnorm,n_Fr) :: uns,ums,refl,dmm,rhomm,nagg,nrwat,qsave,nsave,vdep, &
190 eff,lsave,a_100,n_100,vdep1,i_qsmall,i_qlarge,nrwats,lambda_i,mu_i_save
192 ! outputs for triple moment
193 ! HM zsmall, zlarge no longer needed
194 ! real, dimension(n_Qnorm,n_Fr) :: uzs,zlarge,zsmall
195 real, dimension(n_Qnorm,n_Fr) :: uzs
197 real, dimension(n_Qnorm,n_Drscale,n_Fr) :: qrrain,nrrain,nsrain,qsrain,ngrain
199 real, dimension(n_Drscale) :: lamrs
200 real, dimension(num_int_bins) :: fall1
201 real, dimension(num_int_coll_bins) :: fall2,fallr,num,numi
202 real, dimension(n_rhor) :: cgp,crp
203 real, dimension(150) :: mu_r_table
205 real, parameter :: Dm_max = 40000.e-6 ! max. mean ice [m] size for lambda limiter
206 !real, parameter :: Dm_max = 2000.e-6 ! max. mean ice [m] size for lambda limiter
207 real, parameter :: Dm_min = 2.e-6 ! min. mean ice [m] size for lambda limiter
209 real, parameter :: thrd = 1./3.
210 real, parameter :: sxth = 1./6.
211 real, parameter :: cutoff = 1.e-90
213 character(len=2014) :: filename
215 !=== end of variable declaration ===
218 ! HM, no longer need iteration loop
219 ! n_iter_psdSolve = 3 ! 3 iterations found to be sufficient (trial-and-error)
226 ! RUNNING IN PARALLEL MODE:
228 !------------------------------------------------------------------------------------
229 ! CODE ABOVE HERE IS FOR THE "TOP" OF THE BROKEN UP CODE (for running in parallel)
231 ! Before running ./go_1-compile.ksh, delete all lines below this point and
232 ! and save as 'create_p3_lookupTable_1-top.f90'
233 !------------------------------------------------------------------------------------
235 ! For testing single values, uncomment the following:
239 !------------------------------------------------------------------------------------
240 ! CODE BELOW HERE IS FOR THE "BOTTOM" OF THE BROKEN UP CODE (for running in parallel)
242 ! Before running ./go_1-compile.ksh, delete all lines below this point and
243 ! and save as 'create_p3_lookupTable_1-bottom.f90'
244 !------------------------------------------------------------------------------------
246 ! set constants and parameters
248 ! assume 600 hPa, 253 K for p and T for fallspeed calcs (for reference air density)
251 p = 60000. ! air pressure (pa)
252 t = 253.15 ! temp (K)
253 rho = p/(287.15*t) ! air density (kg m-3)
254 mu = 1.496E-6*t**1.5/(t+120.)/rho ! viscosity of air
255 dv = 8.794E-5*t**1.81/p ! diffusivity of water vapor in air
256 dt = 10. ! time step for collection (s)
258 ! parameters for surface roughness of ice particle used for fallspeed
259 ! see mitchell and heymsfield 2005
262 c1 = 4./(del0**2*c0**0.5)
265 dd = 2.e-6 ! bin width for numerical integration of ice processes (units of m)
266 ddd = 50.e-6 ! bin width for numerical integration for ice-ice and ice-rain collection (units of m)
268 !--- specified mass-dimension relationship (cgs units) for unrimed crystals:
273 ! mg = cg*D^dg no longer used, since bulk volume is predicted
276 !---- Choice of m-D parameters for large unrimed ice:
278 ! Heymsfield et al. 2006
280 ! cs=0.0040157+6.06e-5*(-20.)
282 ! sector-like branches (P1b)
294 ! radiating assemblages of plates (mitchell et al. 1990)
298 ! aggreagtes of side planes, bullets, etc. (Mitchell 1996)
302 !-- ** note: if using one of the above (.i.e. not brown and francis, which is already in mks units),
303 ! then uncomment line below to convert from cgs units to mks
304 ! cs=cs*100.**ds/1000.
307 ! Brown and Francis (1995)
309 !cs = 0.01855 ! original (pre v2.3), based on assumption of Dmax
310 cs = 0.0121 ! scaled value based on assumtion of Dmean from Hogan et al. 2012, JAMC
314 ! specify m-D parameter for fully rimed ice
315 ! note: cg is not constant, due to variable density
319 !--- projected area-diam relationship (mks units) for unrimed crystals:
320 ! note: projected area = aas*D^bas
322 ! sector-like branches (P1b)
324 ! aas = 0.55*100.**bas/(100.**2)
328 ! aas = 0.0869*100.**bas/(100.**2)
330 ! aggreagtes of side planes, bullets, etc.
332 aas = 0.2285*100.**bas/(100.**2)
336 !--- projected area-diam relationship (mks units) for fully rimed ice:
337 ! note: projected area = aag*D^bag
339 ! assumed non-spherical
341 ! aag = 0.625*100.**bag/(100.**2)
348 dcrit = (pi/(6.*cs)*900.)**(1./(ds-3.))
350 ! check to make sure projected area at dcrit not greater than than of solid sphere
351 ! stop and give warning message if that is the case
353 if (pi/4.*dcrit**2.lt.aas*dcrit**bas) then
354 print*,'STOP, area > area of solid ice sphere, unrimed'
358 !.........................................................
359 ! generate lookup table for mu (for rain)
361 ! space of a scaled q/N -- initlamr
363 !Compute mu_r using diagnostic relation:
364 ! ! do i = 1,150 ! loop over lookup table values
365 ! ! initlamr = (real(i)*2.)*1.e-6 + 250.e-6
366 ! ! initlamr = 1./initlamr
367 ! ! ! iterate to get mu_r
368 ! ! ! mu_r-lambda relationship is from Cao et al. (2008), eq. (7)
369 ! ! mu_r = 0. ! first guess
371 ! ! lamr = initlamr*(gamma(mu_r+4.)/(6.*gamma(mu_r+1.)))**thrd
372 ! ! ! new estimate for mu_r based on lambda:
373 ! ! ! set max lambda in formula for mu to 20 mm-1, so Cao et al.
374 ! ! ! formula is not extrapolated beyond Cao et al. data range
375 ! ! dum = min(20.,lamr*1.e-3)
376 ! ! mu_r = max(0.,-0.0201*dum**2+0.902*dum-1.718)
377 ! ! ! if lambda is converged within 0.1%, then exit loop
378 ! ! if (ii.ge.2) then
379 ! ! if (abs((lamold-lamr)/lamr).lt.0.001) goto 111
384 ! ! mu_r_table(i) = mu_r
387 !Precribe a constant mu_r:
390 !.........................................................
393 ! compute Z value from input Z index whose value is "passed in" through the script
394 ! Z_value = 2.1**(i_Znorm)*1.e-23 ! range from 2x10^(-23) to 600 using 80 values
396 ! alpha parameter of m-D for rimed ice
398 crp(2) = 250.*pi*sxth
399 crp(3) = 450.*pi*sxth
400 crp(4) = 650.*pi*sxth
401 crp(5) = 900.*pi*sxth
403 !------------------------------------------------------------------------
405 ! open file to write to lookup table:
407 ! write (filename, "(A12,I0.2,A1,I0.2,A4)") "lookupTable_1-",i_Znorm,"_",i_rhor,".dat" !if parallelized over both i_Znorm and i_rhor
408 write (filename, "(A12,I0.2,A4)") "lookupTable_1-LT1.dat"
409 filename = trim(filename)
410 open(unit=1, file=filename, status='unknown')
412 write (filename, "(A12,I0.2,A4)") "lookupTable_1-",i_rhor,".dat"
413 filename = trim(filename)
414 open(unit=1, file=filename, status='unknown')
418 ! The values of i_Znorm (and possibly i_rhor) are "passed in" for parallelized version of code for 3-moment.
419 ! The values of i_rhor are "passed in" for parallelized version of code for 2-moment.
420 ! Thus, the loops 'i_Znorm_loop' and 'i_rhor_loop' are commented out accordingingly.
423 Z_value =2.*(i_Znorm-1) !mu_i values set to 0., 2., 4., ... 20.
425 Z_value = -99. !this gets overwritten below
428 !i_Znorm_loop: do i_Znorm = 1,n_Znorm !normally commented (kept to illustrate the structure (and to run in serial)
429 ! i_rhor_loop: do i_rhor = 1,n_rhor !COMMENT OUT FOR PARALLELIZATION (2-MOMENT ONLY)
430 i_Fr_loop_1: do i_Fr = 1,n_Fr !COMMENT OUT FOR PARALLELIZATION (2-MOMENT ONLY)
432 ! write header to first file:
433 if (log_3momI .and. i_Znorm==1 .and. i_rhor==1 .and. i_Fr==1) then
434 write(1,*) 'LOOKUP_TABLE_1-version: ',trim(version),'-3momI'
436 ! elseif (i_rhor==1) then
437 elseif (.not.log_3momI .and. i_rhor==1 .and. i_Fr==1) then
438 write(1,*) 'LOOKUP_TABLE_1-version: ',trim(version),'-2momI'
442 !-- these lines to be replaced by Fr(i_Fr) initialization outside of loops
443 ! OR: replace with: Fr = 1./float(n_Fr-1)
444 if (i_Fr.eq.1) Fr = 0.
445 if (i_Fr.eq.2) Fr = 0.333
446 if (i_Fr.eq.3) Fr = 0.667
447 if (i_Fr.eq.4) Fr = 1.
450 ! calculate mass-dimension relationship for partially-rimed crystals
452 ! formula from P3 Part 1 (JAS)
454 ! dcritr is critical size separating fully-rimed from partially-rime ice
456 cgp(i_rhor) = crp(i_rhor) ! first guess
458 if (i_Fr.eq.1) then ! case of no riming (Fr = 0), then we need to set dcrits and dcritr to arbitrary large values
465 elseif (i_Fr.eq.2.or.i_Fr.eq.3) then ! case of partial riming (Fr between 0 and 1)
468 dcrits = (cs/cgp(i_rhor))**(1./(dg-ds))
469 dcritr = ((1.+Fr/(1.-Fr))*cs/cgp(i_rhor))**(1./(dg-ds))
470 csr = cs*(1.+Fr/(1.-Fr))
472 ! get mean density of vapor deposition/aggregation grown ice
473 rhodep = 1./(dcritr-dcrits)*6.*cs/(pi*(ds-2.))*(dcritr**(ds-2.)-dcrits**(ds-2.))
474 ! get density of fully-rimed ice as rime mass fraction weighted rime density plus
475 ! density of vapor deposition/aggregation grown ice
477 cgp(i_rhor) = crp(i_rhor)*Fr+rhodep*(1.-Fr)*pi*sxth
478 if (abs((cgp(i_rhor)-cgpold)/cgp(i_rhor)).lt.0.01) goto 115
482 else ! case of complete riming (Fr=1.0)
484 ! set threshold size between partially-rimed and fully-rimed ice as arbitrary large
485 dcrits = (cs/cgp(i_rhor))**(1./(dg-ds))
486 dcritr = 1.e+6 ! here is the "arbitrary large"
492 !---------------------------------------------------------------------------------------
493 ! set up particle fallspeed arrays
494 ! fallspeed is a function of mass dimension and projected area dimension relationships
495 ! following mitchell and heymsfield (2005), jas
497 ! set up array of particle fallspeed to make computationally efficient
499 ! for high-resolution (in diameter space), ice fallspeed is stored in 'fall1' array (m/s)
500 ! for lower-resolution (in diameter space), ice fallspeed is stored in 'fall2' array (m/s)
501 ! rain fallspeed is stored in 'fallr' (m/s)
503 ! loop over particle size
505 jj_loop_1: do jj = 1,num_int_bins
508 d1 = real(jj)*dd - 0.5*dd
510 !----- get mass-size and projected area-size relationships for given size (d1)
513 if (d1.le.dcrit) then
518 else if (d1.gt.dcrit.and.d1.le.dcrits) then
523 else if (d1.gt.dcrits.and.d1.le.dcritr) then
528 else if (d1.gt.dcritr) then
535 ! for projected area, keep bas1 constant, but modify aas1 according to rimed fraction
541 m3 = cgp(i_rhor)*d1**dg
542 ! linearly interpolate based on particle mass
543 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
544 ! dum3 = (1.-Fr)*dum1+Fr*dum2 !DELETE?
545 aas1 = dum3/(d1**bas)
550 ! correction for turbulence
551 ! if (d1.lt.500.e-6) then
558 ! neglect turbulent correction for aggregates for now (no condition)
562 ! fall speed for particle
564 xx = 2.*cs1*g*rho*d1**(ds1+2.-bas1)/(aas1*(mu*rho)**2)
566 b1 = c1*xx**0.5/(2.*((1.+c1*xx**0.5)**0.5-1.)*(1.+c1*xx**0.5)**0.5)-a0*b0*xx** &
567 b0/(c2*((1.+c1*xx**0.5)**0.5-1.)**2)
568 a1 = (c2*((1.+c1*xx**0.5)**0.5-1.)**2-a0*xx**b0)/xx**b1
569 ! velocity in terms of drag terms
570 fall1(jj) = a1*mu**(1.-2.*b1)*(2.*cs1*g/(rho*aas1))**b1*d1**(b1*(ds1-bas1+2.)-1.)
574 !................................................................
575 ! fallspeed array for ice-ice and ice-rain collision calculations
577 jj_loop_2: do jj = 1,num_int_coll_bins
580 d1 = real(jj)*ddd - 0.5*ddd
582 if (d1.le.dcrit) then
587 else if (d1.gt.dcrit.and.d1.le.dcrits) then
592 else if (d1.gt.dcrits.and.d1.le.dcritr) then
597 else if (d1.gt.dcritr) then
604 ! for area, keep bas1 constant, but modify aas1 according to rimed fraction
608 ! dum3 = (1.-Fr)*dum1+Fr*dum2
611 m3 = cgp(i_rhor)*d1**dg
612 ! linearly interpolate based on particle mass:
613 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
614 aas1 = dum3/(d1**bas)
618 ! correction for turbulence
619 ! if (d1.lt.500.e-6) then
626 ! neglect turbulent correction for aggregates for now (no condition)
632 xx = 2.*cs1*g*rho*d1**(ds1+2.-bas1)/(aas1*(mu*rho)**2)
634 b1 = c1*xx**0.5/(2.*((1.+c1*xx**0.5)**0.5-1.)*(1.+c1*xx**0.5)**0.5)-a0*b0*xx** &
635 b0/(c2*((1.+c1*xx**0.5)**0.5-1.)**2)
636 a1 = (c2*((1.+c1*xx**0.5)**0.5-1.)**2-a0*xx**b0)/xx**b1
637 ! velocity in terms of drag terms
638 fall2(jj) = a1*mu**(1.-2.*b1)*(2.*cs1*g/(rho*aas1))**b1*d1**(b1*(ds1-bas1+2.)-1.)
640 !------------------------------------
641 ! fall speed for rain particle
643 dia = d1 ! diameter m
644 amg = pi*sxth*997.*dia**3 ! mass [kg]
645 amg = amg*1000. ! convert kg to g
647 if (dia.le.134.43e-6) then
648 dum2 = 4.5795e5*amg**(2.*thrd)
652 if(dia.lt.1511.64e-6) then
653 dum2 = 4.962e3*amg**thrd
657 if(dia.lt.3477.84e-6) then
658 dum2 = 1.732e3*amg**sxth
666 fallr(jj) = dum2*1.e-2 ! convert (cm s-1) to (m s-1)
670 !---------------------------------------------------------------------------------
672 ! loop around normalized Q (Qnorm)
673 i_Qnorm_loop: do i_Qnorm = 1,n_Qnorm
675 ! lookup table values of normalized Qnorm
676 ! (range of mean mass diameter from ~ 1 micron to x cm)
678 !q = 261.7**((i_Qnorm+10)*0.1)*1.e-18 ! old (strict) lambda limiter
679 q = 800.**((i_Qnorm+10)*0.1)*1.e-18 ! new lambda limiter
681 !--uncomment to test and print proposed values of qovn
682 ! print*,i_Qnorm,(6./(pi*500.)*q)**0.3333
691 ! initialize qerror to arbitrarily large value:
694 !.....................................................................................
695 ! Find parameters for gamma distribution
697 ! size distribution for ice is assumed to be
698 ! N(D) = n0 * D^mu_i * exp(-lam*D)
700 ! for the given q and N, we need to find n0, mu_i, and lam
702 ! approach for finding lambda:
703 ! cycle through a range of lambda, find closest lambda to produce correct q
705 ! start with lam, range of lam from 100 to 1 x 10^7 is large enough to
706 ! cover full range over mean size from approximately 1 micron to x cm
708 ! HM, no longer needed
709 ! if (log_3momI) then
710 ! ! assign provisional values for mom3 (first guess for mom3)
711 ! ! NOTE: these are normalized: mom3 = M3/M0, mom6 = M6/M3 (M3 = 3rd moment, etc.)
712 ! mom3 = q/cgp(i_rhor) !note: cgp is pi/6*(mean_density), computed above
713 ! ! update normalized mom6 based on the updated ratio of normalized mom3 and normalized Q
714 ! ! (we want mom6 normalized by mom3 not q)
720 iteration_loop1: do i_iter = 1,n_iter_psdSolve
723 ! compute mu_i from normalized mom3 and mom6:
724 ! HM set to loop value of mu (temporarily called Z_value)
725 ! mu_i = compute_mu_3moment(mom3,mom6,mu_i_max)
726 ! mu_i = max(mu_i,mu_i_min) ! make sure mu_i >= 0 (otherwise size dist is infinity at D = 0)
727 ! mu_i = min(mu_i,mu_i_max) ! set upper limit
731 ii_loop_1: do ii = 1,11000 ! this range of ii to calculate lambda chosen by trial and error for the given lambda limiter values
733 ! lam = 1.0013**ii*100. ! old (strict) lambda_i limiter
734 lam = 1.0013**ii*10. ! new lambda_i limiter
736 ! solve for mu_i for 2-moment-ice:
737 if (.not. log_3momI) mu_i = diagnostic_mui(mu_i_min,mu_i_max,lam,q,cgp(i_rhor),Fr,pi)
739 ! for lambda limiter:
740 !dum = Dm_max+Fr*(3000.e-6)
742 lam = max(lam,(mu_i+1.)/dum) ! set min lam corresponding to mean size of x
743 lam = min(lam,(mu_i+1.)/Dm_min) ! set max lam corresponding to mean size of Dm_min (2 micron)
746 n0 = lam**(mu_i+1.)/(gamma(mu_i+1.))
748 ! calculate integral for each of the 4 parts of the size distribution
749 ! check difference with respect to Qnorm
751 ! set up m-D relationship for solid ice with D < Dcrit:
755 call intgrl_section(lam,mu_i, ds1,ds,dg,dsr, dcrit,dcrits,dcritr,intgrR1,intgrR2,intgrR3,intgrR4)
756 ! intgrR1 is integral from 0 to dcrit (solid ice)
757 ! intgrR2 is integral from dcrit to dcrits (unrimed large ice)
758 ! intgrR3 is integral from dcrits to dcritr (fully rimed ice)
759 ! intgrR4 is integral from dcritr to inf (partially rimed)
761 ! sum of the integrals from the 4 regions of the size distribution:
762 qdum = n0*(cs1*intgrR1 + cs*intgrR2 + cgp(i_rhor)*intgrR3 + csr*intgrR4)
764 !--- numerical integration for test to make sure incomplete gamma function is working
769 ! if (dum.lt.dcrit) then
770 ! sum1 = sum1+n0*dum**mu_i*cs1*dum**ds1*exp(-lam*dum)*dd
772 ! sum1 = sum1+n0*dum**mu_i*cs*dum**ds*exp(-lam*dum)*dd
775 ! print*,'sum1=',sum1
784 ! find lam with smallest difference between Qnorm and estimate of Qnorm, assign to lamf
785 if (abs(q-qdum).lt.qerror) then
792 ! check and print relative error in q to make sure it is not too large
793 ! note: large error is possible if size bounds are exceeded!!!!!!!!!!
794 ! print*,'qerror (%)',qerror/q*100.
796 ! find n0 based on final lam value
797 ! set final lamf to 'lam' variable
798 ! this is the value of lam with the smallest qerror
801 ! recalculate mu_i based on final lam (for 2-moment-ice only; not needed for 3-moment-ice)
802 if (.not. log_3momI) mu_i = diagnostic_mui(mu_i_min,mu_i_max,lam,q,cgp(i_rhor),Fr,pi)
804 ! n0 = N*lam**(mu_i+1.)/(gamma(mu_i+1.))
806 ! find n0 from lam and Qnorm:
807 ! (this is done instead of finding n0 from lam and N, since N;
808 ! may need to be adjusted to constrain mean size within reasonable bounds)
810 call intgrl_section(lam,mu_i, ds1,ds,dg,dsr, dcrit,dcrits,dcritr,intgrR1,intgrR2,intgrR3,intgrR4)
811 n0 = q/(cs1*intgrR1 + cs*intgrR2 + cgp(i_rhor)*intgrR3 + csr*intgrR4)
813 ! print*,'lam,N0,mu:',lam,n0,mu_i
815 !--- test final lam, N0 values
820 ! if (dum.lt.dcrit) then
821 ! sum1 = sum1+n0*dum**mu_i*cs1*dum**ds1*exp(-lam*dum)*dd
822 ! elseif (dum.ge.dcrit.and.dum.lt.dcrits) then
823 ! sum1 = sum1+n0*dum**mu_i*cs*dum**ds*exp(-lam*dum)*dd
824 ! elseif (dum.ge.dcrits.and.dum.lt.dcritr) then
825 ! sum1 = sum1+n0*dum**mu_i*cg*dum**dg*exp(-lam*dum)*dd
826 ! elseif (dum.ge.dcritr) then
827 ! sum1 = sum1+n0*dum**mu_i*csr*dum**dsr*exp(-lam*dum)*dd
830 ! print*,'sum1=',sum1
834 ! calculate normalized mom3 directly from PSD parameters (3-moment-ice only)
835 ! HM no longer needed
836 ! if (log_3momI) then
837 ! mom3 = n0*gamma(4.+mu_i)/lam**(4.+mu_i)
838 ! ! update normalized mom6 based on the updated ratio of normalized mom3 and normalized Q
839 ! ! (we want mom6 normalized by mom3 not q)
844 enddo iteration_loop1
846 lambda_i(i_Qnorm,i_Fr) = lam
847 mu_i_save(i_Qnorm,i_Fr) = mu_i
849 !.....................................................................................
850 ! At this point, we have solved for all of the ice size distribution parameters (n0, lam, mu_i)
851 !.....................................................................................
853 !.....................................................................................
854 ! find max/min Q* to constrain mean size (i.e. lambda limiter), this is stored and passed to
855 ! lookup table, so that N (nitot) can be adjusted during the simulation to constrain mean size
856 ! (computed and written as the inverses (i_qsmall,i_qlarge) to avoid run-time division in p3_main)
858 ! limit based on min size, Dm_min (2 micron):
859 duml = (mu_i+1.)/Dm_min
860 call intgrl_section(duml,mu_i, ds1,ds,dg,dsr, dcrit,dcrits,dcritr,intgrR1,intgrR2,intgrR3,intgrR4)
861 n0dum = q/(cs1*intgrR1 + cs*intgrR2 + cgp(i_rhor)*intgrR3 + csr*intgrR4)
863 !find maximum N applying the lambda limiter (lower size limit)
864 dum =n0dum/(duml**(mu_i+1.)/(gamma(mu_i+1.)))
866 !calculate the lower limit of normalized Q to use in P3 main
867 !(this is based on the lower limit of mean size so we call this 'qsmall')
868 !qsmall(i_Qnorm,i_Fr) = q/dum
869 i_qsmall(i_Qnorm,i_Fr) = dum/q
872 ! limit based on max size, Dm_max:
873 duml = (mu_i+1.)/Dm_max
875 call intgrl_section(duml,mu_i, ds1,ds,dg,dsr, dcrit,dcrits,dcritr,intgrR1,intgrR2,intgrR3,intgrR4)
876 n0dum = q/(cs1*intgrR1 + cs*intgrR2 + cgp(i_rhor)*intgrR3 + csr*intgrR4)
878 ! find minium N applying the lambda limiter (lower size limit)
879 dum = n0dum/(duml**(mu_i+1.)/(gamma(mu_i+1.)))
881 ! calculate the upper limit of normalized Q to use in P3 main
882 ! (this is based on the upper limit of mean size so we call this 'qlarge')
883 !qlarge(i_Qnorm,i_Fr) = q/dum
884 i_qlarge(i_Qnorm,i_Fr) = dum/q
886 ! calculate bounds for normalized Z based on min/max allowed mu: (3-moment-ice only)
887 ! HM no longer needed, don't need to calculate or output zlarge and zsmall
888 ! if (log_3momI) then
890 ! gdum = (6.+mu_dum)*(5.+mu_dum)*(4.+mu_dum)/((3.+mu_dum)*(2.+mu_dum)*(1.+mu_dum))
892 ! zlarge(i_Qnorm,i_Fr) = gdum*mom3*dum
894 ! gdum = (6.+mu_dum)*(5.+mu_dum)*(4.+mu_dum)/((3.+mu_dum)*(2.+mu_dum)*(1.+mu_dum))
895 ! zsmall(i_Qnorm,i_Fr) = gdum*mom3*dum
896 ! endif !if (log_3momI)
898 !.....................................................................................
899 ! begin moment and microphysical process calculations for the lookup table
901 !.....................................................................................
902 ! mass- and number-weighted mean fallspeed (m/s)
904 !.....................................................................................
906 ! assume conditions for t and p as assumed above (giving rhos), then in microphysics scheme
907 ! multiply by density correction factor (rhos/rho)^0.54, from Heymsfield et al. 2006
909 ! fallspeed formulation from Mitchell and Heymsfield 2005
911 ! initialize for numerical integration
916 sum5 = 0. ! reflectivity
917 sum6 = 0. ! mass mean size
918 sum7 = 0. ! mass-weighted mean density
919 sum8 = 0. ! 6th moment * velocity [3momI only]
920 sum9 = 0. ! 6th moment [3momI only]
922 ! numerically integrate over size distribution
923 ii_loop_2: do ii = 1,num_int_bins
925 dum = real(ii)*dd - 0.5*dd ! particle size
927 !assign mass-size parameters (depending on size at ii)
928 if (dum.le.dcrit) then
931 else if (dum.gt.dcrit.and.dum.le.dcrits) then
934 elseif (dum.gt.dcrits.and.dum.le.dcritr) then
937 elseif (dum.gt.dcritr) then
942 ! numerator of number-weighted velocity - sum1:
943 sum1 = sum1+fall1(ii)*dum**mu_i*exp(-lam*dum)*dd
945 ! numerator of mass-weighted velocity - sum2:
946 sum2 = sum2+fall1(ii)*cs1*dum**(ds1+mu_i)*exp(-lam*dum)*dd
948 ! total number and mass for weighting above fallspeeds:
949 ! (note: do not need to include n0 and cs since these parameters are in both numerator and denominator
950 !denominator of number-weighted V:
951 sum3 = sum3+dum**mu_i*exp(-lam*dum)*dd
953 !denominator of mass-weighted V:
954 sum4 = sum4+cs1*dum**(ds1+mu_i)*exp(-lam*dum)*dd
956 !reflectivity (integral of mass moment squared):
957 sum5 = sum5+n0*(cs1/917.)**2*(6./pi)**2*dum**(2.*ds1+mu_i)*exp(-lam*dum)*dd
959 !numerator of mass-weighted mean size
960 sum6 = sum6+cs1*dum**(ds1+mu_i+1.)*exp(-lam*dum)*dd
962 !numerator of mass-weighted density:
963 ! particle density is defined as mass divided by volume of sphere with same D
964 sum7 = sum7+(cs1*dum**ds1)**2/(pi*sxth*dum**3)*dum**mu_i*exp(-lam*dum)*dd
966 !numerator in 6th-moment-weight fall speed [3momI only]
967 sum8 = sum8 + fall1(ii)*dum**(mu_i+6.)*exp(-lam*dum)*dd
969 !denominator in 6th-moment-weight fall speed [3momI only]
970 sum9 = sum9 + dum**(mu_i+6.)*exp(-lam*dum)*dd
974 ! save mean fallspeeds for lookup table:
975 uns(i_Qnorm,i_Fr) = sum1/sum3
976 ums(i_Qnorm,i_Fr) = sum2/sum4
977 refl(i_Qnorm,i_Fr) = sum5
978 dmm(i_Qnorm,i_Fr) = sum6/sum4
979 rhomm(i_Qnorm,i_Fr) = sum7/sum4
981 uzs(i_Qnorm,i_Fr) = sum8/sum9
982 ! write(6,'(a12,3e15.5)') 'uzs,ums,uns',uzs(i_Qnorm,i_Fr),ums(i_Qnorm,i_Fr),uns(i_Qnorm,i_Fr)
985 !.....................................................................................
987 !.....................................................................................
991 ! set up binned distribution of ice
992 do jj = num_int_coll_bins,1,-1
993 d1 = real(jj)*ddd - 0.5*ddd
994 num(jj) = n0*d1**mu_i*exp(-lam*d1)*ddd
997 ! loop over exponential size distribution
998 ! ! note: collection of ice within the same bin is neglected
1000 jj_loop_3: do jj = num_int_coll_bins,1,-1
1001 kk_loop_1: do kk = 1,jj-1
1004 d1 = real(jj)*ddd - 0.5*ddd
1005 d2 = real(kk)*ddd - 0.5*ddd
1007 if (d1.le.dcrit) then
1010 elseif (d1.gt.dcrit.and.d1.le.dcrits) then
1013 else if (d1.gt.dcrits.and.d1.le.dcritr) then
1016 else if (d1.gt.dcritr) then
1023 ! for area, keep bas1 constant, but modify aas1 according to rimed fraction
1029 m3 = cgp(i_rhor)*d1**dg
1030 ! linearly interpolate based on particle mass
1031 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
1032 aas1 = dum3/(d1**bas)
1036 ! parameters for particle 2
1037 if (d2.le.dcrit) then
1040 elseif (d2.gt.dcrit.and.d2.le.dcrits) then
1043 elseif (d2.gt.dcrits.and.d2.le.dcritr) then
1046 elseif (d2.gt.dcritr) then
1053 ! for area, keep bas1 constant, but modify aas1 according to rime fraction
1059 m3 = cgp(i_rhor)*d2**dg
1060 ! linearly interpolate based on particle mass
1061 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
1062 aas2 = dum3/(d2**bas)
1066 ! differential fallspeed:
1067 ! (note: in P3_MAIN must multiply by air density correction factor, and collection efficiency
1068 delu = abs(fall2(jj)-fall2(kk))
1072 ! sum1 = # of collision pairs
1073 ! the assumption is that each collision pair reduces crystal
1074 ! number mixing ratio by 1 kg^-1 s^-1 per kg/m^3 of air (this is
1075 ! why we need to multiply by air density, to get units of 1/kg^-1 s^-1)
1077 sum1 = sum1+(aas1*d1**bas1+aas2*d2**bas2)*delu*num(jj)*num(kk)
1079 ! remove collected particles from distribution over time period dt, update num
1080 ! note -- dt is time scale for removal, not model time step
1081 ! num(kk) = num(kk)-(aas1*d1**bas1+aas2*d2**bas2)*delu*num(jj)*num(kk)*dt
1082 ! num(kk) = max(num(kk),0.)
1084 ! write(6,'(2i5,8e15.5)')jj,kk,sum1,num(jj),num(kk),delu,aas1,d1,aas2,d2
1085 ! num(kk)=num(kk)-(aas1*d1**bas1+aas2*d2**bas2)*delu*num(jj)*num(kk)*0.1*0.5
1086 ! num(kk)=max(num(kk),0.)
1087 ! sum1 = sum1+0.5*(aas1*d1**bas1+aas2*d2**bas2)*delu*n0*n0*(d1+d2)**mu_i*exp(-lam*(d1+d2))*dd**2
1092 nagg(i_Qnorm,i_Fr) = sum1 ! save to write to output
1094 ! print*,'nagg',nagg(i_Qnorm,i_Fr)
1096 !.....................................................................................
1097 ! collection of cloud droplets
1098 !.....................................................................................
1099 ! note: In P3_MAIN, needs to be multiplied by collection efficiency Eci
1100 ! Also needs to be multiplied by air density correction factor for fallspeed,
1101 ! ! air density, and cloud water mixing ratio or number concentration
1103 ! initialize sum for integral
1107 ! loop over exponential size distribution (from 1 micron to 2 cm)
1108 jj_loop_4: do jj = 1,num_int_bins
1110 d1 = real(jj)*dd - 0.5*dd ! particle size or dimension (m) for numerical integration
1112 ! get mass-dimension and projected area-dimension relationships
1113 ! for different ice types across the size distribution based on critical dimensions
1114 ! separating these ice types (see Fig. 2, morrison and grabowski 2008)
1117 ! projected area = bas1*D^bas1
1118 if (d1.le.dcrit) then
1123 elseif (d1.gt.dcrit.and.d1.le.dcrits) then
1128 elseif (d1.gt.dcrits.and.d1.le.dcritr) then
1133 elseif (d1.gt.dcritr) then
1140 ! for area, ! keep bas1 constant, but modify aas1 according to rimed fraction
1146 m3 = cgp(i_rhor)*d1**dg
1147 ! linearly interpolate based on particle mass
1148 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
1149 aas1 = dum3/(d1**bas)
1154 ! include assumed ice particle size threshold for riming of 100 micron
1155 ! note: sum1 (nrwat) is the scaled collection rate, units of m^3 kg^-1 s^-1
1156 ! sum2 (nrwats) is mass of snow times scaled collection rate, units of m^3 s^-1
1158 if (d1.ge.100.e-6) then
1159 sum1 = sum1+aas1*d1**bas1*fall1(jj)*n0*d1**mu_i*exp(-lam*d1)*dd
1160 !sum2 = sum2+aas1*d1**bas1*fall1(jj)*n0*d1**mu_i*exp(-lam*d1)*dd*cs1*d1**ds1
1166 nrwat(i_Qnorm,i_Fr) = sum1 ! note: read in as 'f1pr4' in P3_MAIN
1167 !nrwats(i_Qnorm,i_Fr) = sum2
1169 !.....................................................................................
1170 ! collection of rain
1171 !.....................................................................................
1173 ! note: In P3_MAIN, we need to multiply rate by n0r, collection efficiency,
1174 ! air density, and air density correction factor
1176 ! This approach implicitly assumes that the PSDs are constant during the microphysics
1177 ! time step, this could produce errors if the time step is large. In particular,
1178 ! more mass or number could be removed than is available. This will be taken care
1179 ! of by conservation checks in the microphysics code.
1181 ! loop around lambda for rain
1182 i_Drscale_loop: do i_Drscale = 1,n_Drscale
1184 print*,'** STATUS: ',i_Znorm, i_rhor, i_Fr, i_Qnorm, i_Drscale
1186 dum = 1.24**i_Drscale*10.e-6
1188 ! assumed lamv for tests
1190 ! note: lookup table for rain is based on lamv, i.e.,inverse volume mean diameter
1192 lamrs(i_Drscale) = lamv
1194 ! get mu_r from lamr:
1197 if (dum.lt.282.e-6) then
1199 elseif (dum.ge.282.e-6 .and. dum.lt.502.e-6) then
1201 rdumii = (dum-250.e-6)*1.e6*0.5
1202 rdumii = max(rdumii,1.)
1203 rdumii = min(rdumii,150.)
1205 dumii = min(149,dumii)
1206 mu_r = mu_r_table(dumii)+(mu_r_table(dumii+1)-mu_r_table(dumii))*(rdumii-real(dumii))
1207 elseif (dum.ge.502.e-6) then
1210 ! recalculate slope based on mu_r
1211 !LAMR = (pi*sxth*rhow*nr(i_Qnorm,k)*gamma(mu_r+4.)/(qr(i_Qnorm,k)*gamma(mu_r+1.)))**thrd
1213 ! this is done by re-scaling lamv to account for DSD shape (mu_r)
1214 lamr = lamv*(gamma(mu_r+4.)/(6.*gamma(mu_r+1.)))**thrd
1216 ! set maximum value for rain lambda
1217 !lammax = (mu_r+1.)/10.e-6
1218 lammax = (mu_r+1.)*1.e+5
1220 ! set to small value since breakup is explicitly included (mean size 5 mm)
1221 !lammin = (mu_r+1.)/5000.e-6
1222 lammin = (mu_r+1.)*200.
1223 lamr = min(lamr,lammax)
1224 lamr = max(lamr,lammin)
1230 ! sum8 = 0. ! total rain
1232 do jj = 1,num_int_coll_bins
1234 d1 = real(jj)*ddd - 0.5*ddd
1235 ! num is the scaled binned rain size distribution;
1236 ! need to multiply by n0r to get unscaled distribution
1237 num(jj) = d1**mu_r*exp(-lamr*d1)*ddd
1238 ! get (unscaled) binned ice size distribution
1239 numi(jj) = n0*d1**mu_i*exp(-lam*d1)*ddd
1242 ! loop over rain and ice size distributions
1243 jj_loop_5: do jj = 1,num_int_coll_bins
1244 kk_loop_2: do kk = 1,num_int_coll_bins
1247 d1 = real(jj)*ddd - 0.5*ddd ! ice
1248 d2 = real(kk)*ddd - 0.5*ddd ! rain
1249 if (d1.le.dcrit) then
1254 elseif (d1.gt.dcrit.and.d1.le.dcrits) then
1259 elseif (d1.gt.dcrits.and.d1.le.dcritr) then
1264 else if (d1.gt.dcritr) then
1271 ! for area, keep bas1 constant, but modify aas1 according to rime fraction
1277 m3 = cgp(i_rhor)*d1**dg
1278 ! linearly interpolate based on particle mass
1279 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
1280 aas1 = dum3/(d1**bas)
1284 delu = abs(fall2(jj)-fallr(kk)) ! differential fallspeed
1286 !......................................................
1287 ! collection of rain mass and number
1289 ! allow collection of rain both when rain fallspeed > ice fallspeed and ice fallspeed > rain fallspeed
1290 ! this is applied below freezing to calculate total amount of rain mass and number that collides with ice and freezes
1292 ! if (fall2(jj).ge.fallr(kk)) then
1296 ! change in rain N (units of m^4 s^-1 kg^-1), thus need to multiply
1297 ! by air density (units kg m^-3) and n0r (units kg^-1 m^-1) in P3_MAIN
1299 !sum1 = sum1+(aas1*d1**bas1+pi*0.25*d2**2)*delu*n0*d1**mu_i* &
1300 ! exp(-lam*d1)* &dd*num(kk)
1301 sum1 = sum1+(aas1*d1**bas1+pi*0.25*d2**2)*delu*n0*d1**mu_i* &
1302 exp(-lam*d1)*ddd*num(kk)
1303 !sum1 = sum1+min((aas1*d1**bas1+pi*0.25*d2**2)*delu*n0*d1**mu_i* &
1304 ! exp(-lam*d1)*dd*num(kk),num(kk))
1306 ! change in rain q (units of m^4 s^-1), again need to multiply by air density and n0r in P3_MAIN
1308 !sum2 = sum2+(aas1*d1**bas1+pi*0.25*d2**2)*delu*n0*d1**mu_i* &
1309 ! exp(-lam*d1)*dd*num(kk)*pi*sxth*997.*d2**3
1310 sum2 = sum2+(aas1*d1**bas1+pi*0.25*d2**2)*delu*n0*d1**mu_i* &
1311 exp(-lam*d1)*ddd*num(kk)*pi*sxth*997.*d2**3
1313 ! remove collected rain drops from distribution:
1314 !num(kk) = num(kk)-(aas1*d1**bas1+pi*0.25*d2**2)*delu*n0*d1**mu_i* &
1315 ! exp(-lam*d1)*dd*num(kk)*dt
1316 !num(kk) = max(num(kk),0.)
1318 !......................................................
1319 ! now calculate collection of ice mass by rain
1321 ! ice collecting rain
1323 ! again, allow collection both when ice fallspeed > rain fallspeed
1324 ! and when rain fallspeed > ice fallspeed
1325 ! this is applied to conditions above freezing to calculate
1326 ! acceleration of melting due to collisions with liquid (rain)
1328 ! if (fall2(jj).ge.fallr(kk)) then
1330 ! collection of ice number
1332 ! sum5 = sum5+(aas1*d1**bas1+pi/4.*d2**2)*delu*exp(-lamr*d2)*dd*numi(jj)
1334 ! collection of ice mass (units of m^4 s^-1)
1335 ! note: need to multiply by air density and n0r in microphysics code
1336 sum6 = sum6+(aas1*d1**bas1+pi*0.25*d2**2)*delu*d2**mu_r* &
1337 exp(-lamr*d2)*ddd*numi(jj)*cs1*d1**ds1
1339 ! remove collected snow from distribution:
1340 !numi(jj) = numi(jj)-(aas1*d1**bas1+pi*0.25*d2**2)*delu*d2**mu_r* &
1341 ! exp(-lamr*d2)*dd*numi(jj)*dt
1342 !numi(jj) = max(numi(jj),0.)
1348 nrrain(i_Qnorm,i_Drscale,i_Fr) = sum1
1349 qrrain(i_Qnorm,i_Drscale,i_Fr) = sum2
1350 qsrain(i_Qnorm,i_Drscale,i_Fr) = sum6
1352 enddo i_Drscale_loop !(loop around lambda for rain)
1354 !.....................................................................................
1355 ! vapor deposition/melting/wet growth
1356 !.....................................................................................
1358 ! vapor deposition including ventilation effects
1359 ! note: in microphysics code we need to multiply by air density and
1360 ! (mu/dv)^0.3333*(rhofac/mu)^0.5, where rhofac is air density correction factor
1365 ! loop over exponential size distribution:
1366 jj_loop_6: do jj = 1,num_int_bins
1368 d1 = real(jj)*dd - 0.5*dd ! particle size
1370 ! get capacitance for different ice regimes:
1371 if (d1.le.dcrit) then
1372 cap = 1. ! for small spherical crystal use sphere
1373 elseif (d1.gt.dcrit.and.d1.le.dcrits) then
1374 cap = 0.48 ! field et al. 2006
1375 elseif (d1.gt.dcrits.and.d1.le.dcritr) then
1376 cap = 1. ! for graupel assume sphere
1377 elseif (d1.gt.dcritr) then
1387 m3 = cgp(i_rhor)*d1**dg
1388 ! linearly interpolate to get capacitance based on particle mass
1389 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
1394 ! for ventilation, only include fallspeed and size effects, the rest of
1395 ! term Sc^1/3 x Re^1/2 is multiplied in-line in the model code to allow
1396 ! effects of atmospheric conditions on ventilation
1397 !dum = (mu/dv)**0.333333*(fall1(jj)*d1/mu)**0.5
1398 dum = (fall1(jj)*d1)**0.5
1400 ! ventilation from Hall and Pruppacher (1976)
1401 ! only include ventilation for super-100 micron particles
1402 ! if (dum.lt.1.) then
1404 ! units are m^3 kg^-1 s^-1, thus multiplication by air density in P3_MAIN
1406 if (d1.lt.100.e-6) then
1407 sum1 = sum1+cap*n0*d1**(mu_i+1.)*exp(-lam*d1)*dd
1409 !sum1 = sum1+cap*n0*(0.65+0.44*dum)*d1**(mu_i+1.)*exp(-lam*d1)*dd
1410 sum1 = sum1+cap*n0*0.65*d1**(mu_i+1.)*exp(-lam*d1)*dd
1411 sum2 = sum2+cap*n0*0.44*dum*d1**(mu_i+1.)*exp(-lam*d1)*dd
1416 vdep(i_Qnorm,i_Fr) = sum1
1417 vdep1(i_Qnorm,i_Fr) = sum2
1419 !.....................................................................................
1420 ! ice effective radius
1421 ! use definition of Francis et al. (1994), e.g., Eq. 3.11 in Fu (1996) J. Climate
1422 !.....................................................................................
1426 ! loop over exponential size distribution:
1427 jj_loop_7: do jj = 1,num_int_bins
1429 d1 = real(jj)*dd - 0.5*dd ! particle size
1431 if (d1.le.dcrit) then
1436 elseif (d1.gt.dcrit.and.d1.le.dcrits) then
1441 elseif (d1.gt.dcrits.and.d1.le.dcritr) then
1446 elseif (d1.gt.dcritr) then
1453 ! for area, keep bas1 constant, but modify aas1 according to rime fraction
1459 m3 = cgp(i_rhor)*d1**dg
1460 ! linearly interpolate based on particle mass:
1461 dum3 = dum1+(m1-m2)*(dum2-dum1)/(m3-m2)
1462 aas1 = dum3/(d1**bas)
1466 ! n0 not included below becuase it is in both numerator and denominator
1472 sum1 = sum1 + cs1*d1**ds1*d1**mu_i*exp(-lam*d1)*dd
1473 sum2 = sum2 + aas1*d1**bas1*d1**mu_i*exp(-lam*d1)*dd
1475 ! if (d1.ge.100.e-6) then
1476 ! sum3 = sum3+n0*d1**mu_i*exp(-lam*d1)*dd
1477 ! sum4 = sum4+n0*aas1*d1**bas1*d1**mu_i*exp(-lam*d1)*dd
1482 ! calculate eff radius:
1484 !eff(i_Qnorm,i_Fr) = sum1/(1.7321*916.7*sum2)
1485 !calculate effective size following Fu (1996)
1486 !eff(i_Qnorm,i_Fr) = sum1/(1.1547*916.7*sum2)
1487 ! calculate for eff rad for twp ice:
1488 eff(i_Qnorm,i_Fr) = 3.*sum1/(4.*sum2*916.7)
1490 !.....................................................................................
1498 i_Qnorm_loop_2: do i_Qnorm = 1,n_Qnorm
1501 ! Set values less than cutoff (1.e-99) to 0.
1502 ! note: dim(x,cutoff) actually returns x-cutoff (if x>cutoff; else 0.), but this difference will
1503 ! have no effect since the values will be read in single precision in P3_INIT. The purppse
1504 ! here is to avoid problems trying to writevalues with 3-digit exponents (e.g. 0.123456E-100)
1505 uns(i_Qnorm,i_Fr) = dim( uns(i_Qnorm,i_Fr), cutoff)
1506 ums(i_Qnorm,i_Fr) = dim( ums(i_Qnorm,i_Fr), cutoff)
1507 nagg(i_Qnorm,i_Fr) = dim( nagg(i_Qnorm,i_Fr), cutoff)
1508 nrwat(i_Qnorm,i_Fr) = dim( nrwat(i_Qnorm,i_Fr), cutoff)
1509 vdep(i_Qnorm,i_Fr) = dim( vdep(i_Qnorm,i_Fr), cutoff)
1510 eff(i_Qnorm,i_Fr) = dim( eff(i_Qnorm,i_Fr), cutoff)
1511 i_qsmall(i_Qnorm,i_Fr) = dim( i_qsmall(i_Qnorm,i_Fr), cutoff)
1512 i_qlarge(i_Qnorm,i_Fr) = dim( i_qlarge(i_Qnorm,i_Fr), cutoff)
1513 refl(i_Qnorm,i_Fr) = dim( refl(i_Qnorm,i_Fr), cutoff)
1514 vdep1(i_Qnorm,i_Fr) = dim( vdep1(i_Qnorm,i_Fr), cutoff)
1515 dmm(i_Qnorm,i_Fr) = dim( dmm(i_Qnorm,i_Fr), cutoff)
1516 rhomm(i_Qnorm,i_Fr) = dim( rhomm(i_Qnorm,i_Fr), cutoff)
1517 uzs(i_Qnorm,i_Fr) = dim( uzs(i_Qnorm,i_Fr), cutoff)
1518 ! HM no longer needed
1519 ! zlarge(i_Qnorm,i_Fr) = dim( zlarge(i_Qnorm,i_Fr), cutoff)
1520 ! zsmall(i_Qnorm,i_Fr) = dim( zsmall(i_Qnorm,i_Fr), cutoff)
1521 lambda_i(i_Qnorm,i_Fr) = dim( lambda_i(i_Qnorm,i_Fr), cutoff)
1522 mu_i_save(i_Qnorm,i_Fr) = dim( mu_i_save(i_Qnorm,i_Fr), cutoff)
1525 write(1,'(4i5,20e15.5)') &
1526 i_Znorm,i_rhor,i_Fr,i_Qnorm, &
1527 uns(i_Qnorm,i_Fr), &
1528 ums(i_Qnorm,i_Fr), &
1529 nagg(i_Qnorm,i_Fr), &
1530 nrwat(i_Qnorm,i_Fr), &
1531 vdep(i_Qnorm,i_Fr), &
1532 eff(i_Qnorm,i_Fr), &
1533 i_qsmall(i_Qnorm,i_Fr), &
1534 i_qlarge(i_Qnorm,i_Fr), &
1535 refl(i_Qnorm,i_Fr), &
1536 vdep1(i_Qnorm,i_Fr), &
1537 dmm(i_Qnorm,i_Fr), &
1538 rhomm(i_Qnorm,i_Fr), &
1539 uzs(i_Qnorm,i_Fr), &
1540 ! HM no longer needed
1541 ! zlarge(i_Qnorm,i_Fr), &
1542 ! zsmall(i_Qnorm,i_Fr), &
1543 lambda_i(i_Qnorm,i_Fr), &
1544 mu_i_save(i_Qnorm,i_Fr)
1546 write(1,'(3i5,20e15.5)') &
1547 i_rhor,i_Fr,i_Qnorm, &
1548 uns(i_Qnorm,i_Fr), &
1549 ums(i_Qnorm,i_Fr), &
1550 nagg(i_Qnorm,i_Fr), &
1551 nrwat(i_Qnorm,i_Fr), &
1552 vdep(i_Qnorm,i_Fr), &
1553 eff(i_Qnorm,i_Fr), &
1554 i_qsmall(i_Qnorm,i_Fr), &
1555 i_qlarge(i_Qnorm,i_Fr), &
1556 refl(i_Qnorm,i_Fr), &
1557 vdep1(i_Qnorm,i_Fr), &
1558 dmm(i_Qnorm,i_Fr), &
1559 rhomm(i_Qnorm,i_Fr), &
1560 lambda_i(i_Qnorm,i_Fr), &
1561 mu_i_save(i_Qnorm,i_Fr)
1564 enddo i_Qnorm_loop_2
1566 !-- ice-rain collection table:
1567 do i_Qnorm = 1,n_Qnorm
1568 do i_Drscale = 1,n_Drscale
1570 ! ! !Set values less than cutoff (1.e-99) to 0.
1571 ! ! nrrain(i_Qnorm,i_Drscale,i_Fr) = dim(nrrain(i_Qnorm,i_Drscale,i_Fr), cutoff)
1572 ! ! qrrain(i_Qnorm,i_Drscale,i_Fr) = dim(qrrain(i_Qnorm,i_Drscale,i_Fr), cutoff)
1573 nrrain(i_Qnorm,i_Drscale,i_Fr) = log10(max(nrrain(i_Qnorm,i_Drscale,i_Fr), 1.e-99))
1574 qrrain(i_Qnorm,i_Drscale,i_Fr) = log10(max(qrrain(i_Qnorm,i_Drscale,i_Fr), 1.e-99))
1576 write(1,'(3i5,2e15.5)') &
1577 i_Qnorm,i_Drscale,i_Fr, &
1578 nrrain(i_Qnorm,i_Drscale,i_Fr), &
1579 qrrain(i_Qnorm,i_Drscale,i_Fr)
1581 enddo !i_Drscale-loop
1585 ! The values of i_Znorm (3-momI) and i_rhor/i_Fr (2-momI) are "passed in" for parallelized
1586 ! version of code, thus the loops are commented out.
1589 ! enddo i_Znorm_loop
1594 END PROGRAM create_p3_lookuptable_1
1595 !______________________________________________________________________________________
1597 ! Incomplete gamma function
1598 ! from Numerical Recipes in Fortran 77: The Art of
1599 ! Scientific Computing
1606 ! Returns the incomplete gamma function Q(a,x) = 1-P(a,x)
1608 real gammcf,gammser,gln
1609 ! if (x.lt.0..or.a.le.0) pause 'bad argument in gammq'
1610 if (x.lt.0..or.a.le.0) print*, 'bad argument in gammq'
1612 call gser(gamser,a,x,gln)
1615 call gcf(gammcf,a,x,gln)
1621 !______________________________________________________________________________________
1623 subroutine gser(gamser,a,x,gln)
1625 real a,gamser,gln,x,eps
1626 parameter(itmax=100,eps=3.e-7)
1628 real ap,del,sum,gamma
1631 ! if (x.lt.0.) pause 'x < 0 in gser'
1632 if (x.lt.0.) print*, 'x < 0 in gser'
1643 if (abs(del).lt.abs(sum)*eps) goto 1
1645 ! pause 'a too large, itmax too small in gser'
1646 print*, 'a too large, itmax too small in gser'
1647 1 gamser=sum*exp(-x+a*log(x)-gln)
1651 !______________________________________________________________________________________
1653 subroutine gcf(gammcf,a,x,gln)
1655 real a,gammcf,gln,x,eps,fpmin
1656 parameter(itmax=100,eps=3.e-7,fpmin=1.e-30)
1658 real an,b,c,d,del,h,gamma
1668 if(abs(d).lt.fpmin) d=fpmin
1670 if(abs(c).lt.fpmin) c=fpmin
1674 if(abs(del-1.).lt.eps)goto 1
1676 ! pause 'a too large, itmax too small in gcf'
1677 print*, 'a too large, itmax too small in gcf'
1678 1 gammcf=exp(-x+a*log(x)-gln)*h
1682 !______________________________________________________________________________________
1684 real function compute_mu_3moment(mom3,mom6,mu_max)
1686 !--------------------------------------------------------------------------
1687 ! Computes mu as a function of G(mu), where
1689 ! G(mu)= N*Z/Q^2 = [(6+mu)(5+mu)(4+mu)]/[(3+mu)(2+mu)(1+mu)]
1692 !--------------------------------------------------------------------------
1697 real, intent(in) :: mom3,mom6 !normalized moments
1698 real, intent(in) :: mu_max !maximum allowable value of mu
1701 real :: mu ! shape parameter in gamma distribution
1704 ! calculate G from normalized moments
1707 !----------------------------------------------------------!
1708 ! !Solve alpha numerically: (brute-force)
1713 ! g1= (6.+a1)*(5.+a1)*(4.+a1)/((3.+a1)*(2.+a1)*(1.+a1))
1714 ! if(abs(g-g1)<abs(g-g2)) then
1719 !----------------------------------------------------------!
1721 !Piecewise-polynomial approximation of G(mu) to solve for mu:
1726 if (G<20. .and.G>=13.31) mu = 3.3638e-3*g2 - 1.7152e-1*G + 2.0857e+0
1727 if (G<13.31.and.G>=7.123) mu = 1.5900e-2*g2 - 4.8202e-1*G + 4.0108e+0
1728 if (G<7.123.and.G>=4.200) mu = 1.0730e-1*g2 - 1.7481e+0*G + 8.4246e+0
1729 if (G<4.200.and.G>=2.946) mu = 5.9070e-1*g2 - 5.7918e+0*G + 1.6919e+1
1730 if (G<2.946.and.G>=1.793) mu = 4.3966e+0*g2 - 2.6659e+1*G + 4.5477e+1
1731 if (G<1.793.and.G>=1.405) mu = 4.7552e+1*g2 - 1.7958e+2*G + 1.8126e+2
1732 if (G<1.405.and.G>=1.230) mu = 3.0889e+2*g2 - 9.0854e+2*G + 6.8995e+2
1733 if (G<1.230) mu = mu_max
1736 compute_mu_3moment = mu
1738 end function compute_mu_3moment
1740 !______________________________________________________________________________________
1742 real function diagnostic_mui(mu_i_min,mu_i_max,lam,q,cgp,Fr,pi)
1744 !----------------------------------------------------------!
1745 ! Compute mu_i diagnostically.
1746 !----------------------------------------------------------!
1751 real :: mu_i_min,mu_i_max,lam,q,cgp,Fr,pi
1754 real, parameter :: Di_thres = 0.2 !diameter threshold [mm]
1755 !real, parameter :: Di_thres = 0.6 !diameter threshold [mm]
1756 real :: mu_i,dum1,dum2,dum3
1759 !-- diagnostic mu_i, original formulation: (from Heymsfield, 2003)
1760 ! mu_i = 0.076*(lam/100.)**0.8-2. ! /100 is to convert m-1 to cm-1
1761 ! mu_i = max(mu_i,0.)
1762 ! mu_i = min(mu_i,6.)
1764 !-- diagnostic mu_i, 3-moment-based formulation:
1765 ! dum1 = (q/cgp)**(1./3)*1000. ! estimated Dmvd [mm], assuming spherical
1766 ! if (dum1<=Di_thres) then
1767 ! !diagnostic mu_i, original formulation: (from Heymsfield, 2003)
1768 ! mu_i = 0.076*(lam*0.01)**0.8-2. ! /100 is to convert m-1 to cm-1
1769 ! mu_i = min(mu_i,6.)
1771 ! dum2 = (6./pi)*cgp ! mean density (total)
1772 ! dum3 = max(1., 1.+0.00842*(dum2-400.)) ! adjustment factor for density
1773 ! mu_i = 4.*(dum1-Di_thres)*dum3*Fr
1775 ! mu_i = max(mu_i,mu_i_min) ! make sure mu_i >= 0, otherwise size dist is infinity at D = 0
1776 ! mu_i = min(mu_i,mu_i_max)
1778 dum1 = (q/cgp)**(1./3)*1000. ! estimated Dmvd [mm], assuming spherical
1779 if (dum1<=Di_thres) then
1780 !diagnostic mu_i, original formulation: (from Heymsfield, 2003)
1781 mu_i = 0.076*(lam*0.01)**0.8-2. ! /100 is to convert m-1 to cm-1
1784 dum2 = (6./pi)*cgp ! mean density (total)
1785 ! dum3 = max(1., 1.+0.00842*(dum2-400.)) ! adjustment factor for density
1786 dum3 = max(1., 1.+0.00842*(dum2-400.)) ! adjustment factor for density
1787 mu_i = 0.25*(dum1-Di_thres)*dum3*Fr
1789 mu_i = max(mu_i,mu_i_min) ! make sure mu_i >= 0, otherwise size dist is infinity at D = 0
1790 mu_i = min(mu_i,mu_i_max)
1792 diagnostic_mui = mu_i
1794 end function diagnostic_mui
1796 !______________________________________________________________________________________
1798 subroutine intgrl_section(lam,mu, d1,d2,d3,d4, Dcrit1,Dcrit2,Dcrit3, &
1799 intsec_1,intsec_2,intsec_3,intsec_4)
1801 ! Computes and returns partial integrals (partial moments) of ice PSD.
1807 real, intent(in) :: lam,mu, d1,d2,d3,d4, Dcrit1,Dcrit2,Dcrit3
1808 real, intent(out) :: intsec_1,intsec_2,intsec_3,intsec_4
1814 !Region I -- integral from 0 to Dcrit1 (small spherical ice)
1815 intsec_1 = lam**(-d1-mu-1.)*gamma(mu+d1+1.)*(1.-gammq(mu+d1+1.,Dcrit1*lam))
1817 !Region II -- integral from Dcrit1 to Dcrit2 (non-spherical unrimed ice)
1818 intsec_2 = lam**(-d2-mu-1.)*gamma(mu+d2+1.)*(gammq(mu+d2+1.,Dcrit1*lam))
1819 dum = lam**(-d2-mu-1.)*gamma(mu+d2+1.)*(gammq(mu+d2+1.,Dcrit2*lam))
1820 intsec_2 = intsec_2-dum
1822 !Region III -- integral from Dcrit2 to Dcrit3 (fully rimed spherical ice)
1823 intsec_3 = lam**(-d3-mu-1.)*gamma(mu+d3+1.)*(gammq(mu+d3+1.,Dcrit2*lam))
1824 dum = lam**(-d3-mu-1.)*gamma(mu+d3+1.)*(gammq(mu+d3+1.,Dcrit3*lam))
1825 intsec_3 = intsec_3-dum
1827 !Region IV -- integral from Dcrit3 to infinity (partially rimed ice)
1828 intsec_4 = lam**(-d4-mu-1.)*gamma(mu+d4+1.)*(gammq(mu+d4+1.,Dcrit3*lam))
1832 end subroutine intgrl_section