PageRenderTime 80ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/wrfv2_fire/phys/module_mixactivate.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 2743 lines | 1845 code | 334 blank | 564 comment | 153 complexity | aa80bcb1902394863ac73d83dbb3835e MD5 | raw file
Possible License(s): AGPL-1.0
  1. !************************************************************************
  2. ! This computer software was prepared by Battelle Memorial Institute,
  3. ! hereinafter the Contractor, under Contract No. DE-AC05-76RL0 1830 with
  4. ! the Department of Energy (DOE). NEITHER THE GOVERNMENT NOR THE
  5. ! CONTRACTOR MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY
  6. ! LIABILITY FOR THE USE OF THIS SOFTWARE.
  7. !
  8. ! MOSAIC module: see chem/module_mosaic_driver.F for references and terms
  9. ! of use
  10. !************************************************************************
  11. MODULE module_mixactivate
  12. PRIVATE
  13. PUBLIC prescribe_aerosol_mixactivate, mixactivate
  14. CONTAINS
  15. !----------------------------------------------------------------------
  16. !----------------------------------------------------------------------
  17. ! 06-nov-2005 rce - grid_id & ktau added to arg list
  18. ! 25-apr-2006 rce - dens_aer is (g/cm3), NOT (kg/m3)
  19. subroutine prescribe_aerosol_mixactivate ( &
  20. grid_id, ktau, dtstep, naer, &
  21. rho_phy, th_phy, pi_phy, w, cldfra, cldfra_old, &
  22. z, dz8w, p_at_w, t_at_w, exch_h, &
  23. qv, qc, qi, qndrop3d, &
  24. nsource, &
  25. ids,ide, jds,jde, kds,kde, &
  26. ims,ime, jms,jme, kms,kme, &
  27. its,ite, jts,jte, kts,kte, &
  28. f_qc, f_qi )
  29. ! USE module_configure
  30. ! wrapper to call mixactivate for mosaic description of aerosol
  31. implicit none
  32. ! subr arguments
  33. integer, intent(in) :: &
  34. grid_id, ktau, &
  35. ids, ide, jds, jde, kds, kde, &
  36. ims, ime, jms, jme, kms, kme, &
  37. its, ite, jts, jte, kts, kte
  38. real, intent(in) :: dtstep
  39. real, intent(inout) :: naer ! aerosol number (/kg)
  40. real, intent(in), &
  41. dimension( ims:ime, kms:kme, jms:jme ) :: &
  42. rho_phy, th_phy, pi_phy, w, &
  43. z, dz8w, p_at_w, t_at_w, exch_h
  44. real, intent(inout), &
  45. dimension( ims:ime, kms:kme, jms:jme ) :: cldfra, cldfra_old
  46. real, intent(in), &
  47. dimension( ims:ime, kms:kme, jms:jme ) :: &
  48. qv, qc, qi
  49. real, intent(inout), &
  50. dimension( ims:ime, kms:kme, jms:jme ) :: &
  51. qndrop3d
  52. real, intent(out), &
  53. dimension( ims:ime, kms:kme, jms:jme) :: nsource
  54. LOGICAL, OPTIONAL :: f_qc, f_qi
  55. ! local vars
  56. integer maxd_aphase, maxd_atype, maxd_asize, maxd_acomp, max_chem
  57. parameter (maxd_aphase=2,maxd_atype=1,maxd_asize=1,maxd_acomp=1, max_chem=10)
  58. real ddvel(its:ite, jts:jte, max_chem) ! dry deposition velosity
  59. real qsrflx(ims:ime, jms:jme, max_chem) ! dry deposition flux of aerosol
  60. real chem(ims:ime, kms:kme, jms:jme, max_chem) ! chem array
  61. integer i,j,k,l,m,n,p
  62. real hygro( its:ite, kts:kte, jts:jte, maxd_asize, maxd_atype ) ! bulk
  63. integer ntype_aer, nsize_aer(maxd_atype),ncomp_aer(maxd_atype), nphase_aer
  64. integer massptr_aer( maxd_acomp, maxd_asize, maxd_atype, maxd_aphase ), &
  65. waterptr_aer( maxd_asize, maxd_atype ), &
  66. numptr_aer( maxd_asize, maxd_atype, maxd_aphase ), &
  67. ai_phase, cw_phase
  68. real dlo_sect( maxd_asize, maxd_atype ), & ! minimum size of section (cm)
  69. dhi_sect( maxd_asize, maxd_atype ), & ! maximum size of section (cm)
  70. sigmag_aer(maxd_asize, maxd_atype), & ! geometric standard deviation of aerosol size dist
  71. dgnum_aer(maxd_asize, maxd_atype), & ! median diameter (cm) of number distrib of mode
  72. dens_aer( maxd_acomp, maxd_atype), & ! density (g/cm3) of material
  73. mw_aer( maxd_acomp, maxd_atype), & ! molecular weight (g/mole)
  74. dpvolmean_aer(maxd_asize, maxd_atype) ! mean-volume diameter (cm) of mode
  75. ! terminology: (pi/6) * (mean-volume diameter)**3 ==
  76. ! (volume mixing ratio of section/mode)/(number mixing ratio)
  77. real, dimension(ims:ime,kms:kme,jms:jme) :: &
  78. ccn1,ccn2,ccn3,ccn4,ccn5,ccn6 ! number conc of aerosols activated at supersat
  79. integer idrydep_onoff
  80. real, dimension(ims:ime,kms:kme,jms:jme) :: t_phy
  81. integer msectional
  82. integer ptr
  83. real maer
  84. if(naer.lt.1.)then
  85. naer=1000.e6 ! #/kg default value
  86. endif
  87. ai_phase=1
  88. cw_phase=2
  89. idrydep_onoff = 0
  90. msectional = 0
  91. t_phy(its:ite,kts:kte,jts:jte)=th_phy(its:ite,kts:kte,jts:jte)*pi_phy(its:ite,kts:kte,jts:jte)
  92. ntype_aer=maxd_atype
  93. do n=1,ntype_aer
  94. nsize_aer(n)=maxd_asize
  95. ncomp_aer(n)=maxd_acomp
  96. end do
  97. nphase_aer=maxd_aphase
  98. ! set properties for each type and size
  99. do n=1,ntype_aer
  100. do m=1,nsize_aer(n)
  101. dlo_sect( m,n )=0.01e-4 ! minimum size of section (cm)
  102. dhi_sect( m,n )=0.5e-4 ! maximum size of section (cm)
  103. sigmag_aer(m,n)=2. ! geometric standard deviation of aerosol size dist
  104. dgnum_aer(m,n)=0.1e-4 ! median diameter (cm) of number distrib of mode
  105. dpvolmean_aer(m,n) = dgnum_aer(m,n) * exp( 1.5 * (log(sigmag_aer(m,n)))**2 )
  106. end do
  107. do l=1,ncomp_aer(n)
  108. dens_aer( l, n)=1.0 ! density (g/cm3) of material
  109. mw_aer( l, n)=132. ! molecular weight (g/mole)
  110. end do
  111. end do
  112. ptr=0
  113. do p=1,nphase_aer
  114. do n=1,ntype_aer
  115. do m=1,nsize_aer(n)
  116. ptr=ptr+1
  117. numptr_aer( m, n, p )=ptr
  118. if(p.eq.ai_phase)then
  119. chem(its:ite,kts:kte,jts:jte,ptr)=naer
  120. else
  121. chem(its:ite,kts:kte,jts:jte,ptr)=0.
  122. endif
  123. end do ! size
  124. end do ! type
  125. end do ! phase
  126. do p=1,maxd_aphase
  127. do n=1,ntype_aer
  128. do m=1,nsize_aer(n)
  129. do l=1,ncomp_aer(n)
  130. ptr=ptr+1
  131. if(ptr.gt.max_chem)then
  132. write(6,*)'ptr,max_chem=',ptr,max_chem,' in prescribe_aerosol_mixactivate'
  133. call wrf_error_fatal("1")
  134. endif
  135. massptr_aer(l, m, n, p)=ptr
  136. ! maer is ug/kg-air; naer is #/kg-air; dgnum is cm; dens_aer is g/cm3
  137. ! 1.e6 factor converts g to ug
  138. maer= 1.0e6 * naer * dens_aer(l,n) * ( (3.1416/6.) * &
  139. (dgnum_aer(m,n)**3) * exp( 4.5*((log(sigmag_aer(m,n)))**2) ) )
  140. if(p.eq.ai_phase)then
  141. chem(its:ite,kts:kte,jts:jte,ptr)=maer
  142. else
  143. chem(its:ite,kts:kte,jts:jte,ptr)=0.
  144. endif
  145. end do
  146. end do ! size
  147. end do ! type
  148. end do ! phase
  149. do n=1,ntype_aer
  150. do m=1,nsize_aer(n)
  151. ptr=ptr+1
  152. if(ptr.gt.max_chem)then
  153. write(6,*)'ptr,max_chem=',ptr,max_chem,' in prescribe_aerosol_mixactivate'
  154. call wrf_error_fatal("1")
  155. endif
  156. !wig waterptr_aer(m, n)=ptr
  157. waterptr_aer(m, n)=-1
  158. end do ! size
  159. end do ! type
  160. ddvel(its:ite,jts:jte,:)=0.
  161. hygro(its:ite,kts:kte,jts:jte,:,:) = 0.5
  162. ! 06-nov-2005 rce - grid_id & ktau added to arg list
  163. call mixactivate( msectional, &
  164. chem,max_chem,qv,qc,qi,qndrop3d, &
  165. t_phy, w, ddvel, idrydep_onoff, &
  166. maxd_acomp, maxd_asize, maxd_atype, maxd_aphase, &
  167. ncomp_aer, nsize_aer, ntype_aer, nphase_aer, &
  168. numptr_aer, massptr_aer, dlo_sect, dhi_sect, sigmag_aer, dpvolmean_aer, &
  169. dens_aer, mw_aer, &
  170. waterptr_aer, hygro, ai_phase, cw_phase, &
  171. ids,ide, jds,jde, kds,kde, &
  172. ims,ime, jms,jme, kms,kme, &
  173. its,ite, jts,jte, kts,kte, &
  174. rho_phy, z, dz8w, p_at_w, t_at_w, exch_h, &
  175. cldfra, cldfra_old, qsrflx, &
  176. ccn1, ccn2, ccn3, ccn4, ccn5, ccn6, nsource, &
  177. grid_id, ktau, dtstep, &
  178. F_QC=f_qc, F_QI=f_qi )
  179. end subroutine prescribe_aerosol_mixactivate
  180. !----------------------------------------------------------------------
  181. !----------------------------------------------------------------------
  182. ! nov-04 sg ! replaced amode with aer and expanded aerosol dimension to include type and phase
  183. ! 06-nov-2005 rce - grid_id & ktau added to arg list
  184. ! 25-apr-2006 rce - dens_aer is (g/cm3), NOT (kg/m3)
  185. subroutine mixactivate( msectional, &
  186. chem, num_chem, qv, qc, qi, qndrop3d, &
  187. temp, w, ddvel, idrydep_onoff, &
  188. maxd_acomp, maxd_asize, maxd_atype, maxd_aphase, &
  189. ncomp_aer, nsize_aer, ntype_aer, nphase_aer, &
  190. numptr_aer, massptr_aer, dlo_sect, dhi_sect, sigmag_aer, dpvolmean_aer, &
  191. dens_aer, mw_aer, &
  192. waterptr_aer, hygro, ai_phase, cw_phase, &
  193. ids,ide, jds,jde, kds,kde, &
  194. ims,ime, jms,jme, kms,kme, &
  195. its,ite, jts,jte, kts,kte, &
  196. rho, zm, dz8w, p_at_w, t_at_w, kvh, &
  197. cldfra, cldfra_old, qsrflx, &
  198. ccn1, ccn2, ccn3, ccn4, ccn5, ccn6, nsource, &
  199. grid_id, ktau, dtstep, &
  200. f_qc, f_qi )
  201. ! vertical diffusion and nucleation of cloud droplets
  202. ! assume cloud presence controlled by cloud fraction
  203. ! doesn't distinguish between warm, cold clouds
  204. USE module_model_constants, only: g, rhowater, xlv, cp, rvovrd, r_d, r_v, mwdry, ep_2
  205. USE module_radiation_driver, only: cal_cldfra
  206. implicit none
  207. ! input
  208. INTEGER, intent(in) :: grid_id, ktau
  209. INTEGER, intent(in) :: num_chem
  210. integer, intent(in) :: ids,ide, jds,jde, kds,kde, &
  211. ims,ime, jms,jme, kms,kme, &
  212. its,ite, jts,jte, kts,kte
  213. integer maxd_aphase, nphase_aer, maxd_atype, ntype_aer
  214. integer maxd_asize, maxd_acomp, nsize_aer(maxd_atype)
  215. integer, intent(in) :: &
  216. ncomp_aer( maxd_atype ), &
  217. massptr_aer( maxd_acomp, maxd_asize, maxd_atype, maxd_aphase ), &
  218. waterptr_aer( maxd_asize, maxd_atype ), &
  219. numptr_aer( maxd_asize, maxd_atype, maxd_aphase), &
  220. ai_phase, cw_phase
  221. integer, intent(in) :: msectional ! 1 for sectional, 0 for modal
  222. integer, intent(in) :: idrydep_onoff
  223. real, intent(in) :: &
  224. dlo_sect( maxd_asize, maxd_atype ), & ! minimum size of section (cm)
  225. dhi_sect( maxd_asize, maxd_atype ), & ! maximum size of section (cm)
  226. sigmag_aer(maxd_asize, maxd_atype), & ! geometric standard deviation of aerosol size dist
  227. dens_aer( maxd_acomp, maxd_atype), & ! density (g/cm3) of material
  228. mw_aer( maxd_acomp, maxd_atype), & ! molecular weight (g/mole)
  229. dpvolmean_aer(maxd_asize, maxd_atype) ! mean-volume diameter (cm) of mode
  230. ! terminology: (pi/6) * (mean-volume diameter)**3 ==
  231. ! (volume mixing ratio of section/mode)/(number mixing ratio)
  232. REAL, intent(inout), DIMENSION( ims:ime, kms:kme, jms:jme, num_chem ) :: &
  233. chem ! aerosol molar mixing ratio (ug/kg or #/kg)
  234. REAL, intent(in), DIMENSION( ims:ime, kms:kme, jms:jme ) :: &
  235. qv, qc, qi ! water species (vapor, cloud drops, cloud ice) mixing ratio (g/g)
  236. LOGICAL, OPTIONAL :: f_qc, f_qi
  237. REAL, intent(inout), DIMENSION( ims:ime, kms:kme, jms:jme ) :: &
  238. qndrop3d ! water species mixing ratio (g/g)
  239. real, intent(in) :: dtstep ! time step for microphysics (s)
  240. real, intent(in) :: temp(ims:ime, kms:kme, jms:jme) ! temperature (K)
  241. real, intent(in) :: w(ims:ime, kms:kme, jms:jme) ! vertical velocity (m/s)
  242. real, intent(in) :: rho(ims:ime, kms:kme, jms:jme) ! density at mid-level (kg/m3)
  243. REAL, intent(in) :: ddvel( its:ite, jts:jte, num_chem ) ! deposition velocity (m/s)
  244. real, intent(in) :: zm(ims:ime, kms:kme, jms:jme) ! geopotential height of level (m)
  245. real, intent(in) :: dz8w(ims:ime, kms:kme, jms:jme) ! layer thickness (m)
  246. real, intent(in) :: p_at_w(ims:ime, kms:kme, jms:jme) ! pressure at layer interface (Pa)
  247. real, intent(in) :: t_at_w(ims:ime, kms:kme, jms:jme) ! temperature at layer interface (K)
  248. real, intent(in) :: kvh(ims:ime, kms:kme, jms:jme) ! vertical diffusivity (m2/s)
  249. real, intent(inout) :: cldfra_old(ims:ime, kms:kme, jms:jme)! cloud fraction on previous time step
  250. real, intent(inout) :: cldfra(ims:ime, kms:kme, jms:jme) ! cloud fraction
  251. real, intent(in) :: hygro( its:ite, kts:kte, jts:jte, maxd_asize, maxd_atype ) ! bulk hygroscopicity &
  252. REAL, intent(out), DIMENSION( ims:ime, jms:jme, num_chem ) :: qsrflx ! dry deposition rate for aerosol
  253. real, intent(out), dimension(ims:ime,kms:kme,jms:jme) :: nsource, & ! droplet number source (#/kg/s)
  254. ccn1,ccn2,ccn3,ccn4,ccn5,ccn6 ! number conc of aerosols activated at supersat
  255. !--------------------Local storage-------------------------------------
  256. !
  257. real :: dgnum_aer(maxd_asize, maxd_atype) ! median diameter (cm) of number distrib of mode
  258. real :: qndrop(kms:kme) ! cloud droplet number mixing ratio (#/kg)
  259. real :: lcldfra(kms:kme) ! liquid cloud fraction
  260. real :: lcldfra_old(kms:kme) ! liquid cloud fraction for previous timestep
  261. real :: wtke(kms:kme) ! turbulent vertical velocity at base of layer k (m2/s)
  262. real zn(kms:kme) ! g/pdel (m2/g) for layer
  263. real zs(kms:kme) ! inverse of distance between levels (m)
  264. real, parameter :: zkmin = 0.01
  265. real, parameter :: zkmax = 100.
  266. real cs(kms:kme) ! air density (kg/m3) at layer center
  267. real csbot(kms:kme) ! air density (kg/m3) at layer bottom
  268. real csbot_cscen(kms:kme) ! csbot(k)/cs(k)
  269. real dz(kms:kme) ! geometric thickness of layers (m)
  270. real wdiab ! diabatic vertical velocity
  271. ! real, parameter :: wmixmin = 0.1 ! minimum turbulence vertical velocity (m/s)
  272. real, parameter :: wmixmin = 0.2 ! minimum turbulence vertical velocity (m/s)
  273. ! real, parameter :: wmixmin = 1.0 ! minimum turbulence vertical velocity (m/s)
  274. real :: qndrop_new(kms:kme) ! droplet number nucleated on cloud boundaries
  275. real :: ekd(kms:kme) ! diffusivity for droplets (m2/s)
  276. real :: ekk(kms:kme) ! density*diffusivity for droplets (kg/m3 m2/s)
  277. real :: srcn(kms:kme) ! droplet source rate (/s)
  278. real, parameter :: sq2pi = 2.5066282746
  279. real dtinv
  280. integer km1,kp1
  281. real wbar,wmix,wmin,wmax
  282. real dum
  283. real tmpa, tmpb, tmpc, tmpc1, tmpc2, tmpd, tmpe, tmpf
  284. real tmpcourno
  285. real dact
  286. real fluxntot ! (#/cm2/s)
  287. real fac_srflx
  288. real depvel_drop, depvel_tmp
  289. real, parameter :: depvel_uplimit = 1.0 ! upper limit for dep vels (m/s)
  290. real :: surfrate(num_chem) ! surface exchange rate (/s)
  291. real surfratemax ! max surfrate for all species treated here
  292. real surfrate_drop ! surfade exchange rate for droplelts
  293. real dtmin,tinv,dtt
  294. integer nsubmix,nsubmix_bnd
  295. integer i,j,k,m,n,nsub
  296. real dtmix
  297. real alogarg
  298. real qcld
  299. real pi
  300. integer nnew,nsav,ntemp
  301. real :: overlapp(kms:kme),overlapm(kms:kme) ! cloud overlap
  302. real :: ekkp(kms:kme),ekkm(kms:kme) ! zn*zs*density*diffusivity
  303. ! integer, save :: count_submix(100)=0 ! wig: Note that this is a no-no for tile threads with OMP
  304. integer lnum,lnumcw,l,lmass,lmasscw,lsfc,lsfccw,ltype,lsig,lwater
  305. integer :: ntype(maxd_asize)
  306. real :: naerosol(maxd_asize, maxd_atype) ! interstitial aerosol number conc (/m3)
  307. real :: naerosolcw(maxd_asize, maxd_atype) ! activated number conc (/m3)
  308. real :: maerosol(maxd_acomp,maxd_asize, maxd_atype) ! interstit mass conc (kg/m3)
  309. real :: maerosolcw(maxd_acomp,maxd_asize, maxd_atype) ! activated mass conc (kg/m3)
  310. real :: maerosol_tot(maxd_asize, maxd_atype) ! species-total interstit mass conc (kg/m3)
  311. real :: maerosol_totcw(maxd_asize, maxd_atype) ! species-total activated mass conc (kg/m3)
  312. real :: vaerosol(maxd_asize, maxd_atype) ! interstit+activated aerosol volume conc (m3/m3)
  313. real :: vaerosolcw(maxd_asize, maxd_atype) ! activated aerosol volume conc (m3/m3)
  314. real :: raercol(kms:kme,num_chem,2) ! aerosol mass, number mixing ratios
  315. real :: source(kms:kme) !
  316. real :: fn(maxd_asize, maxd_atype) ! activation fraction for aerosol number
  317. real :: fs(maxd_asize, maxd_atype) ! activation fraction for aerosol sfcarea
  318. real :: fm(maxd_asize, maxd_atype) ! activation fraction for aerosol mass
  319. integer :: ncomp(maxd_atype)
  320. real :: fluxn(maxd_asize, maxd_atype) ! number activation fraction flux (m/s)
  321. real :: fluxs(maxd_asize, maxd_atype) ! sfcarea activation fraction flux (m/s)
  322. real :: fluxm(maxd_asize, maxd_atype) ! mass activation fraction flux (m/s)
  323. real :: flux_fullact(kms:kme) ! 100% activation fraction flux (m/s)
  324. ! note: activation fraction fluxes are defined as
  325. ! fluxn = [flux of activated aero. number into cloud (#/m2/s)]
  326. ! / [aero. number conc. in updraft, just below cloudbase (#/m3)]
  327. real :: nact(kms:kme,maxd_asize, maxd_atype) ! fractional aero. number activation rate (/s)
  328. real :: mact(kms:kme,maxd_asize, maxd_atype) ! fractional aero. mass activation rate (/s)
  329. real :: npv(maxd_asize, maxd_atype) ! number per volume concentration (/m3)
  330. real scale
  331. real :: hygro_aer(maxd_asize, maxd_atype) ! hygroscopicity of aerosol mode
  332. real :: exp45logsig ! exp(4.5*alogsig**2)
  333. real :: alogsig(maxd_asize, maxd_atype) ! natl log of geometric standard dev of aerosol
  334. integer, parameter :: psat=6 ! number of supersaturations to calc ccn concentration
  335. real ccn(kts:kte,psat) ! number conc of aerosols activated at supersat
  336. real, parameter :: supersat(psat)= &! supersaturation (%) to determine ccn concentration
  337. (/0.02,0.05,0.1,0.2,0.5,1.0/)
  338. real super(psat) ! supersaturation
  339. real, parameter :: surften = 0.076 ! surface tension of water w/respect to air (N/m)
  340. real :: ccnfact(psat,maxd_asize, maxd_atype)
  341. real :: amcube(maxd_asize, maxd_atype) ! cube of dry mode radius (m)
  342. real :: argfactor(maxd_asize, maxd_atype)
  343. real aten ! surface tension parameter
  344. real t0 ! reference temperature
  345. real sm ! critical supersaturation
  346. real arg
  347. integer,parameter :: icheck_colmass = 0
  348. ! icheck_colmass > 0 turns on mass/number conservation checking
  349. ! values of 1, 10, 100 produce less to more diagnostics
  350. integer :: colmass_worst_ij( 2, 0:maxd_acomp, maxd_asize, maxd_atype )
  351. integer :: colmass_maxworst_i(3)
  352. real :: colmass_bgn( 0:maxd_acomp, maxd_asize, maxd_atype, maxd_aphase )
  353. real :: colmass_end( 0:maxd_acomp, maxd_asize, maxd_atype, maxd_aphase )
  354. real :: colmass_sfc( 0:maxd_acomp, maxd_asize, maxd_atype, maxd_aphase )
  355. real :: colmass_worst( 0:maxd_acomp, maxd_asize, maxd_atype )
  356. real :: colmass_maxworst_r
  357. real :: rhodz( kts:kte ), rhodzsum
  358. !!$#if (defined AIX)
  359. !!$#define ERF erf
  360. !!$#define ERFC erfc
  361. !!$#else
  362. !!$#define ERF erf
  363. !!$ real erf
  364. !!$#define ERFC erfc
  365. !!$ real erfc
  366. !!$#endif
  367. character*8, parameter :: ccn_name(psat)=(/'CCN1','CCN2','CCN3','CCN4','CCN5','CCN6'/)
  368. colmass_worst(:,:,:) = 0.0
  369. colmass_worst_ij(:,:,:,:) = -1
  370. arg = 1.0
  371. if (abs(0.8427-ERF_ALT(arg))/0.8427>0.001) then
  372. write (6,*) 'erf_alt(1.0) = ',ERF_ALT(arg)
  373. call wrf_error_fatal('dropmixnuc: Error function error')
  374. endif
  375. arg = 0.0
  376. if (ERF_ALT(arg) /= 0.0) then
  377. write (6,*) 'erf_alt(0.0) = ',ERF_ALT(arg)
  378. call wrf_error_fatal('dropmixnuc: Error function error')
  379. endif
  380. pi = 4.*atan(1.0)
  381. dtinv=1./dtstep
  382. depvel_drop = 0.1 ! prescribed here rather than getting it from dry_dep_driver
  383. if (idrydep_onoff .le. 0) depvel_drop = 0.0
  384. depvel_drop = min(depvel_drop,depvel_uplimit)
  385. do n=1,ntype_aer
  386. do m=1,nsize_aer(n)
  387. ncomp(n)=ncomp_aer(n)
  388. alogsig(m,n)=alog(sigmag_aer(m,n))
  389. dgnum_aer(m,n) = dpvolmean_aer(m,n) * exp( -1.5*alogsig(m,n)*alogsig(m,n) )
  390. ! print *,'sigmag_aer,dgnum_aer=',sigmag_aer(m,n),dgnum_aer(m,n)
  391. ! npv is used only if number is diagnosed from volume
  392. npv(m,n)=6./(pi*(0.01*dgnum_aer(m,n))**3*exp(4.5*alogsig(m,n)*alogsig(m,n)))
  393. end do
  394. end do
  395. t0=273.15 !wig, 1-Mar-2009: Added .15
  396. aten=2.*surften/(r_v*t0*rhowater)
  397. super(:)=0.01*supersat(:)
  398. do n=1,ntype_aer
  399. do m=1,nsize_aer(n)
  400. exp45logsig=exp(4.5*alogsig(m,n)*alogsig(m,n))
  401. argfactor(m,n)=2./(3.*sqrt(2.)*alogsig(m,n))
  402. amcube(m,n)=3./(4.*pi*exp45logsig*npv(m,n))
  403. enddo
  404. enddo
  405. IF( PRESENT(F_QC) .AND. PRESENT ( F_QI ) ) THEN
  406. CALL cal_cldfra(CLDFRA,qc,qi,f_qc,f_qi, &
  407. ids,ide, jds,jde, kds,kde, &
  408. ims,ime, jms,jme, kms,kme, &
  409. its,ite, jts,jte, kts,kte )
  410. END IF
  411. qsrflx(its:ite,jts:jte,:) = 0.
  412. ! start loop over columns
  413. OVERALL_MAIN_J_LOOP: do j=jts,jte
  414. OVERALL_MAIN_I_LOOP: do i=its,ite
  415. ! load number nucleated into qndrop on cloud boundaries
  416. ! initialization for current i .........................................
  417. do k=kts+1,kte
  418. zs(k)=1./(zm(i,k,j)-zm(i,k-1,j))
  419. enddo
  420. zs(kts)=zs(kts+1)
  421. zs(kte+1)=0.
  422. do k=kts,kte
  423. !!$ if(qndrop3d(i,k,j).lt.-10.e6.or.qndrop3d(i,k,j).gt.1.E20)then
  424. !!$! call wrf_error_fatal("1")
  425. !!$ endif
  426. if(f_qi)then
  427. qcld=qc(i,k,j)+qi(i,k,j)
  428. else
  429. qcld=qc(i,k,j)
  430. endif
  431. if(qcld.lt.-1..or.qcld.gt.1.)then
  432. write(6,'(a,g12.2,a,3i5)')'qcld=',qcld,' for i,k,j=',i,k,j
  433. call wrf_error_fatal("1")
  434. endif
  435. if(qcld.gt.1.e-20)then
  436. lcldfra(k)=cldfra(i,k,j)*qc(i,k,j)/qcld
  437. lcldfra_old(k)=cldfra_old(i,k,j)*qc(i,k,j)/qcld
  438. else
  439. lcldfra(k)=0.
  440. lcldfra_old(k)=0.
  441. endif
  442. qndrop(k)=qndrop3d(i,k,j)
  443. ! qndrop(k)=1.e5
  444. cs(k)=rho(i,k,j) ! air density (kg/m3)
  445. dz(k)=dz8w(i,k,j)
  446. do n=1,ntype_aer
  447. do m=1,nsize_aer(n)
  448. nact(k,m,n)=0.
  449. mact(k,m,n)=0.
  450. enddo
  451. enddo
  452. zn(k)=1./(cs(k)*dz(k))
  453. if(k>kts)then
  454. ekd(k)=kvh(i,k,j)
  455. ekd(k)=max(ekd(k),zkmin)
  456. ekd(k)=min(ekd(k),zkmax)
  457. else
  458. ekd(k)=0
  459. endif
  460. ! diagnose subgrid vertical velocity from diffusivity
  461. if(k.eq.kts)then
  462. wtke(k)=sq2pi*depvel_drop
  463. ! wtke(k)=sq2pi*kvh(i,k,j)
  464. ! wtke(k)=max(wtke(k),wmixmin)
  465. else
  466. wtke(k)=sq2pi*ekd(k)/dz(k)
  467. endif
  468. wtke(k)=max(wtke(k),wmixmin)
  469. nsource(i,k,j)=0.
  470. enddo
  471. nsource(i,kte+1,j) = 0.
  472. qndrop(kte+1) = 0.
  473. zn(kte+1) = 0.
  474. do k = kts+1, kte
  475. tmpa = dz(k-1) ; tmpb = dz(k)
  476. tmpc = tmpa/(tmpa + tmpb)
  477. csbot(k) = cs(k-1)*(1.0-tmpc) + cs(k)*tmpc
  478. csbot_cscen(k) = csbot(k)/cs(k)
  479. end do
  480. csbot(kts) = cs(kts)
  481. csbot_cscen(kts) = 1.0
  482. csbot(kte+1) = cs(kte)
  483. csbot_cscen(kte+1) = 1.0
  484. ! calculate surface rate and mass mixing ratio for aerosol
  485. surfratemax = 0.0
  486. nsav=1
  487. nnew=2
  488. surfrate_drop=depvel_drop/dz(kts)
  489. surfratemax = max( surfratemax, surfrate_drop )
  490. do n=1,ntype_aer
  491. do m=1,nsize_aer(n)
  492. lnum=numptr_aer(m,n,ai_phase)
  493. lnumcw=numptr_aer(m,n,cw_phase)
  494. if(lnum>0)then
  495. depvel_tmp = max( 0.0, min( ddvel(i,j,lnum), depvel_uplimit ) )
  496. surfrate(lnum)=depvel_tmp/dz(kts)
  497. surfrate(lnumcw)=surfrate_drop
  498. surfratemax = max( surfratemax, surfrate(lnum) )
  499. ! scale = 1000./mwdry ! moles/kg
  500. scale = 1.
  501. raercol(kts:kte,lnumcw,nsav)=chem(i,kts:kte,j,lnumcw)*scale ! #/kg
  502. raercol(kts:kte,lnum,nsav)=chem(i,kts:kte,j,lnum)*scale
  503. endif
  504. do l=1,ncomp(n)
  505. lmass=massptr_aer(l,m,n,ai_phase)
  506. lmasscw=massptr_aer(l,m,n,cw_phase)
  507. ! scale = mw_aer(l,n)/mwdry
  508. scale = 1.e-9 ! kg/ug
  509. depvel_tmp = max( 0.0, min( ddvel(i,j,lmass), depvel_uplimit ) )
  510. surfrate(lmass)=depvel_tmp/dz(kts)
  511. surfrate(lmasscw)=surfrate_drop
  512. surfratemax = max( surfratemax, surfrate(lmass) )
  513. raercol(kts:kte,lmasscw,nsav)=chem(i,kts:kte,j,lmasscw)*scale ! kg/kg
  514. raercol(kts:kte,lmass,nsav)=chem(i,kts:kte,j,lmass)*scale ! kg/kg
  515. enddo
  516. lwater=waterptr_aer(m,n)
  517. if(lwater>0)then
  518. depvel_tmp = max( 0.0, min( ddvel(i,j,lwater), depvel_uplimit ) )
  519. surfrate(lwater)=depvel_tmp/dz(kts)
  520. surfratemax = max( surfratemax, surfrate(lwater) )
  521. raercol(kts:kte,lwater,nsav)=chem(i,kts:kte,j,lwater) ! don't bother to convert units,
  522. ! because it doesn't contribute to aerosol mass
  523. endif
  524. enddo ! size
  525. enddo ! type
  526. ! mass conservation checking
  527. if (icheck_colmass > 0) then
  528. ! calc initial column burdens
  529. colmass_bgn(:,:,:,:) = 0.0
  530. colmass_end(:,:,:,:) = 0.0
  531. colmass_sfc(:,:,:,:) = 0.0
  532. rhodz(kts:kte) = 1.0/zn(kts:kte)
  533. rhodzsum = sum( rhodz(kts:kte) )
  534. do n=1,ntype_aer
  535. do m=1,nsize_aer(n)
  536. lnum=numptr_aer(m,n,ai_phase)
  537. lnumcw=numptr_aer(m,n,cw_phase)
  538. if(lnum>0)then
  539. colmass_bgn(0,m,n,1) = sum( chem(i,kts:kte,j,lnum )*rhodz(kts:kte) )
  540. colmass_bgn(0,m,n,2) = sum( chem(i,kts:kte,j,lnumcw)*rhodz(kts:kte) )
  541. endif
  542. do l=1,ncomp(n)
  543. lmass=massptr_aer(l,m,n,ai_phase)
  544. lmasscw=massptr_aer(l,m,n,cw_phase)
  545. colmass_bgn(l,m,n,1) = sum( chem(i,kts:kte,j,lmass )*rhodz(kts:kte) )
  546. colmass_bgn(l,m,n,2) = sum( chem(i,kts:kte,j,lmasscw)*rhodz(kts:kte) )
  547. enddo
  548. enddo ! size
  549. enddo ! type
  550. endif ! (icheck_colmass > 0)
  551. ! droplet nucleation/aerosol activation
  552. ! k-loop for growing/shrinking cloud calcs .............................
  553. GROW_SHRINK_MAIN_K_LOOP: do k=kts,kte
  554. km1=max0(k-1,1)
  555. kp1=min0(k+1,kde-1)
  556. ! if(lcldfra(k)-lcldfra_old(k).gt.0.01)then ! this line is the "old" criterion
  557. ! go to 10
  558. ! growing cloud PLUS
  559. ! upwards vertical advection when lcldfra(k-1) < lcldfra(k)
  560. !
  561. ! tmpc1 = cloud fraction increase from previous time step
  562. tmpc1 = max( (lcldfra(k)-lcldfra_old(k)), 0.0 )
  563. if (k > kts) then
  564. ! tmpc2 = fraction of layer for which vertical advection from below
  565. ! (over dtstep) displaces cloudy air with clear air
  566. ! = (courant number using upwards w at layer bottom)*(difference in cloud fraction)
  567. tmpcourno = dtstep*max(w(i,k,j),0.0)/dz(k)
  568. tmpc2 = max( (lcldfra(k)-lcldfra(km1)), 0.0 ) * tmpcourno
  569. tmpc2 = min( tmpc2, 1.0 )
  570. ! tmpc2 = 0.0 ! this turns off the vertical advect part
  571. else
  572. tmpc2 = 0.0
  573. endif
  574. if ((tmpc1 > 0.001) .or. (tmpc2 > 0.001)) then
  575. ! wmix=wtke(k)
  576. wbar=w(i,k,j)+wtke(k)
  577. wmix=0.
  578. wmin=0.
  579. ! 06-nov-2005 rce - increase wmax from 10 to 50 (deep convective clouds)
  580. wmax=50.
  581. wdiab=0
  582. ! load aerosol properties, assuming external mixtures
  583. do n=1,ntype_aer
  584. do m=1,nsize_aer(n)
  585. call loadaer(raercol(1,1,nsav),k,kms,kme,num_chem, &
  586. cs(k), npv(m,n), dlo_sect(m,n),dhi_sect(m,n), &
  587. maxd_acomp, ncomp(n), &
  588. grid_id, ktau, i, j, m, n, &
  589. numptr_aer(m,n,ai_phase),numptr_aer(m,n,cw_phase), &
  590. dens_aer(1,n), &
  591. massptr_aer(1,m,n,ai_phase), massptr_aer(1,m,n,cw_phase), &
  592. maerosol(1,m,n), maerosolcw(1,m,n), &
  593. maerosol_tot(m,n), maerosol_totcw(m,n), &
  594. naerosol(m,n), naerosolcw(m,n), &
  595. vaerosol(m,n), vaerosolcw(m,n) )
  596. hygro_aer(m,n)=hygro(i,k,j,m,n)
  597. enddo
  598. enddo
  599. ! 06-nov-2005 rce - grid_id & ktau added to arg list
  600. call activate(wbar,wmix,wdiab,wmin,wmax,temp(i,k,j),cs(k), &
  601. msectional, maxd_atype, ntype_aer, maxd_asize, nsize_aer, &
  602. naerosol, vaerosol, &
  603. dlo_sect,dhi_sect,sigmag_aer,hygro_aer, &
  604. fn,fs,fm,fluxn,fluxs,fluxm,flux_fullact(k), grid_id, ktau, i, j, k )
  605. do n = 1,ntype_aer
  606. do m = 1,nsize_aer(n)
  607. lnum = numptr_aer(m,n,ai_phase)
  608. lnumcw = numptr_aer(m,n,cw_phase)
  609. if (tmpc1 > 0.0) then
  610. dact = tmpc1*fn(m,n)*raercol(k,lnum,nsav) ! interstitial only
  611. else
  612. dact = 0.0
  613. endif
  614. if (tmpc2 > 0.0) then
  615. dact = dact + tmpc2*fn(m,n)*raercol(km1,lnum,nsav) ! interstitial only
  616. endif
  617. dact = min( dact, 0.99*raercol(k,lnum,nsav) )
  618. raercol(k,lnumcw,nsav) = raercol(k,lnumcw,nsav)+dact
  619. raercol(k,lnum, nsav) = raercol(k,lnum, nsav)-dact
  620. qndrop(k) = qndrop(k)+dact
  621. nsource(i,k,j) = nsource(i,k,j)+dact*dtinv
  622. do l = 1,ncomp(n)
  623. lmass = massptr_aer(l,m,n,ai_phase)
  624. lmasscw = massptr_aer(l,m,n,cw_phase)
  625. if (tmpc1 > 0.0) then
  626. dact = tmpc1*fm(m,n)*raercol(k,lmass,nsav) ! interstitial only
  627. else
  628. dact = 0.0
  629. endif
  630. if (tmpc2 > 0.0) then
  631. dact = dact + tmpc2*fm(m,n)*raercol(km1,lmass,nsav) ! interstitial only
  632. endif
  633. dact = min( dact, 0.99*raercol(k,lmass,nsav) )
  634. raercol(k,lmasscw,nsav) = raercol(k,lmasscw,nsav)+dact
  635. raercol(k,lmass, nsav) = raercol(k,lmass, nsav)-dact
  636. enddo
  637. enddo
  638. enddo
  639. ! 10 continue
  640. endif ! ((tmpc1 > 0.001) .or. (tmpc2 > 0.001))
  641. if(lcldfra(k) < lcldfra_old(k) .and. lcldfra_old(k) > 1.e-20)then ! this line is the "old" criterion
  642. ! go to 20
  643. ! shrinking cloud ......................................................
  644. ! droplet loss in decaying cloud
  645. nsource(i,k,j)=nsource(i,k,j)+qndrop(k)*(lcldfra(k)-lcldfra_old(k))*dtinv
  646. qndrop(k)=qndrop(k)*(1.+lcldfra(k)-lcldfra_old(k))
  647. ! convert activated aerosol to interstitial in decaying cloud
  648. tmpc = (lcldfra(k)-lcldfra_old(k))/lcldfra_old(k)
  649. do n=1,ntype_aer
  650. do m=1,nsize_aer(n)
  651. lnum=numptr_aer(m,n,ai_phase)
  652. lnumcw=numptr_aer(m,n,cw_phase)
  653. if(lnum.gt.0)then
  654. dact=raercol(k,lnumcw,nsav)*tmpc
  655. raercol(k,lnumcw,nsav)=raercol(k,lnumcw,nsav)+dact
  656. raercol(k,lnum,nsav)=raercol(k,lnum,nsav)-dact
  657. endif
  658. do l=1,ncomp(n)
  659. lmass=massptr_aer(l,m,n,ai_phase)
  660. lmasscw=massptr_aer(l,m,n,cw_phase)
  661. dact=raercol(k,lmasscw,nsav)*tmpc
  662. raercol(k,lmasscw,nsav)=raercol(k,lmasscw,nsav)+dact
  663. raercol(k,lmass,nsav)=raercol(k,lmass,nsav)-dact
  664. enddo
  665. enddo
  666. enddo
  667. ! 20 continue
  668. endif
  669. enddo GROW_SHRINK_MAIN_K_LOOP
  670. ! end of k-loop for growing/shrinking cloud calcs ......................
  671. ! ......................................................................
  672. ! start of main k-loop for calc of old cloud activation tendencies ..........
  673. ! this loop does "set up" for the nsubmix loop
  674. !
  675. ! rce-comment
  676. ! changed this part of code to use current cloud fraction (lcldfra) exclusively
  677. OLD_CLOUD_MAIN_K_LOOP: do k=kts,kte
  678. km1=max0(k-1,kts)
  679. kp1=min0(k+1,kde-1)
  680. flux_fullact(k) = 0.0
  681. if(lcldfra(k).gt.0.01)then
  682. ! go to 30
  683. ! old cloud
  684. if(lcldfra(k)-lcldfra(km1).gt.0.01.or.k.eq.kts)then
  685. ! interior cloud
  686. ! cloud base
  687. wdiab=0
  688. wmix=wtke(k) ! spectrum of updrafts
  689. wbar=w(i,k,j) ! spectrum of updrafts
  690. ! wmix=0. ! single updraft
  691. ! wbar=wtke(k) ! single updraft
  692. ! 06-nov-2005 rce - increase wmax from 10 to 50 (deep convective clouds)
  693. wmax=50.
  694. ekd(k)=wtke(k)*dz(k)/sq2pi
  695. alogarg=max(1.e-20,1/lcldfra(k)-1.)
  696. wmin=wbar+wmix*0.25*sq2pi*alog(alogarg)
  697. do n=1,ntype_aer
  698. do m=1,nsize_aer(n)
  699. call loadaer(raercol(1,1,nsav),km1,kms,kme,num_chem, &
  700. cs(k), npv(m,n),dlo_sect(m,n),dhi_sect(m,n), &
  701. maxd_acomp, ncomp(n), &
  702. grid_id, ktau, i, j, m, n, &
  703. numptr_aer(m,n,ai_phase),numptr_aer(m,n,cw_phase), &
  704. dens_aer(1,n), &
  705. massptr_aer(1,m,n,ai_phase), massptr_aer(1,m,n,cw_phase), &
  706. maerosol(1,m,n), maerosolcw(1,m,n), &
  707. maerosol_tot(m,n), maerosol_totcw(m,n), &
  708. naerosol(m,n), naerosolcw(m,n), &
  709. vaerosol(m,n), vaerosolcw(m,n) )
  710. hygro_aer(m,n)=hygro(i,k,j,m,n)
  711. enddo
  712. enddo
  713. ! print *,'old cloud wbar,wmix=',wbar,wmix
  714. call activate(wbar,wmix,wdiab,wmin,wmax,temp(i,k,j),cs(k), &
  715. msectional, maxd_atype, ntype_aer, maxd_asize, nsize_aer, &
  716. naerosol, vaerosol, &
  717. dlo_sect,dhi_sect, sigmag_aer,hygro_aer, &
  718. fn,fs,fm,fluxn,fluxs,fluxm,flux_fullact(k), grid_id, ktau, i, j, k )
  719. ! rce-comment
  720. ! the activation-fraction fluxes (fluxn, fluxm) from subr activate assume that
  721. ! wbar << wmix, which is valid for global-model scale but not mesoscale
  722. ! for wrf-chem application, divide these by flux_fullact to get a
  723. ! "flux-weighted-average" activation fraction, then multiply by (ekd(k)*zs(k))
  724. ! which is the local "turbulent vertical-mixing velocity"
  725. if (k > kts) then
  726. if (flux_fullact(k) > 1.0e-20) then
  727. tmpa = ekd(k)*zs(k)
  728. tmpf = flux_fullact(k)
  729. do n=1,ntype_aer
  730. do m=1,nsize_aer(n)
  731. tmpb = max( fluxn(m,n), 0.0 ) / max( fluxn(m,n), tmpf )
  732. fluxn(m,n) = tmpa*tmpb
  733. tmpb = max( fluxm(m,n), 0.0 ) / max( fluxm(m,n), tmpf )
  734. fluxm(m,n) = tmpa*tmpb
  735. enddo
  736. enddo
  737. else
  738. fluxn(:,:) = 0.0
  739. fluxm(:,:) = 0.0
  740. endif
  741. endif
  742. if(k.gt.kts)then
  743. tmpc = lcldfra(k)-lcldfra(km1)
  744. else
  745. tmpc=lcldfra(k)
  746. endif
  747. ! rce-comment
  748. ! flux of activated mass into layer k (in kg/m2/s)
  749. ! = "actmassflux" = dumc*fluxm*raercol(kp1,lmass)*csbot(k)
  750. ! source of activated mass (in kg/kg/s) = flux divergence
  751. ! = actmassflux/(cs(i,k)*dz(i,k))
  752. ! so need factor of csbot_cscen = csbot(k)/cs(i,k)
  753. ! tmpe=1./(dz(k))
  754. tmpe = csbot_cscen(k)/(dz(k))
  755. fluxntot=0.
  756. do n=1,ntype_aer
  757. do m=1,nsize_aer(n)
  758. fluxn(m,n)=fluxn(m,n)*tmpc
  759. ! fluxs(m,n)=fluxs(m,n)*tmpc
  760. fluxm(m,n)=fluxm(m,n)*tmpc
  761. lnum=numptr_aer(m,n,ai_phase)
  762. fluxntot=fluxntot+fluxn(m,n)*raercol(km1,lnum,nsav)
  763. ! print *,'fn=',fn(m,n),' for m,n=',m,n
  764. ! print *,'old cloud tmpc=',tmpc,' fn=',fn(m,n),' for m,n=',m,n
  765. nact(k,m,n)=nact(k,m,n)+fluxn(m,n)*tmpe
  766. mact(k,m,n)=mact(k,m,n)+fluxm(m,n)*tmpe
  767. enddo
  768. enddo
  769. flux_fullact(k) = flux_fullact(k)*tmpe
  770. nsource(i,k,j)=nsource(i,k,j)+fluxntot*zs(k)
  771. fluxntot=fluxntot*cs(k)
  772. endif
  773. ! 30 continue
  774. else
  775. ! go to 40
  776. ! no cloud
  777. if(qndrop(k).gt.10000.e6)then
  778. print *,'i,k,j,lcldfra,qndrop=',i,k,j,lcldfra(k),qndrop(k)
  779. print *,'cldfra,ql,qi',cldfra(i,k,j),qc(i,k,j),qi(i,k,j)
  780. endif
  781. nsource(i,k,j)=nsource(i,k,j)-qndrop(k)*dtinv
  782. qndrop(k)=0.
  783. ! convert activated aerosol to interstitial in decaying cloud
  784. do n=1,ntype_aer
  785. do m=1,nsize_aer(n)
  786. lnum=numptr_aer(m,n,ai_phase)
  787. lnumcw=numptr_aer(m,n,cw_phase)
  788. if(lnum.gt.0)then
  789. raercol(k,lnum,nsav)=raercol(k,lnum,nsav)+raercol(k,lnumcw,nsav)
  790. raercol(k,lnumcw,nsav)=0.
  791. endif
  792. do l=1,ncomp(n)
  793. lmass=massptr_aer(l,m,n,ai_phase)
  794. lmasscw=massptr_aer(l,m,n,cw_phase)
  795. raercol(k,lmass,nsav)=raercol(k,lmass,nsav)+raercol(k,lmasscw,nsav)
  796. raercol(k,lmasscw,nsav)=0.
  797. enddo
  798. enddo
  799. enddo
  800. ! 40 continue
  801. endif
  802. enddo OLD_CLOUD_MAIN_K_LOOP
  803. ! cycle OVERALL_MAIN_I_LOOP
  804. ! switch nsav, nnew so that nnew is the updated aerosol
  805. ntemp=nsav
  806. nsav=nnew
  807. nnew=ntemp
  808. ! load new droplets in layers above, below clouds
  809. dtmin=dtstep
  810. ekk(kts)=0.0
  811. ! rce-comment -- ekd(k) is eddy-diffusivity at k/k-1 interface
  812. ! want ekk(k) = ekd(k) * (density at k/k-1 interface)
  813. do k=kts+1,kte
  814. ekk(k)=ekd(k)*csbot(k)
  815. enddo
  816. ekk(kte+1)=0.0
  817. do k=kts,kte
  818. ekkp(k)=zn(k)*ekk(k+1)*zs(k+1)
  819. ekkm(k)=zn(k)*ekk(k)*zs(k)
  820. tinv=ekkp(k)+ekkm(k)
  821. if(k.eq.kts)tinv=tinv+surfratemax
  822. if(tinv.gt.1.e-6)then
  823. dtt=1./tinv
  824. dtmin=min(dtmin,dtt)
  825. endif
  826. enddo
  827. dtmix=0.9*dtmin
  828. nsubmix=dtstep/dtmix+1
  829. if(nsubmix>100)then
  830. nsubmix_bnd=100
  831. else
  832. nsubmix_bnd=nsubmix
  833. endif
  834. ! count_submix(nsubmix_bnd)=count_submix(nsubmix_bnd)+1
  835. dtmix=dtstep/nsubmix
  836. fac_srflx = -1.0/(zn(1)*nsubmix)
  837. do k=kts,kte
  838. kp1=min(k+1,kde-1)
  839. km1=max(k-1,1)
  840. if(lcldfra(kp1).gt.0)then
  841. overlapp(k)=min(lcldfra(k)/lcldfra(kp1),1.)
  842. else
  843. overlapp(k)=1.
  844. endif
  845. if(lcldfra(km1).gt.0)then
  846. overlapm(k)=min(lcldfra(k)/lcldfra(km1),1.)
  847. else
  848. overlapm(k)=1.
  849. endif
  850. enddo
  851. ! ......................................................................
  852. ! start of nsubmix-loop for calc of old cloud activation tendencies ....
  853. OLD_CLOUD_NSUBMIX_LOOP: do nsub=1,nsubmix
  854. qndrop_new(kts:kte)=qndrop(kts:kte)
  855. ! switch nsav, nnew so that nsav is the updated aerosol
  856. ntemp=nsav
  857. nsav=nnew
  858. nnew=ntemp
  859. srcn(:)=0.0
  860. do n=1,ntype_aer
  861. do m=1,nsize_aer(n)
  862. lnum=numptr_aer(m,n,ai_phase)
  863. ! update droplet source
  864. ! rce-comment - activation source in layer k involves particles from k-1
  865. ! srcn(kts :kte)=srcn(kts :kte)+nact(kts :kte,m,n)*(raercol(kts:kte ,lnum,nsav))
  866. srcn(kts+1:kte)=srcn(kts+1:kte)+nact(kts+1:kte,m,n)*(raercol(kts:kte-1,lnum,nsav))
  867. ! rce-comment - new formulation for k=kts should be implemented
  868. srcn(kts )=srcn(kts )+nact(kts ,m,n)*(raercol(kts ,lnum,nsav))
  869. enddo
  870. enddo
  871. call explmix(qndrop,srcn,ekkp,ekkm,overlapp,overlapm, &
  872. qndrop_new,surfrate_drop,kms,kme,kts,kte,dtmix,.false.)
  873. do n=1,ntype_aer
  874. do m=1,nsize_aer(n)
  875. lnum=numptr_aer(m,n,ai_phase)
  876. lnumcw=numptr_aer(m,n,cw_phase)
  877. if(lnum>0)then
  878. ! rce-comment - activation source in layer k involves particles from k-1
  879. ! source(kts :kte)= nact(kts :kte,m,n)*(raercol(kts:kte ,lnum,nsav))
  880. source(kts+1:kte)= nact(kts+1:kte,m,n)*(raercol(kts:kte-1,lnum,nsav))
  881. ! rce-comment - new formulation for k=kts should be implemented
  882. source(kts )= nact(kts ,m,n)*(raercol(kts ,lnum,nsav))
  883. call explmix(raercol(1,lnumcw,nnew),source,ekkp,ekkm,overlapp,overlapm, &
  884. raercol(1,lnumcw,nsav),surfrate(lnumcw),kms,kme,kts,kte,dtmix,&
  885. .false.)
  886. call explmix(raercol(1,lnum,nnew),source,ekkp,ekkm,overlapp,overlapm, &
  887. raercol(1,lnum,nsav),surfrate(lnum),kms,kme,kts,kte,dtmix, &
  888. .true.,raercol(1,lnumcw,nsav))
  889. qsrflx(i,j,lnum) = qsrflx(i,j,lnum) + fac_srflx* &
  890. raercol(kts,lnum,nsav)*surfrate(lnum)
  891. qsrflx(i,j,lnumcw) = qsrflx(i,j,lnumcw) + fac_srflx* &
  892. raercol(kts,lnumcw,nsav)*surfrate(lnumcw)
  893. if (icheck_colmass > 0) then
  894. tmpf = dtmix*rhodz(kts)
  895. colmass_sfc(0,m,n,1) = colmass_sfc(0,m,n,1) &
  896. + raercol(kts,lnum ,nsav)*surfrate(lnum )*tmpf
  897. colmass_sfc(0,m,n,2) = colmass_sfc(0,m,n,2) &
  898. + raercol(kts,lnumcw,nsav)*surfrate(lnumcw)*tmpf
  899. endif
  900. endif
  901. do l=1,ncomp(n)
  902. lmass=massptr_aer(l,m,n,ai_phase)
  903. lmasscw=massptr_aer(l,m,n,cw_phase)
  904. ! rce-comment - activation source in layer k involves particles from k-1
  905. ! source(kts :kte)= mact(kts :kte,m,n)*(raercol(kts:kte ,lmass,nsav))
  906. source(kts+1:kte)= mact(kts+1:kte,m,n)*(raercol(kts:kte-1,lmass,nsav))
  907. ! rce-comment - new formulation for k=kts should be implemented
  908. source(kts )= mact(kts ,m,n)*(raercol(kts ,lmass,nsav))
  909. call explmix(raercol(1,lmasscw,nnew),source,ekkp,ekkm,overlapp,overlapm, &
  910. raercol(1,lmasscw,nsav),surfrate(lmasscw),kms,kme,kts,kte,dtmix, &
  911. .false.)
  912. call explmix(raercol(1,lmass,nnew),source,ekkp,ekkm,overlapp,overlapm, &
  913. raercol(1,lmass,nsav),surfrate(lmass),kms,kme,kts,kte,dtmix, &
  914. .true.,raercol(1,lmasscw,nsav))
  915. qsrflx(i,j,lmass) = qsrflx(i,j,lmass) + fac_srflx* &
  916. raercol(kts,lmass,nsav)*surfrate(lmass)
  917. qsrflx(i,j,lmasscw) = qsrflx(i,j,lmasscw) + fac_srflx* &
  918. raercol(kts,lmasscw,nsav)*surfrate(lmasscw)
  919. if (icheck_colmass > 0) then
  920. ! colmass_sfc calculation
  921. ! colmass_bgn/end = bgn/end column burden = sum.over.k.of{ rho(k)*dz(k)*chem(k,l) }
  922. ! colmass_sfc = surface loss over dtstep
  923. ! = sum.over.nsubmix.substeps{ depvel(l)*rho(kts)*chem(kts,l)*dtmix }
  924. ! surfrate(l) = depvel(l)/dz(kts) so need to multiply by dz(kts)
  925. ! for mass, raercol(k,l) = chem(k,l)*1.0e-9, so need to multiply by 1.0e9
  926. tmpf = dtmix*rhodz(kts)*1.0e9
  927. colmass_sfc(l,m,n,1) = colmass_sfc(l,m,n,1) &
  928. + raercol(kts,lmass ,nsav)*surfrate(lmass )*tmpf
  929. colmass_sfc(l,m,n,2) = colmass_sfc(l,m,n,2) &
  930. + raercol(kts,lmasscw,nsav)*surfrate(lmasscw)*tmpf
  931. endif
  932. enddo
  933. lwater=waterptr_aer(m,n) ! aerosol water
  934. if(lwater>0)then
  935. source(:)=0.
  936. call explmix( raercol(1,lwater,nnew),source,ekkp,ekkm,overlapp,overlapm, &
  937. raercol(1,lwater,nsav),surfrate(lwater),kms,kme,kts,kte,dtmix, &
  938. .true.,source)
  939. endif
  940. enddo ! size
  941. enddo ! type
  942. enddo OLD_CLOUD_NSUBMIX_LOOP
  943. ! cycle OVERALL_MAIN_I_LOOP
  944. ! evaporate particles again if no cloud
  945. do k=kts,kte
  946. if(lcldfra(k).eq.0.)then
  947. ! no cloud
  948. qndrop(k)=0.
  949. ! convert activated aerosol to interstitial in decaying cloud
  950. do n=1,ntype_aer
  951. do m=1,nsize_aer(n)
  952. lnum=numptr_aer(m,n,ai_phase)
  953. lnumcw=numptr_aer(m,n,cw_phase)
  954. if(lnum.gt.0)then
  955. raercol(k,lnum,nnew)=raercol(k,lnum,nnew)+raercol(k,lnumcw,nnew)
  956. raercol(k,lnumcw,nnew)=0.
  957. endif
  958. do l=1,ncomp(n)
  959. lmass=massptr_aer(l,m,n,ai_phase)
  960. lmasscw=massptr_aer(l,m,n,cw_phase)
  961. raercol(k,lmass,nnew)=raercol(k,lmass,nnew)+raercol(k,lmasscw,nnew)
  962. raercol(k,lmasscw,nnew)=0.
  963. enddo
  964. enddo
  965. enddo
  966. endif
  967. enddo
  968. ! cycle OVERALL_MAIN_I_LOOP
  969. ! droplet number
  970. do k=kts,kte
  971. ! if(lcldfra(k).gt.0.1)then
  972. ! write(6,'(a,3i5,f12.1)')'i,j,k,qndrop=',i,j,k,qndrop(k)
  973. ! endif
  974. if(qndrop(k).lt.-10.e6.or.qndrop(k).gt.1.e12)then
  975. write(6,'(a,g12.2,a,3i5)')'after qndrop=',qndrop(k),' for i,k,j=',i,k,j
  976. endif
  977. qndrop3d(i,k,j) = max(qndrop(k),1.e-6)
  978. if(qndrop3d(i,k,j).lt.-10.e6.or.qndrop3d(i,k,j).gt.1.E20)then
  979. write(6,'(a,g12.2,a,3i5)')'after qndrop3d=',qndrop3d(i,k,j),' for i,k,j=',i,k,j
  980. endif
  981. if(qc(i,k,j).lt.-1..or.qc(i,k,j).gt.1.)then
  982. write(6,'(a,g12.2,a,3i5)')'qc=',qc(i,k,j),' for i,k,j=',i,k,j
  983. call wrf_error_fatal("1")
  984. endif
  985. if(qi(i,k,j).lt.-1..or.qi(i,k,j).gt.1.)then
  986. write(6,'(a,g12.2,a,3i5)')'qi=',qi(i,k,j),' for i,k,j=',i,k,j
  987. call wrf_error_fatal("1")
  988. endif
  989. if(qv(i,k,j).lt.-1..or.qv(i,k,j).gt.1.)then
  990. write(6,'(a,g12.2,a,3i5)')'qv=',qv(i,k,j),' for i,k,j=',i,k,j
  991. call wrf_error_fatal("1")
  992. endif
  993. cldfra_old(i,k,j) = cldfra(i,k,j)
  994. ! if(k.gt.6.and.k.lt.11)cldfra_old(i,k,j)=1.
  995. enddo
  996. ! cycle OVERALL_MAIN_I_LOOP
  997. ! update chem and convert back to mole/mole
  998. ccn(:,:) = 0.
  999. do n=1,ntype_aer
  1000. do m=1,nsize_aer(n)
  1001. lnum=numptr_aer(m,n,ai_phase)
  1002. lnumcw=numptr_aer(m,n,cw_phase)
  1003. if(lnum.gt.0)then
  1004. ! scale=mwdry*0.001
  1005. scale = 1.
  1006. chem(i,kts:kte,j,lnumcw)= raercol(kts:kte,lnumcw,nnew)*scale
  1007. chem(i,kts:kte,j,lnum)= raercol(kts:kte,lnum,nnew)*scale
  1008. endif
  1009. do l=1,ncomp(n)
  1010. lmass=massptr_aer(l,m,n,ai_phase)
  1011. lmasscw=massptr_aer(l,m,n,cw_phase)
  1012. ! scale = mwdry/mw_aer(l,n)
  1013. scale = 1.e9
  1014. chem(i,kts:kte,j,lmasscw)=raercol(kts:kte,lmasscw,nnew)*scale ! ug/kg
  1015. chem(i,kts:kte,j,lmass)=raercol(kts:kte,lmass,nnew)*scale ! ug/kg
  1016. enddo
  1017. lwater=waterptr_aer(m,n)
  1018. if(lwater>0)chem(i,kts:kte,j,lwater)=raercol(kts:kte,lwater,nnew) ! don't convert units
  1019. do k=kts,kte
  1020. sm=2.*aten*sqrt(aten/(27.*hygro(i,k,j,m,n)*amcube(m,n)))
  1021. do l=1,psat
  1022. arg=argfactor(m,n)*log(sm/super(l))
  1023. if(arg<2)then
  1024. if(arg<-2)then
  1025. ccnfact(l,m,n)=1.e-6 ! convert from #/m3 to #/cm3
  1026. else
  1027. ccnfact(l,m,n)=1.e-6*0.5*ERFC_NUM_RECIPES(arg)
  1028. endif
  1029. else
  1030. ccnfact(l,m,n) = 0.
  1031. endif
  1032. ! ccn concentration as diagnostic
  1033. ! assume same hygroscopicity and ccnfact for cloud-phase and aerosol phase particles
  1034. ccn(k,l)=ccn(k,l)+(raercol(k,lnum,nnew)+raercol(k,lnumcw,nnew))*cs(k)*ccnfact(l,m,n)
  1035. enddo
  1036. enddo
  1037. enddo
  1038. enddo
  1039. do l=1,psat
  1040. !wig, 22-Nov-2006: added vertical bounds to prevent out-of-bounds at top
  1041. if(l.eq.1)ccn1(i,kts:kte,j)=ccn(:,l)
  1042. if(l.eq.2)ccn2(i,kts:kte,j)=ccn(:,l)
  1043. if(l.eq.3)ccn3(i,kts:kte,j)=ccn(:,l)
  1044. if(l.eq.4)ccn4(i,kts:kte,j)=ccn(:,l)
  1045. if(l.eq.5)ccn5(i,kts:kte,j)=ccn(:,l)
  1046. if(l.eq.6)ccn6(i,kts:kte,j)=ccn(:,l)
  1047. end do
  1048. ! mass conservation checking
  1049. if (icheck_colmass > 0) then
  1050. ! calc final column burdens
  1051. do n=1,ntype_aer
  1052. do m=1,nsize_aer(n)
  1053. lnum=numptr_aer(m,n,ai_phase)
  1054. lnumcw=numptr_aer(m,n,cw_phase)
  1055. if(lnum>0)then
  1056. colmass_end(0,m,n,1) = sum( chem(i,kts:kte,j,lnum )*rhodz(kts:kte) )
  1057. colmass_end(0,m,n,2) = sum( chem(i,kts:kte,j,lnumcw)*rhodz(kts:kte) )
  1058. endif
  1059. do l=1,ncomp(n)
  1060. lmass=massptr_aer(l,m,n,ai_phase)
  1061. lmasscw=massptr_aer(l,m,n,cw_phase)
  1062. colmass_end(l,m,n,1) = sum( chem(i,kts:kte,j,lmass )*rhodz(kts:kte) )
  1063. colmass_end(l,m,n,2) = sum( chem(i,kts:kte,j,lmasscw)*rhodz(kts:kte) )
  1064. enddo
  1065. enddo ! size
  1066. enddo ! type
  1067. ! calc burden change errors for each interstitial/activated pair
  1068. do n=1,ntype_aer
  1069. do m=1,nsize_aer(n)
  1070. do l=0,ncomp(n)
  1071. ! tmpa & tmpb = beginning & ending column burden divided by rhodzsum,
  1072. ! = beginning & ending column-mean mixing ratios
  1073. ! tmpc = loss to surface divided by rhodzsum,
  1074. tmpa = ( colmass_bgn(l,m,n,1) + colmass_bgn(l,m,n,2) )/rhodzsum
  1075. tmpb = ( colmass_end(l,m,n,1) + colmass_end(l,m,n,2) )/rhodzsum
  1076. tmpc = ( colmass_sfc(l,m,n,1) + colmass_sfc(l,m,n,2) )/rhodzsum
  1077. ! tmpd = ((final burden) + (sfc loss)) - (initial burden)
  1078. ! = burden change error
  1079. tmpd = (tmpb + tmpc) - tmpa
  1080. tmpe = max( tmpa, 1.0e-20 )
  1081. ! tmpf = (burden change error) / (initial burden)
  1082. if (abs(tmpd) < 1.0e5*tmpe) then
  1083. tmpf = tmpd/tmpe
  1084. else if (tmpf < 0.0) then
  1085. tmpf = -1.0e5
  1086. else
  1087. tmpf = 1.0e5
  1088. end if
  1089. if (abs(tmpf) > abs(colmass_worst(l,m,n))) then
  1090. colmass_worst(l,m,n) = tmpf
  1091. colmass_worst_ij(1,l,m,n) = i
  1092. colmass_worst_ij(2,l,m,n) = j
  1093. endif
  1094. enddo
  1095. enddo ! size
  1096. enddo ! type
  1097. endif ! (icheck_colmass > 0)
  1098. enddo OVERALL_MAIN_I_LOOP ! end of main loop over i
  1099. enddo OVERALL_MAIN_J_LOOP ! end of main loop over j
  1100. ! mass conservation checking
  1101. if (icheck_colmass > 0) then
  1102. if (icheck_colmass >= 100) write(*,'(a)') &
  1103. 'mixactivate colmass worst errors bgn - type, size, comp, err, i, j'
  1104. colmass_maxworst_r = 0.0
  1105. colmass_maxworst_i(:) = -1
  1106. do n=1,ntype_aer
  1107. do m=1,nsize_aer(n)
  1108. do l=0,ncomp(n)
  1109. if (icheck_colmass >= 100) &
  1110. write(*,'(3i3,1p,e10.2,2i4)') n, m, l, &
  1111. colmass_worst(l,m,n), colmass_worst_ij(1:2,l,m,n)
  1112. if (abs(colmass_worst(l,m,n)) > abs(colmass_maxworst_r)) then
  1113. colmass_maxworst_r = colmass_worst(l,m,n)
  1114. colmass_maxworst_i(1) = n
  1115. colmass_maxworst_i(2) = m
  1116. colmass_maxworst_i(3) = l
  1117. end if
  1118. enddo
  1119. enddo ! size
  1120. enddo ! type
  1121. if ((icheck_colmass >= 10) .or. (abs(colmass_maxworst_r) >= 1.0e-6)) &
  1122. write(*,'(a,3i3,1p,e10.2)') 'mixactivate colmass maxworst', &
  1123. colmass_maxworst_i(1:3), colmass_maxworst_r
  1124. endif ! (icheck_colmass > 0)
  1125. return
  1126. end subroutine mixactivate
  1127. !----------------------------------------------------------------------
  1128. !----------------------------------------------------------------------
  1129. subroutine explmix( q, src, ekkp, ekkm, overlapp, overlapm, &
  1130. qold, surfrate, kms, kme, kts, kte, dt, &
  1131. is_unact, qactold )
  1132. ! explicit integration of droplet/aerosol mixing
  1133. ! with source due to activation/nucleation
  1134. implicit none
  1135. integer, intent(in) :: kms,kme ! number of levels for array definition
  1136. integer, intent(in) :: kts,kte ! number of levels for looping
  1137. real, intent(inout) :: q(kms:kme) ! mixing ratio to be updated
  1138. real, intent(in) :: qold(kms:kme) ! mixing ratio from previous time step
  1139. real, intent(in) :: src(kms:kme) ! source due to activation/nucleation (/s)
  1140. real, intent(in) :: ekkp(kms:kme) ! zn*zs*density*diffusivity (kg/m3 m2/s) at interface
  1141. ! below layer k (k,k+1 interface)
  1142. real, intent(in) :: ekkm(kms:kme) ! zn*zs*density*diffusivity (kg/m3 m2/s) at interface
  1143. ! above layer k (k,k+1 interface)
  1144. real, intent(in) :: overlapp(kms:kme) ! cloud overlap below
  1145. real, intent(in) :: overlapm(kms:kme) ! cloud overlap above
  1146. real, intent(in) :: surfrate ! surface exchange rate (/s)
  1147. real, intent(in) :: dt ! time step (s)
  1148. logical, intent(in) :: is_unact ! true if this is an unactivated species
  1149. real, intent(in),optional :: qactold(kms:kme)
  1150. ! mixing ratio of ACTIVATED species from previous step
  1151. ! *** this should only be present
  1152. ! if the current species is unactivated number/sfc/mass
  1153. integer k,kp1,km1
  1154. if ( is_unact ) then
  1155. ! the qactold*(1-overlap) terms are resuspension of activated material
  1156. do k=kts,kte
  1157. kp1=min(k+1,kte)
  1158. km1=max(k-1,kts)
  1159. q(k) = qold(k) + dt*( - src(k) + ekkp(k)*(qold(kp1) - qold(k) + &
  1160. qactold(kp1)*(1.0-overlapp(k))) &
  1161. + ekkm(k)*(qold(km1) - qold(k) + &
  1162. qactold(km1)*(1.0-overlapm(k))) )
  1163. ! if(q(k)<-1.e-30)then ! force to non-negative
  1164. ! print *,'q=',q(k),' in explmix'
  1165. q(k)=max(q(k),0.)
  1166. ! endif
  1167. end do
  1168. else
  1169. do k=kts,kte
  1170. kp1=min(k+1,kte)
  1171. km1=max(k-1,kts)
  1172. q(k) = qold(k) + dt*(src(k) + ekkp(k)*(overlapp(k)*qold(kp1)-qold(k)) + &
  1173. ekkm(k)*(overlapm(k)*qold(km1)-qold(k)) )
  1174. ! if(q(k)<-1.e-30)then ! force to non-negative
  1175. ! print *,'q=',q(k),' in explmix'
  1176. q(k)=max(q(k),0.)
  1177. ! endif
  1178. end do
  1179. end if
  1180. ! dry deposition loss at base of lowest layer
  1181. q(kts)=q(kts)-surfrate*qold(kts)*dt
  1182. ! if(q(kts)<-1.e-30)then ! force to non-negative
  1183. ! print *,'q=',q(kts),' in explmix'
  1184. q(kts)=max(q(kts),0.)
  1185. ! endif
  1186. return
  1187. end subroutine explmix
  1188. !----------------------------------------------------------------------
  1189. !----------------------------------------------------------------------
  1190. ! 06-nov-2005 rce - grid_id & ktau added to arg list
  1191. subroutine activate(wbar, sigw, wdiab, wminf, wmaxf, tair, rhoair, &
  1192. msectional, maxd_atype, ntype_aer, maxd_asize, nsize_aer, &
  1193. na, volc, dlo_sect,dhi_sect,sigman, hygro, &
  1194. fn, fs, fm, fluxn, fluxs, fluxm, flux_fullact, &
  1195. grid_id, ktau, ii, jj, kk )
  1196. ! calculates number, surface, and mass fraction of aerosols activated as CCN
  1197. ! calculates flux of cloud droplets, surface area, and aerosol mass into cloud
  1198. ! assumes an internal mixture within each of aerosol mode.
  1199. ! A sectional treatment within each type is assumed if ntype_aer >7.
  1200. ! A gaussiam spectrum of updrafts can be treated.
  1201. ! mks units
  1202. ! Abdul-Razzak and Ghan, A parameterization of aerosol activation.
  1203. ! 2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844.
  1204. USE module_model_constants, only: g,rhowater, xlv, cp, rvovrd, r_d, r_v, &
  1205. mwdry,svp1,svp2,svp3,ep_2
  1206. implicit none
  1207. ! input
  1208. integer,intent(in) :: maxd_atype ! dimension of types
  1209. integer,intent(in) :: maxd_asize ! dimension of sizes
  1210. integer,intent(in) :: ntype_aer ! number of types
  1211. integer,intent(in) :: nsize_aer(maxd_atype) ! number of sizes for type
  1212. integer,intent(in) :: msectional ! 1 for sectional, 0 for modal
  1213. integer,intent(in) :: grid_id ! WRF grid%id
  1214. integer,intent(in) :: ktau ! WRF time step count
  1215. integer,intent(in) :: ii, jj, kk ! i,j,k of current grid cell
  1216. real,intent(in) :: wbar ! grid cell mean vertical velocity (m/s)
  1217. real,intent(in) :: sigw ! subgrid standard deviation of vertical vel (m/s)
  1218. real,intent(in) :: wdiab ! diabatic vertical velocity (0 if adiabatic)
  1219. real,intent(in) :: wminf ! minimum updraft velocity for integration (m/s)
  1220. real,intent(in) :: wmaxf ! maximum updraft velocity for integration (m/s)
  1221. real,intent(in) :: tair ! air temperature (K)
  1222. real,intent(in) :: rhoair ! air density (kg/m3)
  1223. real,intent(in) :: na(maxd_asize,maxd_atype) ! aerosol number concentration (/m3)
  1224. real,intent(in) :: sigman(maxd_asize,maxd_atype) ! geometric standard deviation of aerosol size distribution
  1225. real,intent(in) :: hygro(maxd_asize,maxd_atype) ! bulk hygroscopicity of aerosol mode
  1226. real,intent(in) :: volc(maxd_asize,maxd_atype) ! total aerosol volume concentration (m3/m3)
  1227. real,intent(in) :: dlo_sect( maxd_asize, maxd_atype ), & ! minimum size of section (cm)
  1228. dhi_sect( maxd_asize, maxd_atype ) ! maximum size of section (cm)
  1229. ! output
  1230. real,intent(inout) :: fn(maxd_asize,maxd_atype) ! number fraction of aerosols activated
  1231. real,intent(inout) :: fs(maxd_asize,maxd_atype) ! surface fraction of aerosols activated
  1232. real,intent(inout) :: fm(maxd_asize,maxd_atype) ! mass fraction of aerosols activated
  1233. real,intent(inout) :: fluxn(maxd_asize,maxd_atype) ! flux of activated aerosol number fraction into cloud (m/s)
  1234. real,intent(inout) :: fluxs(maxd_asize,maxd_atype) ! flux of activated aerosol surface fraction (m/s)
  1235. real,intent(inout) :: fluxm(maxd_asize,maxd_atype) ! flux of activated aerosol mass fraction into cloud (m/s)
  1236. real,intent(inout) :: flux_fullact ! flux when activation fraction = 100% (m/s)
  1237. ! local
  1238. !!$ external erf,erfc
  1239. !!$ real erf,erfc
  1240. ! external qsat_water
  1241. integer, parameter:: nx=200
  1242. integer iquasisect_option, isectional
  1243. real integ,integf
  1244. real, parameter :: surften = 0.076 ! surface tension of water w/respect to air (N/m)
  1245. real, parameter :: p0 = 1013.25e2 ! reference pressure (Pa)
  1246. real, parameter :: t0 = 273.15 ! reference temperature (K)
  1247. real ylo(maxd_asize,maxd_atype),yhi(maxd_asize,maxd_atype) ! 1-particle volume at section interfaces
  1248. real ymean(maxd_asize,maxd_atype) ! 1-particle volume at r=rmean
  1249. real ycut, lnycut, betayy, betayy2, gammayy, phiyy
  1250. real surfc(maxd_asize,maxd_atype) ! surface concentration (m2/m3)
  1251. real sign(maxd_asize,maxd_atype) ! geometric standard deviation of size distribution
  1252. real alnsign(maxd_asize,maxd_atype) ! natl log of geometric standard dev of aerosol
  1253. real am(maxd_asize,maxd_atype) ! number mode radius of dry aerosol (m)
  1254. real lnhygro(maxd_asize,maxd_atype) ! ln(b)
  1255. real f1(maxd_asize,maxd_atype) ! array to hold parameter for maxsat
  1256. real pres ! pressure (Pa)
  1257. real path ! mean free path (m)
  1258. real diff ! diffusivity (m2/s)
  1259. real conduct ! thermal conductivity (Joule/m/sec/deg)
  1260. real diff0,conduct0
  1261. real es ! saturation vapor pressure
  1262. real qs ! water vapor saturation mixing ratio
  1263. real dqsdt ! change in qs with temperature
  1264. real dqsdp ! change in qs with pressure
  1265. real gg ! thermodynamic function (m2/s)
  1266. real sqrtg ! sqrt(gg)
  1267. real sm(maxd_asize,maxd_atype) ! critical supersaturation for number mode radius
  1268. real lnsm(maxd_asize,maxd_atype) ! ln( sm )
  1269. real zeta, eta(maxd_asize,maxd_atype)
  1270. real lnsmax ! ln(smax)
  1271. real alpha
  1272. real gamma
  1273. real beta
  1274. real gaus
  1275. logical :: top ! true if cloud top, false if cloud base or new cloud
  1276. real asub(maxd_asize,maxd_atype),bsub(maxd_asize,maxd_atype) ! coefficients of submode size distribution N=a+bx
  1277. real totn(maxd_atype) ! total aerosol number concentration
  1278. real aten ! surface tension parameter
  1279. real gmrad(maxd_atype) ! geometric mean radius
  1280. real gmradsq(maxd_atype) ! geometric mean of radius squared
  1281. real gmlnsig(maxd_atype) ! geometric standard deviation
  1282. real gmsm(maxd_atype) ! critical supersaturation at radius gmrad
  1283. real sumflxn(maxd_asize,maxd_atype)
  1284. real sumflxs(maxd_asize,maxd_atype)
  1285. real sumflxm(maxd_asize,maxd_atype)
  1286. real sumflx_fullact
  1287. real sumfn(maxd_asize,maxd_atype)
  1288. real sumfs(maxd_asize,maxd_atype)
  1289. real sumfm(maxd_asize,maxd_atype)
  1290. real sumns(maxd_atype)
  1291. real fnold(maxd_asize,maxd_atype) ! number fraction activated
  1292. real fsold(maxd_asize,maxd_atype) ! surface fraction activated
  1293. real fmold(maxd_asize,maxd_atype) ! mass fraction activated
  1294. real wold,gold
  1295. real alogten,alog2,alog3,alogaten
  1296. real alogam
  1297. real rlo(maxd_asize,maxd_atype), rhi(maxd_asize,maxd_atype)
  1298. real rmean(maxd_asize,maxd_atype)
  1299. ! mean radius (m) for the section (not used with modal)
  1300. ! calculated from current volume & number
  1301. real ccc
  1302. real dumaa,dumbb
  1303. real wmin,wmax,w,dw,dwmax,dwmin,wnuc,dwnew,wb
  1304. real dfmin,dfmax,fnew,fold,fnmin,fnbar,fsbar,fmbar
  1305. real alw,sqrtalw
  1306. real smax
  1307. real x,arg
  1308. real xmincoeff,xcut
  1309. real z,z1,z2,wf1,wf2,zf1,zf2,gf1,gf2,gf
  1310. real etafactor1,etafactor2(maxd_asize,maxd_atype),etafactor2max
  1311. integer m,n,nw,nwmax
  1312. ! numerical integration parameters
  1313. real, parameter :: eps = 0.3
  1314. real, parameter :: fmax = 0.99
  1315. real, parameter :: sds = 3.
  1316. ! mathematical constants
  1317. real third, twothird, sixth, zero, one, two, three
  1318. real, parameter :: sq2 = 1.4142135624
  1319. real, parameter :: sqpi = 1.7724538509
  1320. real, parameter :: pi = 3.1415926536
  1321. ! integer, save :: ndist(nx) ! accumulates frequency distribution of integration bins required
  1322. ! data ndist/nx*0/
  1323. ! for nsize_aer>7, a sectional approach is used and isectional = iquasisect_option
  1324. ! activation fractions (fn,fs,fm) are computed as follows
  1325. ! iquasisect_option = 1,3 - each section treated as a narrow lognormal
  1326. ! iquasisect_option = 2,4 - within-section dn/dx = a + b*x, x = ln(r)
  1327. ! smax is computed as follows (when explicit activation is OFF)
  1328. ! iquasisect_option = 1,2 - razzak-ghan modal parameterization with
  1329. ! single mode having same ntot, dgnum, sigmag as the combined sections
  1330. ! iquasisect_option = 3,4 - razzak-ghan sectional parameterization
  1331. ! for nsize_aer=<9, a modal approach is used and isectional = 0
  1332. ! rce 08-jul-2005
  1333. ! if either (na(n,m) < nsmall) or (volc(n,m) < vsmall)
  1334. ! then treat bin/mode (n,m) as being empty, and set its fn/fs/fm=0.0
  1335. ! (for single precision, gradual underflow starts around 1.0e-38,
  1336. ! and strange things can happen when in that region)
  1337. real, parameter :: nsmall = 1.0e-20 ! aer number conc in #/m3
  1338. real, parameter :: vsmall = 1.0e-37 ! aer volume conc in m3/m3
  1339. logical bin_is_empty(maxd_asize,maxd_atype), all_bins_empty
  1340. logical bin_is_narrow(maxd_asize,maxd_atype)
  1341. integer idiagaa, ipass_nwloop
  1342. integer idiag_dndy_neg, idiag_fnsm_prob
  1343. ! The flag for cloud top is no longer used so set it to false. This is an
  1344. ! antiquated feature related to radiation enhancing mass fluxes at cloud
  1345. ! top. It is currently, as of Feb. 2009, set to false in the CAM version
  1346. ! as well.
  1347. top = .false.
  1348. !.......................................................................
  1349. !
  1350. ! start calc. of modal or sectional activation properties (start of section 1)
  1351. !
  1352. !.......................................................................
  1353. idiag_dndy_neg = 1 ! set this to 0 to turn off
  1354. ! warnings about dn/dy < 0
  1355. idiag_fnsm_prob = 1 ! set this to 0 to turn off
  1356. ! warnings about fn/fs/fm misbehavior
  1357. iquasisect_option = 2
  1358. if(msectional.gt.0)then
  1359. isectional = iquasisect_option
  1360. else
  1361. isectional = 0
  1362. endif
  1363. do n=1,ntype_aer
  1364. ! print *,'ntype_aer,n,nsize_aer(n)=',ntype_aer,n,nsize_aer(n)
  1365. if(ntype_aer.eq.1.and.nsize_aer(n).eq.1.and.na(1,1).lt.1.e-20)then
  1366. fn(1,1)=0.
  1367. fs(1,1)=0.
  1368. fm(1,1)=0.
  1369. fluxn(1,1)=0.
  1370. fluxs(1,1)=0.
  1371. fluxm(1,1)=0.
  1372. flux_fullact=0.
  1373. return
  1374. endif
  1375. enddo
  1376. zero = 0.0
  1377. one = 1.0
  1378. two = 2.0
  1379. three = 3.0
  1380. third = 1.0/3.0
  1381. twothird = 2.0/3.0 !wig, 1-Mar-2009: Corrected value from 2/6
  1382. sixth = 1.0/6.0
  1383. pres=r_d*rhoair*tair
  1384. diff0=0.211e-4*(p0/pres)*(tair/t0)**1.94
  1385. conduct0=(5.69+0.017*(tair-t0))*4.186e2*1.e-5 ! convert to J/m/s/deg
  1386. es=1000.*svp1*exp( svp2*(tair-t0)/(tair-svp3) )
  1387. qs=ep_2*es/(pres-es)
  1388. dqsdt=xlv/(r_v*tair*tair)*qs
  1389. alpha=g*(xlv/(cp*r_v*tair*tair)-1./(r_d*tair))
  1390. gamma=(1+xlv/cp*dqsdt)/(rhoair*qs)
  1391. gg=1./(rhowater/(diff0*rhoair*qs)+xlv*rhowater/(conduct0*tair)*(xlv/(r_v*tair)-1.))
  1392. sqrtg=sqrt(gg)
  1393. beta=4.*pi*rhowater*gg*gamma
  1394. aten=2.*surften/(r_v*tair*rhowater)
  1395. alogaten=log(aten)
  1396. alog2=log(two)
  1397. alog3=log(three)
  1398. ccc=4.*pi*third
  1399. etafactor2max=1.e10/(alpha*wmaxf)**1.5 ! this should make eta big if na is very small.
  1400. all_bins_empty = .true.
  1401. do n=1,ntype_aer
  1402. totn(n)=0.
  1403. gmrad(n)=0.
  1404. gmradsq(n)=0.
  1405. sumns(n)=0.
  1406. do m=1,nsize_aer(n)
  1407. alnsign(m,n)=log(sigman(m,n))
  1408. ! internal mixture of aerosols
  1409. bin_is_empty(m,n) = .true.
  1410. if (volc(m,n).gt.vsmall .and. na(m,n).gt.nsmall) then
  1411. bin_is_empty(m,n) = .false.
  1412. all_bins_empty = .false.
  1413. lnhygro(m,n)=log(hygro(m,n))
  1414. ! number mode radius (m,n)
  1415. ! write(6,*)'alnsign,volc,na=',alnsign(m,n),volc(m,n),na(m,n)
  1416. am(m,n)=exp(-1.5*alnsign(m,n)*alnsign(m,n))* &
  1417. (3.*volc(m,n)/(4.*pi*na(m,n)))**third
  1418. if (isectional .gt. 0) then
  1419. ! sectional model.
  1420. ! need to use bulk properties because parameterization doesn't
  1421. ! work well for narrow bins.
  1422. totn(n)=totn(n)+na(m,n)
  1423. alogam=log(am(m,n))
  1424. gmrad(n)=gmrad(n)+na(m,n)*alogam
  1425. gmradsq(n)=gmradsq(n)+na(m,n)*alogam*alogam
  1426. endif
  1427. etafactor2(m,n)=1./(na(m,n)*beta*sqrtg)
  1428. if(hygro(m,n).gt.1.e-10)then
  1429. sm(m,n)=2.*aten/(3.*am(m,n))*sqrt(aten/(3.*hygro(m,n)*am(m,n)))
  1430. else
  1431. sm(m,n)=100.
  1432. endif
  1433. ! write(6,*)'sm,hygro,am=',sm(m,n),hygro(m,n),am(m,n)
  1434. else
  1435. sm(m,n)=1.
  1436. etafactor2(m,n)=etafactor2max ! this should make eta big if na is very small.
  1437. endif
  1438. lnsm(m,n)=log(sm(m,n))
  1439. if ((isectional .eq. 3) .or. (isectional .eq. 4)) then
  1440. sumns(n)=sumns(n)+na(m,n)/sm(m,n)**twothird
  1441. endif
  1442. ! write(6,'(a,i4,6g12.2)')'m,na,am,hygro,lnhygro,sm,lnsm=',m,na(m,n),am(m,n),hygro(m,n),lnhygro(m,n),sm(m,n),lnsm(m,n)
  1443. end do ! size
  1444. end do ! type
  1445. ! if all bins are empty, set all activation fractions to zero and exit
  1446. if ( all_bins_empty ) then
  1447. do n=1,ntype_aer
  1448. do m=1,nsize_aer(n)
  1449. fluxn(m,n)=0.
  1450. fn(m,n)=0.
  1451. fluxs(m,n)=0.
  1452. fs(m,n)=0.
  1453. fluxm(m,n)=0.
  1454. fm(m,n)=0.
  1455. end do
  1456. end do
  1457. flux_fullact=0.
  1458. return
  1459. endif
  1460. if (isectional .le. 0) then
  1461. ! Initialize maxsat at this cell and timestep for the
  1462. ! modal setup (the sectional case is handled below).
  1463. call maxsat_init(maxd_atype, ntype_aer, &
  1464. maxd_asize, nsize_aer, alnsign, f1)
  1465. goto 30000
  1466. end if
  1467. do n=1,ntype_aer
  1468. !wig 19-Oct-2006: Add zero trap based May 2006 e-mail from
  1469. !Ghan. Transport can clear out a cell leading to
  1470. !inconsistencies with the mass.
  1471. gmrad(n)=gmrad(n)/max(totn(n),1e-20)
  1472. gmlnsig=gmradsq(n)/totn(n)-gmrad(n)*gmrad(n) ! [ln(sigmag)]**2
  1473. gmlnsig(n)=sqrt( max( 1.e-4, gmlnsig(n) ) )
  1474. gmrad(n)=exp(gmrad(n))
  1475. if ((isectional .eq. 3) .or. (isectional .eq. 4)) then
  1476. gmsm(n)=totn(n)/sumns(n)
  1477. gmsm(n)=gmsm(n)*gmsm(n)*gmsm(n)
  1478. gmsm(n)=sqrt(gmsm(n))
  1479. else
  1480. ! gmsm(n)=2.*aten/(3.*gmrad(n))*sqrt(aten/(3.*hygro(1,n)*gmrad(n)))
  1481. gmsm(n)=2.*aten/(3.*gmrad(n))*sqrt(aten/(3.*hygro(nsize_aer(n),n)*gmrad(n)))
  1482. endif
  1483. enddo
  1484. ! Initialize maxsat at this cell and timestep for the
  1485. ! sectional setup (the modal case is handled above)...
  1486. call maxsat_init(maxd_atype, ntype_aer, &
  1487. maxd_asize, (/1/), gmlnsig, f1)
  1488. !.......................................................................
  1489. ! calculate sectional "sub-bin" size distribution
  1490. !
  1491. ! dn/dy = nt*( a + b*y ) for ylo < y < yhi
  1492. !
  1493. ! nt = na(m,n) = number mixing ratio of the bin
  1494. ! y = v/vhi
  1495. ! v = (4pi/3)*r**3 = particle volume
  1496. ! vhi = v at r=rhi (upper bin boundary)
  1497. ! ylo = y at lower bin boundary = vlo/vhi = (rlo/rhi)**3
  1498. ! yhi = y at upper bin boundary = 1.0
  1499. !
  1500. ! dv/dy = v * dn/dy = nt*vhi*( a*y + b*y*y )
  1501. !
  1502. !.......................................................................
  1503. ! 02-may-2006 - this dn/dy replaces the previous
  1504. ! dn/dx = a + b*x where l = ln(r)
  1505. ! the old dn/dx was overly complicated for cases of rmean near rlo or rhi
  1506. ! the new dn/dy is consistent with that used in the movesect routine,
  1507. ! which does continuous growth by condensation and aqueous chemistry
  1508. !.......................................................................
  1509. do 25002 n = 1,ntype_aer
  1510. do 25000 m = 1,nsize_aer(n)
  1511. ! convert from diameter in cm to radius in m
  1512. rlo(m,n) = 0.5*0.01*dlo_sect(m,n)
  1513. rhi(m,n) = 0.5*0.01*dhi_sect(m,n)
  1514. ylo(m,n) = (rlo(m,n)/rhi(m,n))**3
  1515. yhi(m,n) = 1.0
  1516. ! 04-nov-2005 - extremely narrow bins will be treated using 0/1 activation
  1517. ! this is to avoid potential numerical problems
  1518. bin_is_narrow(m,n) = .false.
  1519. if ((rhi(m,n)/rlo(m,n)) .le. 1.01) bin_is_narrow(m,n) = .true.
  1520. ! rmean is mass mean radius for the bin; xmean = log(rmean)
  1521. ! just use section midpoint if bin is empty
  1522. if ( bin_is_empty(m,n) ) then
  1523. rmean(m,n) = sqrt(rlo(m,n)*rhi(m,n))
  1524. ymean(m,n) = (rmean(m,n)/rhi(m,n))**3
  1525. goto 25000
  1526. end if
  1527. rmean(m,n) = (volc(m,n)/(ccc*na(m,n)))**third
  1528. rmean(m,n) = max( rlo(m,n), min( rhi(m,n), rmean(m,n) ) )
  1529. ymean(m,n) = (rmean(m,n)/rhi(m,n))**3
  1530. if ( bin_is_narrow(m,n) ) goto 25000
  1531. ! if rmean is extremely close to either rlo or rhi,
  1532. ! treat the bin as extremely narrow
  1533. if ((rhi(m,n)/rmean(m,n)) .le. 1.01) then
  1534. bin_is_narrow(m,n) = .true.
  1535. rlo(m,n) = min( rmean(m,n), (rhi(m,n)/1.01) )
  1536. ylo(m,n) = (rlo(m,n)/rhi(m,n))**3
  1537. goto 25000
  1538. else if ((rmean(m,n)/rlo(m,n)) .le. 1.01) then
  1539. bin_is_narrow(m,n) = .true.
  1540. rhi(m,n) = max( rmean(m,n), (rlo(m,n)*1.01) )
  1541. ylo(m,n) = (rlo(m,n)/rhi(m,n))**3
  1542. ymean(m,n) = (rmean(m,n)/rhi(m,n))**3
  1543. goto 25000
  1544. endif
  1545. ! if rmean is somewhat close to either rlo or rhi, then dn/dy will be
  1546. ! negative near the upper or lower bin boundary
  1547. ! in these cases, assume that all the particles are in a subset of the full bin,
  1548. ! and adjust rlo or rhi so that rmean will be near the center of this subset
  1549. ! note that the bin is made narrower LOCALLY/TEMPORARILY,
  1550. ! just for the purposes of the activation calculation
  1551. gammayy = (ymean(m,n)-ylo(m,n)) / (yhi(m,n)-ylo(m,n))
  1552. if (gammayy .lt. 0.34) then
  1553. dumaa = ylo(m,n) + (yhi(m,n)-ylo(m,n))*(gammayy/0.34)
  1554. rhi(m,n) = rhi(m,n)*(dumaa**third)
  1555. ylo(m,n) = (rlo(m,n)/rhi(m,n))**3
  1556. ymean(m,n) = (rmean(m,n)/rhi(m,n))**3
  1557. else if (gammayy .ge. 0.66) then
  1558. dumaa = ylo(m,n) + (yhi(m,n)-ylo(m,n))*((gammayy-0.66)/0.34)
  1559. ylo(m,n) = dumaa
  1560. rlo(m,n) = rhi(m,n)*(dumaa**third)
  1561. end if
  1562. if ((rhi(m,n)/rlo(m,n)) .le. 1.01) then
  1563. bin_is_narrow(m,n) = .true.
  1564. goto 25000
  1565. end if
  1566. betayy = ylo(m,n)/yhi(m,n)
  1567. betayy2 = betayy*betayy
  1568. bsub(m,n) = (12.0*ymean(m,n) - 6.0*(1.0+betayy)) / &
  1569. (4.0*(1.0-betayy2*betayy) - 3.0*(1.0-betayy2)*(1.0+betayy))
  1570. asub(m,n) = (1.0 - bsub(m,n)*(1.0-betayy2)*0.5) / (1.0-betayy)
  1571. if ( asub(m,n)+bsub(m,n)*ylo(m,n) .lt. 0. ) then
  1572. if (idiag_dndy_neg .gt. 0) then
  1573. print *,'dndy<0 at lower boundary'
  1574. print *,'n,m=',n,m
  1575. print *,'na=',na(m,n),' volc=',volc(m,n)
  1576. print *,'volc/(na*pi*4/3)=', (volc(m,n)/(na(m,n)*ccc))
  1577. print *,'rlo(m,n),rhi(m,n)=',rlo(m,n),rhi(m,n)
  1578. print *,'dlo_sect/2,dhi_sect/2=', &
  1579. (0.005*dlo_sect(m,n)),(0.005*dhi_sect(m,n))
  1580. print *,'asub,bsub,ylo,yhi=',asub(m,n),bsub(m,n),ylo(m,n),yhi(m,n)
  1581. print *,'asub+bsub*ylo=', &
  1582. (asub(m,n)+bsub(m,n)*ylo(m,n))
  1583. print *,'subr activate error 11 - i,j,k =', ii, jj, kk
  1584. endif
  1585. endif
  1586. if ( asub(m,n)+bsub(m,n)*yhi(m,n) .lt. 0. ) then
  1587. if (idiag_dndy_neg .gt. 0) then
  1588. print *,'dndy<0 at upper boundary'
  1589. print *,'n,m=',n,m
  1590. print *,'na=',na(m,n),' volc=',volc(m,n)
  1591. print *,'volc/(na*pi*4/3)=', (volc(m,n)/(na(m,n)*ccc))
  1592. print *,'rlo(m,n),rhi(m,n)=',rlo(m,n),rhi(m,n)
  1593. print *,'dlo_sect/2,dhi_sect/2=', &
  1594. (0.005*dlo_sect(m,n)),(0.005*dhi_sect(m,n))
  1595. print *,'asub,bsub,ylo,yhi=',asub(m,n),bsub(m,n),ylo(m,n),yhi(m,n)
  1596. print *,'asub+bsub*yhi=', &
  1597. (asub(m,n)+bsub(m,n)*yhi(m,n))
  1598. print *,'subr activate error 12 - i,j,k =', ii, jj, kk
  1599. endif
  1600. endif
  1601. 25000 continue ! m=1,nsize_aer(n)
  1602. 25002 continue ! n=1,ntype_aer
  1603. 30000 continue
  1604. !.......................................................................
  1605. !
  1606. ! end calc. of modal or sectional activation properties (end of section 1)
  1607. !
  1608. !.......................................................................
  1609. ! sjg 7-16-98 upward
  1610. ! print *,'wbar,sigw=',wbar,sigw
  1611. if(sigw.le.1.e-5) goto 50000
  1612. !.......................................................................
  1613. !
  1614. ! start calc. of activation fractions/fluxes
  1615. ! for spectrum of updrafts (start of section 2)
  1616. !
  1617. !.......................................................................
  1618. ipass_nwloop = 1
  1619. idiagaa = 0
  1620. ! 06-nov-2005 rce - set idiagaa=1 for testing/debugging
  1621. ! if ((grid_id.eq.1) .and. (ktau.eq.167) .and. &
  1622. ! (ii.eq.24) .and. (jj.eq. 1) .and. (kk.eq.14)) idiagaa = 1
  1623. 40000 continue
  1624. if(top)then
  1625. wmax=0.
  1626. wmin=min(zero,-wdiab)
  1627. else
  1628. wmax=min(wmaxf,wbar+sds*sigw)
  1629. wmin=max(wminf,-wdiab)
  1630. endif
  1631. wmin=max(wmin,wbar-sds*sigw)
  1632. w=wmin
  1633. dwmax=eps*sigw
  1634. dw=dwmax
  1635. dfmax=0.2
  1636. dfmin=0.1
  1637. if(wmax.le.w)then
  1638. do n=1,ntype_aer
  1639. do m=1,nsize_aer(n)
  1640. fluxn(m,n)=0.
  1641. fn(m,n)=0.
  1642. fluxs(m,n)=0.
  1643. fs(m,n)=0.
  1644. fluxm(m,n)=0.
  1645. fm(m,n)=0.
  1646. end do
  1647. end do
  1648. flux_fullact=0.
  1649. return
  1650. endif
  1651. do n=1,ntype_aer
  1652. do m=1,nsize_aer(n)
  1653. sumflxn(m,n)=0.
  1654. sumfn(m,n)=0.
  1655. fnold(m,n)=0.
  1656. sumflxs(m,n)=0.
  1657. sumfs(m,n)=0.
  1658. fsold(m,n)=0.
  1659. sumflxm(m,n)=0.
  1660. sumfm(m,n)=0.
  1661. fmold(m,n)=0.
  1662. enddo
  1663. enddo
  1664. sumflx_fullact=0.
  1665. fold=0
  1666. gold=0
  1667. ! 06-nov-2005 rce - set wold=w here
  1668. ! wold=0
  1669. wold=w
  1670. ! 06-nov-2005 rce - define nwmax; calc dwmin from nwmax
  1671. nwmax = 200
  1672. ! dwmin = min( dwmax, 0.01 )
  1673. dwmin = (wmax - wmin)/(nwmax-1)
  1674. dwmin = min( dwmax, dwmin )
  1675. dwmin = max( 0.01, dwmin )
  1676. !
  1677. ! loop over updrafts, incrementing sums as you go
  1678. ! the "200" is (arbitrary) upper limit for number of updrafts
  1679. ! if integration finishes before this, OK; otherwise, ERROR
  1680. !
  1681. if (idiagaa.gt.0) then
  1682. write(*,94700) ktau, grid_id, ii, jj, kk, nwmax
  1683. write(*,94710) 'wbar,sigw,wdiab=', wbar, sigw, wdiab
  1684. write(*,94710) 'wmin,wmax,dwmin,dwmax=', wmin, wmax, dwmin, dwmax
  1685. write(*,94720) -1, w, wold, dw
  1686. end if
  1687. 94700 format( / 'activate 47000 - ktau,id,ii,jj,kk,nwmax=', 6i5 )
  1688. 94710 format( 'activate 47000 - ', a, 6(1x,f11.5) )
  1689. 94720 format( 'activate 47000 - nw,w,wold,dw=', i5, 3(1x,f11.5) )
  1690. do 47000 nw = 1, nwmax
  1691. 41000 wnuc=w+wdiab
  1692. if (idiagaa.gt.0) write(*,94720) nw, w, wold, dw
  1693. ! write(6,*)'wnuc=',wnuc
  1694. alw=alpha*wnuc
  1695. sqrtalw=sqrt(alw)
  1696. zeta=2.*sqrtalw*aten/(3.*sqrtg)
  1697. etafactor1=2.*alw*sqrtalw
  1698. if (isectional .gt. 0) then
  1699. ! sectional model.
  1700. ! use bulk properties
  1701. do n=1,ntype_aer
  1702. if(totn(n).gt.1.e-10)then
  1703. eta(1,n)=etafactor1/(totn(n)*beta*sqrtg)
  1704. else
  1705. eta(1,n)=1.e10
  1706. endif
  1707. enddo
  1708. call maxsat(zeta,eta,maxd_atype,ntype_aer, &
  1709. maxd_asize,(/1/),gmsm,gmlnsig,f1,smax)
  1710. lnsmax=log(smax)
  1711. x=2*(log(gmsm(1))-lnsmax)/(3*sq2*gmlnsig(1))
  1712. fnew=0.5*(1.-ERF_ALT(x))
  1713. else
  1714. do n=1,ntype_aer
  1715. do m=1,nsize_aer(n)
  1716. eta(m,n)=etafactor1*etafactor2(m,n)
  1717. enddo
  1718. enddo
  1719. call maxsat(zeta,eta,maxd_atype,ntype_aer, &
  1720. maxd_asize,nsize_aer,sm,alnsign,f1,smax)
  1721. ! write(6,*)'w,smax=',w,smax
  1722. lnsmax=log(smax)
  1723. x=2*(lnsm(nsize_aer(1),1)-lnsmax)/(3*sq2*alnsign(nsize_aer(1),1))
  1724. fnew=0.5*(1.-ERF_ALT(x))
  1725. endif
  1726. dwnew = dw
  1727. ! 06-nov-2005 rce - "n" here should be "nw" (?)
  1728. ! if(fnew-fold.gt.dfmax.and.n.gt.1)then
  1729. if(fnew-fold.gt.dfmax.and.nw.gt.1)then
  1730. ! reduce updraft increment for greater accuracy in integration
  1731. if (dw .gt. 1.01*dwmin) then
  1732. dw=0.7*dw
  1733. dw=max(dw,dwmin)
  1734. w=wold+dw
  1735. go to 41000
  1736. else
  1737. dwnew = dwmin
  1738. endif
  1739. endif
  1740. if(fnew-fold.lt.dfmin)then
  1741. ! increase updraft increment to accelerate integration
  1742. dwnew=min(1.5*dw,dwmax)
  1743. endif
  1744. fold=fnew
  1745. z=(w-wbar)/(sigw*sq2)
  1746. gaus=exp(-z*z)
  1747. fnmin=1.
  1748. xmincoeff=alogaten-2.*third*(lnsmax-alog2)-alog3
  1749. ! write(6,*)'xmincoeff=',xmincoeff
  1750. do 44002 n=1,ntype_aer
  1751. do 44000 m=1,nsize_aer(n)
  1752. if ( bin_is_empty(m,n) ) then
  1753. fn(m,n)=0.
  1754. fs(m,n)=0.
  1755. fm(m,n)=0.
  1756. else if ((isectional .eq. 2) .or. (isectional .eq. 4)) then
  1757. ! sectional
  1758. ! within-section dn/dx = a + b*x
  1759. xcut=xmincoeff-third*lnhygro(m,n)
  1760. ! ycut=(exp(xcut)/rhi(m,n))**3
  1761. ! 07-jul-2006 rce - the above line gave a (rare) overflow when smax=1.0e-20
  1762. ! if (ycut > yhi), then actual value of ycut is unimportant,
  1763. ! so do the following to avoid overflow
  1764. lnycut = 3.0 * ( xcut - log(rhi(m,n)) )
  1765. lnycut = min( lnycut, log(yhi(m,n)*1.0e5) )
  1766. ycut=exp(lnycut)
  1767. ! write(6,*)'m,n,rcut,rlo,rhi=',m,n,exp(xcut),rlo(m,n),rhi(m,n)
  1768. ! if(lnsmax.lt.lnsmn(m,n))then
  1769. if(ycut.gt.yhi(m,n))then
  1770. fn(m,n)=0.
  1771. fs(m,n)=0.
  1772. fm(m,n)=0.
  1773. elseif(ycut.lt.ylo(m,n))then
  1774. fn(m,n)=1.
  1775. fs(m,n)=1.
  1776. fm(m,n)=1.
  1777. elseif ( bin_is_narrow(m,n) ) then
  1778. ! 04-nov-2005 rce - for extremely narrow bins,
  1779. ! do zero activation if xcut>xmean, 100% activation otherwise
  1780. if (ycut.gt.ymean(m,n)) then
  1781. fn(m,n)=0.
  1782. fs(m,n)=0.
  1783. fm(m,n)=0.
  1784. else
  1785. fn(m,n)=1.
  1786. fs(m,n)=1.
  1787. fm(m,n)=1.
  1788. endif
  1789. else
  1790. phiyy=ycut/yhi(m,n)
  1791. fn(m,n) = asub(m,n)*(1.0-phiyy) + 0.5*bsub(m,n)*(1.0-phiyy*phiyy)
  1792. if (fn(m,n).lt.zero .or. fn(m,n).gt.one) then
  1793. if (idiag_fnsm_prob .gt. 0) then
  1794. print *,'fn(',m,n,')=',fn(m,n),' outside 0,1 - activate err21'
  1795. print *,'na,volc =', na(m,n), volc(m,n)
  1796. print *,'asub,bsub =', asub(m,n), bsub(m,n)
  1797. print *,'yhi,ycut =', yhi(m,n), ycut
  1798. endif
  1799. endif
  1800. if (fn(m,n) .le. zero) then
  1801. ! 10-nov-2005 rce - if fn=0, then fs & fm must be 0
  1802. fn(m,n)=zero
  1803. fs(m,n)=zero
  1804. fm(m,n)=zero
  1805. else if (fn(m,n) .ge. one) then
  1806. ! 10-nov-2005 rce - if fn=1, then fs & fm must be 1
  1807. fn(m,n)=one
  1808. fs(m,n)=one
  1809. fm(m,n)=one
  1810. else
  1811. ! 10-nov-2005 rce - otherwise, calc fm and check it
  1812. fm(m,n) = (yhi(m,n)/ymean(m,n)) * (0.5*asub(m,n)*(1.0-phiyy*phiyy) + &
  1813. third*bsub(m,n)*(1.0-phiyy*phiyy*phiyy))
  1814. if (fm(m,n).lt.fn(m,n) .or. fm(m,n).gt.one) then
  1815. if (idiag_fnsm_prob .gt. 0) then
  1816. print *,'fm(',m,n,')=',fm(m,n),' outside fn,1 - activate err22'
  1817. print *,'na,volc,fn =', na(m,n), volc(m,n), fn(m,n)
  1818. print *,'asub,bsub =', asub(m,n), bsub(m,n)
  1819. print *,'yhi,ycut =', yhi(m,n), ycut
  1820. endif
  1821. endif
  1822. if (fm(m,n) .le. fn(m,n)) then
  1823. ! 10-nov-2005 rce - if fm=fn, then fs must =fn
  1824. fm(m,n)=fn(m,n)
  1825. fs(m,n)=fn(m,n)
  1826. else if (fm(m,n) .ge. one) then
  1827. ! 10-nov-2005 rce - if fm=1, then fs & fn must be 1
  1828. fm(m,n)=one
  1829. fs(m,n)=one
  1830. fn(m,n)=one
  1831. else
  1832. ! 10-nov-2005 rce - these two checks assure that the mean size
  1833. ! of the activated & interstitial particles will be between rlo & rhi
  1834. dumaa = fn(m,n)*(yhi(m,n)/ymean(m,n))
  1835. fm(m,n) = min( fm(m,n), dumaa )
  1836. dumaa = 1.0 + (fn(m,n)-1.0)*(ylo(m,n)/ymean(m,n))
  1837. fm(m,n) = min( fm(m,n), dumaa )
  1838. ! 10-nov-2005 rce - now calculate fs and bound it by fn, fm
  1839. betayy = ylo(m,n)/yhi(m,n)
  1840. dumaa = phiyy**twothird
  1841. dumbb = betayy**twothird
  1842. fs(m,n) = &
  1843. (asub(m,n)*(1.0-phiyy*dumaa) + &
  1844. 0.625*bsub(m,n)*(1.0-phiyy*phiyy*dumaa)) / &
  1845. (asub(m,n)*(1.0-betayy*dumbb) + &
  1846. 0.625*bsub(m,n)*(1.0-betayy*betayy*dumbb))
  1847. fs(m,n)=max(fs(m,n),fn(m,n))
  1848. fs(m,n)=min(fs(m,n),fm(m,n))
  1849. endif
  1850. endif
  1851. endif
  1852. else
  1853. ! modal
  1854. x=2*(lnsm(m,n)-lnsmax)/(3*sq2*alnsign(m,n))
  1855. fn(m,n)=0.5*(1.-ERF_ALT(x))
  1856. arg=x-sq2*alnsign(m,n)
  1857. fs(m,n)=0.5*(1.-ERF_ALT(arg))
  1858. arg=x-1.5*sq2*alnsign(m,n)
  1859. fm(m,n)=0.5*(1.-ERF_ALT(arg))
  1860. ! print *,'w,x,fn,fs,fm=',w,x,fn(m,n),fs(m,n),fm(m,n)
  1861. endif
  1862. ! fn(m,n)=1. !test
  1863. ! fs(m,n)=1.
  1864. ! fm(m,n)=1.
  1865. fnmin=min(fn(m,n),fnmin)
  1866. ! integration is second order accurate
  1867. ! assumes linear variation of f*gaus with w
  1868. wb=(w+wold)
  1869. fnbar=(fn(m,n)*gaus+fnold(m,n)*gold)
  1870. fsbar=(fs(m,n)*gaus+fsold(m,n)*gold)
  1871. fmbar=(fm(m,n)*gaus+fmold(m,n)*gold)
  1872. if((top.and.w.lt.0.).or.(.not.top.and.w.gt.0.))then
  1873. sumflxn(m,n)=sumflxn(m,n)+sixth*(wb*fnbar &
  1874. +(fn(m,n)*gaus*w+fnold(m,n)*gold*wold))*dw
  1875. sumflxs(m,n)=sumflxs(m,n)+sixth*(wb*fsbar &
  1876. +(fs(m,n)*gaus*w+fsold(m,n)*gold*wold))*dw
  1877. sumflxm(m,n)=sumflxm(m,n)+sixth*(wb*fmbar &
  1878. +(fm(m,n)*gaus*w+fmold(m,n)*gold*wold))*dw
  1879. endif
  1880. sumfn(m,n)=sumfn(m,n)+0.5*fnbar*dw
  1881. ! write(6,'(a,9g10.2)')'lnsmax,lnsm(m,n),x,fn(m,n),fnold(m,n),g,gold,fnbar,dw=', &
  1882. ! lnsmax,lnsm(m,n),x,fn(m,n),fnold(m,n),g,gold,fnbar,dw
  1883. fnold(m,n)=fn(m,n)
  1884. sumfs(m,n)=sumfs(m,n)+0.5*fsbar*dw
  1885. fsold(m,n)=fs(m,n)
  1886. sumfm(m,n)=sumfm(m,n)+0.5*fmbar*dw
  1887. fmold(m,n)=fm(m,n)
  1888. 44000 continue ! m=1,nsize_aer(n)
  1889. 44002 continue ! n=1,ntype_aer
  1890. ! same form as sumflxm(m,n) but replace the fm/fmold(m,n) with 1.0
  1891. sumflx_fullact = sumflx_fullact &
  1892. + sixth*(wb*(gaus+gold) + (gaus*w + gold*wold))*dw
  1893. ! sumg=sumg+0.5*(gaus+gold)*dw
  1894. gold=gaus
  1895. wold=w
  1896. dw=dwnew
  1897. if(nw.gt.1.and.(w.gt.wmax.or.fnmin.gt.fmax))go to 48000
  1898. w=w+dw
  1899. 47000 continue ! nw = 1, nwmax
  1900. print *,'do loop is too short in activate'
  1901. print *,'wmin=',wmin,' w=',w,' wmax=',wmax,' dw=',dw
  1902. print *,'wbar=',wbar,' sigw=',sigw,' wdiab=',wdiab
  1903. print *,'wnuc=',wnuc
  1904. do n=1,ntype_aer
  1905. print *,'ntype=',n
  1906. print *,'na=',(na(m,n),m=1,nsize_aer(n))
  1907. print *,'fn=',(fn(m,n),m=1,nsize_aer(n))
  1908. end do
  1909. ! dump all subr parameters to allow testing with standalone code
  1910. ! (build a driver that will read input and call activate)
  1911. print *,'top,wbar,sigw,wdiab,tair,rhoair,ntype_aer='
  1912. print *, top,wbar,sigw,wdiab,tair,rhoair,ntype_aer
  1913. print *,'na='
  1914. print *, na
  1915. print *,'volc='
  1916. print *, volc
  1917. print *,'sigman='
  1918. print *, sigman
  1919. print *,'hygro='
  1920. print *, hygro
  1921. print *,'subr activate error 31 - i,j,k =', ii, jj, kk
  1922. ! 06-nov-2005 rce - if integration fails, repeat it once with additional diagnostics
  1923. if (ipass_nwloop .eq. 1) then
  1924. ipass_nwloop = 2
  1925. idiagaa = 2
  1926. goto 40000
  1927. end if
  1928. call wrf_error_fatal("STOP: activate before 48000")
  1929. 48000 continue
  1930. ! ndist(n)=ndist(n)+1
  1931. if(.not.top.and.w.lt.wmaxf)then
  1932. ! contribution from all updrafts stronger than wmax
  1933. ! assuming constant f (close to fmax)
  1934. wnuc=w+wdiab
  1935. z1=(w-wbar)/(sigw*sq2)
  1936. z2=(wmaxf-wbar)/(sigw*sq2)
  1937. integ=sigw*0.5*sq2*sqpi*(ERFC_NUM_RECIPES(z1)-ERFC_NUM_RECIPES(z2))
  1938. ! consider only upward flow into cloud base when estimating flux
  1939. wf1=max(w,zero)
  1940. zf1=(wf1-wbar)/(sigw*sq2)
  1941. gf1=exp(-zf1*zf1)
  1942. wf2=max(wmaxf,zero)
  1943. zf2=(wf2-wbar)/(sigw*sq2)
  1944. gf2=exp(-zf2*zf2)
  1945. gf=(gf1-gf2)
  1946. integf=wbar*sigw*0.5*sq2*sqpi*(ERFC_NUM_RECIPES(zf1)-ERFC_NUM_RECIPES(zf2))+sigw*sigw*gf
  1947. do n=1,ntype_aer
  1948. do m=1,nsize_aer(n)
  1949. sumflxn(m,n)=sumflxn(m,n)+integf*fn(m,n)
  1950. sumfn(m,n)=sumfn(m,n)+fn(m,n)*integ
  1951. sumflxs(m,n)=sumflxs(m,n)+integf*fs(m,n)
  1952. sumfs(m,n)=sumfs(m,n)+fs(m,n)*integ
  1953. sumflxm(m,n)=sumflxm(m,n)+integf*fm(m,n)
  1954. sumfm(m,n)=sumfm(m,n)+fm(m,n)*integ
  1955. end do
  1956. end do
  1957. ! same form as sumflxm(m,n) but replace the fm(m,n) with 1.0
  1958. sumflx_fullact = sumflx_fullact + integf
  1959. ! sumg=sumg+integ
  1960. endif
  1961. do n=1,ntype_aer
  1962. do m=1,nsize_aer(n)
  1963. ! fn(m,n)=sumfn(m,n)/(sumg)
  1964. fn(m,n)=sumfn(m,n)/(sq2*sqpi*sigw)
  1965. fluxn(m,n)=sumflxn(m,n)/(sq2*sqpi*sigw)
  1966. if(fn(m,n).gt.1.01)then
  1967. if (idiag_fnsm_prob .gt. 0) then
  1968. print *,'fn=',fn(m,n),' > 1 - activate err41'
  1969. print *,'w,m,n,na,am=',w,m,n,na(m,n),am(m,n)
  1970. print *,'integ,sumfn,sigw=',integ,sumfn(m,n),sigw
  1971. print *,'subr activate error - i,j,k =', ii, jj, kk
  1972. endif
  1973. fluxn(m,n) = fluxn(m,n)/fn(m,n)
  1974. endif
  1975. fs(m,n)=sumfs(m,n)/(sq2*sqpi*sigw)
  1976. fluxs(m,n)=sumflxs(m,n)/(sq2*sqpi*sigw)
  1977. if(fs(m,n).gt.1.01)then
  1978. if (idiag_fnsm_prob .gt. 0) then
  1979. print *,'fs=',fs(m,n),' > 1 - activate err42'
  1980. print *,'m,n,isectional=',m,n,isectional
  1981. print *,'alnsign(m,n)=',alnsign(m,n)
  1982. print *,'rcut,rlo(m,n),rhi(m,n)',exp(xcut),rlo(m,n),rhi(m,n)
  1983. print *,'w,m,na,am=',w,m,na(m,n),am(m,n)
  1984. print *,'integ,sumfs,sigw=',integ,sumfs(m,n),sigw
  1985. endif
  1986. fluxs(m,n) = fluxs(m,n)/fs(m,n)
  1987. endif
  1988. ! fm(m,n)=sumfm(m,n)/(sumg)
  1989. fm(m,n)=sumfm(m,n)/(sq2*sqpi*sigw)
  1990. fluxm(m,n)=sumflxm(m,n)/(sq2*sqpi*sigw)
  1991. if(fm(m,n).gt.1.01)then
  1992. if (idiag_fnsm_prob .gt. 0) then
  1993. print *,'fm(',m,n,')=',fm(m,n),' > 1 - activate err43'
  1994. endif
  1995. fluxm(m,n) = fluxm(m,n)/fm(m,n)
  1996. endif
  1997. end do
  1998. end do
  1999. ! same form as fluxm(m,n)
  2000. flux_fullact = sumflx_fullact/(sq2*sqpi*sigw)
  2001. goto 60000
  2002. !.......................................................................
  2003. !
  2004. ! end calc. of activation fractions/fluxes
  2005. ! for spectrum of updrafts (end of section 2)
  2006. !
  2007. !.......................................................................
  2008. !.......................................................................
  2009. !
  2010. ! start calc. of activation fractions/fluxes
  2011. ! for (single) uniform updraft (start of section 3)
  2012. !
  2013. !.......................................................................
  2014. 50000 continue
  2015. wnuc=wbar+wdiab
  2016. ! write(6,*)'uniform updraft =',wnuc
  2017. ! 04-nov-2005 rce - moved the code for "wnuc.le.0" code to here
  2018. if(wnuc.le.0.)then
  2019. do n=1,ntype_aer
  2020. do m=1,nsize_aer(n)
  2021. fn(m,n)=0
  2022. fluxn(m,n)=0
  2023. fs(m,n)=0
  2024. fluxs(m,n)=0
  2025. fm(m,n)=0
  2026. fluxm(m,n)=0
  2027. end do
  2028. end do
  2029. flux_fullact=0.
  2030. return
  2031. endif
  2032. w=wbar
  2033. alw=alpha*wnuc
  2034. sqrtalw=sqrt(alw)
  2035. zeta=2.*sqrtalw*aten/(3.*sqrtg)
  2036. if (isectional .gt. 0) then
  2037. ! sectional model.
  2038. ! use bulk properties
  2039. do n=1,ntype_aer
  2040. if(totn(n).gt.1.e-10)then
  2041. eta(1,n)=2*alw*sqrtalw/(totn(n)*beta*sqrtg)
  2042. else
  2043. eta(1,n)=1.e10
  2044. endif
  2045. end do
  2046. call maxsat(zeta,eta,maxd_atype,ntype_aer, &
  2047. maxd_asize,(/1/),gmsm,gmlnsig,f1,smax)
  2048. else
  2049. do n=1,ntype_aer
  2050. do m=1,nsize_aer(n)
  2051. if(na(m,n).gt.1.e-10)then
  2052. eta(m,n)=2*alw*sqrtalw/(na(m,n)*beta*sqrtg)
  2053. else
  2054. eta(m,n)=1.e10
  2055. endif
  2056. end do
  2057. end do
  2058. call maxsat(zeta,eta,maxd_atype,ntype_aer, &
  2059. maxd_asize,nsize_aer,sm,alnsign,f1,smax)
  2060. endif
  2061. lnsmax=log(smax)
  2062. xmincoeff=alogaten-2.*third*(lnsmax-alog2)-alog3
  2063. do 55002 n=1,ntype_aer
  2064. do 55000 m=1,nsize_aer(n)
  2065. ! 04-nov-2005 rce - check for bin_is_empty here too, just like earlier
  2066. if ( bin_is_empty(m,n) ) then
  2067. fn(m,n)=0.
  2068. fs(m,n)=0.
  2069. fm(m,n)=0.
  2070. else if ((isectional .eq. 2) .or. (isectional .eq. 4)) then
  2071. ! sectional
  2072. ! within-section dn/dx = a + b*x
  2073. xcut=xmincoeff-third*lnhygro(m,n)
  2074. ! ycut=(exp(xcut)/rhi(m,n))**3
  2075. ! 07-jul-2006 rce - the above line gave a (rare) overflow when smax=1.0e-20
  2076. ! if (ycut > yhi), then actual value of ycut is unimportant,
  2077. ! so do the following to avoid overflow
  2078. lnycut = 3.0 * ( xcut - log(rhi(m,n)) )
  2079. lnycut = min( lnycut, log(yhi(m,n)*1.0e5) )
  2080. ycut=exp(lnycut)
  2081. ! write(6,*)'m,n,rcut,rlo,rhi=',m,n,exp(xcut),rlo(m,n),rhi(m,n)
  2082. ! if(lnsmax.lt.lnsmn(m,n))then
  2083. if(ycut.gt.yhi(m,n))then
  2084. fn(m,n)=0.
  2085. fs(m,n)=0.
  2086. fm(m,n)=0.
  2087. ! elseif(lnsmax.gt.lnsmx(m,n))then
  2088. elseif(ycut.lt.ylo(m,n))then
  2089. fn(m,n)=1.
  2090. fs(m,n)=1.
  2091. fm(m,n)=1.
  2092. elseif ( bin_is_narrow(m,n) ) then
  2093. ! 04-nov-2005 rce - for extremely narrow bins,
  2094. ! do zero activation if xcut>xmean, 100% activation otherwise
  2095. if (ycut.gt.ymean(m,n)) then
  2096. fn(m,n)=0.
  2097. fs(m,n)=0.
  2098. fm(m,n)=0.
  2099. else
  2100. fn(m,n)=1.
  2101. fs(m,n)=1.
  2102. fm(m,n)=1.
  2103. endif
  2104. else
  2105. phiyy=ycut/yhi(m,n)
  2106. fn(m,n) = asub(m,n)*(1.0-phiyy) + 0.5*bsub(m,n)*(1.0-phiyy*phiyy)
  2107. if (fn(m,n).lt.zero .or. fn(m,n).gt.one) then
  2108. if (idiag_fnsm_prob .gt. 0) then
  2109. print *,'fn(',m,n,')=',fn(m,n),' outside 0,1 - activate err21'
  2110. print *,'na,volc =', na(m,n), volc(m,n)
  2111. print *,'asub,bsub =', asub(m,n), bsub(m,n)
  2112. print *,'yhi,ycut =', yhi(m,n), ycut
  2113. endif
  2114. endif
  2115. if (fn(m,n) .le. zero) then
  2116. ! 10-nov-2005 rce - if fn=0, then fs & fm must be 0
  2117. fn(m,n)=zero
  2118. fs(m,n)=zero
  2119. fm(m,n)=zero
  2120. else if (fn(m,n) .ge. one) then
  2121. ! 10-nov-2005 rce - if fn=1, then fs & fm must be 1
  2122. fn(m,n)=one
  2123. fs(m,n)=one
  2124. fm(m,n)=one
  2125. else
  2126. ! 10-nov-2005 rce - otherwise, calc fm and check it
  2127. fm(m,n) = (yhi(m,n)/ymean(m,n)) * (0.5*asub(m,n)*(1.0-phiyy*phiyy) + &
  2128. third*bsub(m,n)*(1.0-phiyy*phiyy*phiyy))
  2129. if (fm(m,n).lt.fn(m,n) .or. fm(m,n).gt.one) then
  2130. if (idiag_fnsm_prob .gt. 0) then
  2131. print *,'fm(',m,n,')=',fm(m,n),' outside fn,1 - activate err22'
  2132. print *,'na,volc,fn =', na(m,n), volc(m,n), fn(m,n)
  2133. print *,'asub,bsub =', asub(m,n), bsub(m,n)
  2134. print *,'yhi,ycut =', yhi(m,n), ycut
  2135. endif
  2136. endif
  2137. if (fm(m,n) .le. fn(m,n)) then
  2138. ! 10-nov-2005 rce - if fm=fn, then fs must =fn
  2139. fm(m,n)=fn(m,n)
  2140. fs(m,n)=fn(m,n)
  2141. else if (fm(m,n) .ge. one) then
  2142. ! 10-nov-2005 rce - if fm=1, then fs & fn must be 1
  2143. fm(m,n)=one
  2144. fs(m,n)=one
  2145. fn(m,n)=one
  2146. else
  2147. ! 10-nov-2005 rce - these two checks assure that the mean size
  2148. ! of the activated & interstitial particles will be between rlo & rhi
  2149. dumaa = fn(m,n)*(yhi(m,n)/ymean(m,n))
  2150. fm(m,n) = min( fm(m,n), dumaa )
  2151. dumaa = 1.0 + (fn(m,n)-1.0)*(ylo(m,n)/ymean(m,n))
  2152. fm(m,n) = min( fm(m,n), dumaa )
  2153. ! 10-nov-2005 rce - now calculate fs and bound it by fn, fm
  2154. betayy = ylo(m,n)/yhi(m,n)
  2155. dumaa = phiyy**twothird
  2156. dumbb = betayy**twothird
  2157. fs(m,n) = &
  2158. (asub(m,n)*(1.0-phiyy*dumaa) + &
  2159. 0.625*bsub(m,n)*(1.0-phiyy*phiyy*dumaa)) / &
  2160. (asub(m,n)*(1.0-betayy*dumbb) + &
  2161. 0.625*bsub(m,n)*(1.0-betayy*betayy*dumbb))
  2162. fs(m,n)=max(fs(m,n),fn(m,n))
  2163. fs(m,n)=min(fs(m,n),fm(m,n))
  2164. endif
  2165. endif
  2166. endif
  2167. else
  2168. ! modal
  2169. x=2*(lnsm(m,n)-lnsmax)/(3*sq2*alnsign(m,n))
  2170. fn(m,n)=0.5*(1.-ERF_ALT(x))
  2171. arg=x-sq2*alnsign(m,n)
  2172. fs(m,n)=0.5*(1.-ERF_ALT(arg))
  2173. arg=x-1.5*sq2*alnsign(m,n)
  2174. fm(m,n)=0.5*(1.-ERF_ALT(arg))
  2175. endif
  2176. ! fn(m,n)=1. ! test
  2177. ! fs(m,n)=1.
  2178. ! fm(m,n)=1.
  2179. if((top.and.wbar.lt.0.).or.(.not.top.and.wbar.gt.0.))then
  2180. fluxn(m,n)=fn(m,n)*w
  2181. fluxs(m,n)=fs(m,n)*w
  2182. fluxm(m,n)=fm(m,n)*w
  2183. else
  2184. fluxn(m,n)=0
  2185. fluxs(m,n)=0
  2186. fluxm(m,n)=0
  2187. endif
  2188. 55000 continue ! m=1,nsize_aer(n)
  2189. 55002 continue ! n=1,ntype_aer
  2190. if((top.and.wbar.lt.0.).or.(.not.top.and.wbar.gt.0.))then
  2191. flux_fullact = w
  2192. else
  2193. flux_fullact = 0.0
  2194. endif
  2195. ! 04-nov-2005 rce - moved the code for "wnuc.le.0" from here
  2196. ! to near the start the uniform undraft section
  2197. !.......................................................................
  2198. !
  2199. ! end calc. of activation fractions/fluxes
  2200. ! for (single) uniform updraft (end of section 3)
  2201. !
  2202. !.......................................................................
  2203. 60000 continue
  2204. ! do n=1,ntype_aer
  2205. ! do m=1,nsize_aer(n)
  2206. ! write(6,'(a,2i3,5e10.1)')'n,m,na,wbar,sigw,fn,fm=',n,m,na(m,n),wbar,sigw,fn(m,n),fm(m,n)
  2207. ! end do
  2208. ! end do
  2209. return
  2210. end subroutine activate
  2211. !----------------------------------------------------------------------
  2212. !----------------------------------------------------------------------
  2213. subroutine maxsat(zeta,eta, &
  2214. maxd_atype,ntype_aer,maxd_asize,nsize_aer, &
  2215. sm,alnsign,f1,smax)
  2216. ! Calculates maximum supersaturation for multiple competing aerosol
  2217. ! modes. Note that maxsat_init must be called before calling this
  2218. ! subroutine.
  2219. ! Abdul-Razzak and Ghan, A parameterization of aerosol activation.
  2220. ! 2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844.
  2221. implicit none
  2222. integer, intent(in) :: maxd_atype
  2223. integer, intent(in) :: ntype_aer
  2224. integer, intent(in) :: maxd_asize
  2225. integer, intent(in) :: nsize_aer(maxd_atype) ! number of size bins
  2226. real, intent(in) :: sm(maxd_asize,maxd_atype) ! critical supersaturation for number mode radius
  2227. real, intent(in) :: zeta, eta(maxd_asize,maxd_atype)
  2228. real, intent(in) :: alnsign(maxd_asize,maxd_atype) ! ln(sigma)
  2229. real, intent(in) :: f1(maxd_asize,maxd_atype)
  2230. real, intent(out) :: smax ! maximum supersaturation
  2231. real :: g1, g2
  2232. real thesum
  2233. integer m ! size index
  2234. integer n ! type index
  2235. do n=1,ntype_aer
  2236. do m=1,nsize_aer(n)
  2237. if(zeta.gt.1.e5*eta(m,n) .or. &
  2238. sm(m,n)*sm(m,n).gt.1.e5*eta(m,n))then
  2239. ! weak forcing. essentially none activated
  2240. smax=1.e-20
  2241. else
  2242. ! significant activation of this mode. calc activation all modes.
  2243. go to 1
  2244. endif
  2245. end do
  2246. end do
  2247. return
  2248. 1 continue
  2249. thesum=0
  2250. do n=1,ntype_aer
  2251. do m=1,nsize_aer(n)
  2252. if(eta(m,n).gt.1.e-20)then
  2253. g1=sqrt(zeta/eta(m,n))
  2254. g1=g1*g1*g1
  2255. g2=sm(m,n)/sqrt(eta(m,n)+3*zeta)
  2256. g2=sqrt(g2)
  2257. g2=g2*g2*g2
  2258. thesum=thesum + &
  2259. (f1(m,n)*g1+(1.+0.25*alnsign(m,n))*g2)/(sm(m,n)*sm(m,n))
  2260. else
  2261. thesum=1.e20
  2262. endif
  2263. end do
  2264. end do
  2265. smax=1./sqrt(thesum)
  2266. return
  2267. end subroutine maxsat
  2268. !----------------------------------------------------------------------
  2269. !----------------------------------------------------------------------
  2270. subroutine maxsat_init(maxd_atype, ntype_aer, &
  2271. maxd_asize, nsize_aer, alnsign, f1)
  2272. ! Calculates the f1 paramter needed by maxsat.
  2273. ! Abdul-Razzak and Ghan, A parameterization of aerosol activation.
  2274. ! 2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844.
  2275. implicit none
  2276. integer, intent(in) :: maxd_atype
  2277. integer, intent(in) :: ntype_aer ! number of aerosol types
  2278. integer, intent(in) :: maxd_asize
  2279. integer, intent(in) :: nsize_aer(maxd_atype) ! number of size bins
  2280. real, intent(in) :: alnsign(maxd_asize,maxd_atype) ! ln(sigma)
  2281. real, intent(out) :: f1(maxd_asize,maxd_atype)
  2282. integer m ! size index
  2283. integer n ! type index
  2284. ! calculate and save f1(sigma), assumes sigma is invariant
  2285. ! between calls to this init routine
  2286. do n=1,ntype_aer
  2287. do m=1,nsize_aer(n)
  2288. f1(m,n)=0.5*exp(2.5*alnsign(m,n)*alnsign(m,n))
  2289. end do
  2290. end do
  2291. end subroutine maxsat_init
  2292. !----------------------------------------------------------------------
  2293. !----------------------------------------------------------------------
  2294. ! 25-apr-2006 rce - dens_aer is (g/cm3), NOT (kg/m3);
  2295. ! grid_id, ktau, i, j, isize, itype added to arg list to assist debugging
  2296. subroutine loadaer(chem,k,kmn,kmx,num_chem,cs,npv, &
  2297. dlo_sect,dhi_sect,maxd_acomp, ncomp, &
  2298. grid_id, ktau, i, j, isize, itype, &
  2299. numptr_aer, numptrcw_aer, dens_aer, &
  2300. massptr_aer, massptrcw_aer, &
  2301. maerosol, maerosolcw, &
  2302. maerosol_tot, maerosol_totcw, &
  2303. naerosol, naerosolcw, &
  2304. vaerosol, vaerosolcw)
  2305. implicit none
  2306. ! load aerosol number, surface, mass concentrations
  2307. ! input
  2308. integer, intent(in) :: num_chem ! maximum number of consituents
  2309. integer, intent(in) :: k,kmn,kmx
  2310. real, intent(in) :: chem(kmn:kmx,num_chem) ! aerosol mass, number mixing ratios
  2311. real, intent(in) :: cs ! air density (kg/m3)
  2312. real, intent(in) :: npv ! number per volume concentration (/m3)
  2313. integer, intent(in) :: maxd_acomp,ncomp
  2314. integer, intent(in) :: numptr_aer,numptrcw_aer
  2315. integer, intent(in) :: massptr_aer(maxd_acomp), massptrcw_aer(maxd_acomp)
  2316. real, intent(in) :: dens_aer(maxd_acomp) ! aerosol material density (g/cm3)
  2317. real, intent(in) :: dlo_sect,dhi_sect ! minimum, maximum diameter of section (cm)
  2318. integer, intent(in) :: grid_id, ktau, i, j, isize, itype
  2319. ! output
  2320. real, intent(out) :: naerosol ! interstitial number conc (/m3)
  2321. real, intent(out) :: naerosolcw ! activated number conc (/m3)
  2322. real, intent(out) :: maerosol(maxd_acomp) ! interstitial mass conc (kg/m3)
  2323. real, intent(out) :: maerosolcw(maxd_acomp) ! activated mass conc (kg/m3)
  2324. real, intent(out) :: maerosol_tot ! total-over-species interstitial mass conc (kg/m3)
  2325. real, intent(out) :: maerosol_totcw ! total-over-species activated mass conc (kg/m3)
  2326. real, intent(out) :: vaerosol ! interstitial volume conc (m3/m3)
  2327. real, intent(out) :: vaerosolcw ! activated volume conc (m3/m3)
  2328. ! internal
  2329. integer lnum,lnumcw,l,ltype,lmass,lmasscw,lsfc,lsfccw
  2330. real num_at_dhi, num_at_dlo
  2331. real npv_at_dhi, npv_at_dlo
  2332. real, parameter :: pi = 3.1415926526
  2333. real specvol ! inverse aerosol material density (m3/kg)
  2334. lnum=numptr_aer
  2335. lnumcw=numptrcw_aer
  2336. maerosol_tot=0.
  2337. maerosol_totcw=0.
  2338. vaerosol=0.
  2339. vaerosolcw=0.
  2340. do l=1,ncomp
  2341. lmass=massptr_aer(l)
  2342. lmasscw=massptrcw_aer(l)
  2343. maerosol(l)=chem(k,lmass)*cs
  2344. maerosol(l)=max(maerosol(l),0.)
  2345. maerosolcw(l)=chem(k,lmasscw)*cs
  2346. maerosolcw(l)=max(maerosolcw(l),0.)
  2347. maerosol_tot=maerosol_tot+maerosol(l)
  2348. maerosol_totcw=maerosol_totcw+maerosolcw(l)
  2349. ! [ 1.e-3 factor because dens_aer is (g/cm3), specvol is (m3/kg) ]
  2350. specvol=1.0e-3/dens_aer(l)
  2351. vaerosol=vaerosol+maerosol(l)*specvol
  2352. vaerosolcw=vaerosolcw+maerosolcw(l)*specvol
  2353. ! write(6,'(a,3e12.2)')'maerosol,dens_aer,vaerosol=',maerosol(l),dens_aer(l),vaerosol
  2354. enddo
  2355. if(lnum.gt.0)then
  2356. ! aerosol number predicted
  2357. ! [ 1.0e6 factor because because dhi_ & dlo_sect are (cm), vaerosol is (m3) ]
  2358. npv_at_dhi = 6.0e6/(pi*dhi_sect*dhi_sect*dhi_sect)
  2359. npv_at_dlo = 6.0e6/(pi*dlo_sect*dlo_sect*dlo_sect)
  2360. naerosol=chem(k,lnum)*cs
  2361. naerosolcw=chem(k,lnumcw)*cs
  2362. num_at_dhi = vaerosol*npv_at_dhi
  2363. num_at_dlo = vaerosol*npv_at_dlo
  2364. naerosol = max( num_at_dhi, min( num_at_dlo, naerosol ) )
  2365. ! write(6,'(a,5e10.1)')'naerosol,num_at_dhi,num_at_dlo,dhi_sect,dlo_sect', &
  2366. ! naerosol,num_at_dhi,num_at_dlo,dhi_sect,dlo_sect
  2367. num_at_dhi = vaerosolcw*npv_at_dhi
  2368. num_at_dlo = vaerosolcw*npv_at_dlo
  2369. naerosolcw = max( num_at_dhi, min( num_at_dlo, naerosolcw ) )
  2370. else
  2371. ! aerosol number diagnosed from mass and prescribed size
  2372. naerosol=vaerosol*npv
  2373. naerosol=max(naerosol,0.)
  2374. naerosolcw=vaerosolcw*npv
  2375. naerosolcw=max(naerosolcw,0.)
  2376. endif
  2377. return
  2378. end subroutine loadaer
  2379. !-----------------------------------------------------------------------
  2380. real function erfc_num_recipes( x )
  2381. !
  2382. ! from press et al, numerical recipes, 1990, page 164
  2383. !
  2384. implicit none
  2385. real x
  2386. double precision erfc_dbl, dum, t, zz
  2387. zz = abs(x)
  2388. t = 1.0/(1.0 + 0.5*zz)
  2389. ! erfc_num_recipes =
  2390. ! & t*exp( -zz*zz - 1.26551223 + t*(1.00002368 + t*(0.37409196 +
  2391. ! & t*(0.09678418 + t*(-0.18628806 + t*(0.27886807 +
  2392. ! & t*(-1.13520398 +
  2393. ! & t*(1.48851587 + t*(-0.82215223 + t*0.17087277 )))))))))
  2394. dum = ( -zz*zz - 1.26551223 + t*(1.00002368 + t*(0.37409196 + &
  2395. t*(0.09678418 + t*(-0.18628806 + t*(0.27886807 + &
  2396. t*(-1.13520398 + &
  2397. t*(1.48851587 + t*(-0.82215223 + t*0.17087277 )))))))))
  2398. erfc_dbl = t * exp(dum)
  2399. if (x .lt. 0.0) erfc_dbl = 2.0d0 - erfc_dbl
  2400. erfc_num_recipes = erfc_dbl
  2401. return
  2402. end function erfc_num_recipes
  2403. !-----------------------------------------------------------------------
  2404. real function erf_alt( x )
  2405. implicit none
  2406. real,intent(in) :: x
  2407. erf_alt = 1. - erfc_num_recipes(x)
  2408. end function erf_alt
  2409. END MODULE module_mixactivate