PageRenderTime 74ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/wrfv2_fire/phys/module_mp_milbrandt2mom.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 4438 lines | 2761 code | 561 blank | 1116 comment | 341 complexity | 0d6118d58a2e2fcb63fb635577f6d68e MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. !_______________________________________________________________________________!
  2. ! !
  3. ! This module contains the microphysics sub-driver for the 2-moment version of !
  4. ! the Milbrandt-Yau (2005, JAS) microphysics scheme, along with all associated !
  5. ! subprograms. The main subroutine, 'mp_milbrandt2mom_main', is essentially !
  6. ! directly from the RPN-CMC physics library of the Canadian GEM model. It is !
  7. ! called by the wrapper 'mp_milbrandt2mom_driver' which makes the necessary !
  8. ! adjustments to the calling parameters for the interface to WRF. !
  9. ! !
  10. ! For questions, bug reports, etc. pertaining to the scheme, or to request !
  11. ! updates to the code (before the next offical WRF release) please contact !
  12. ! Jason Milbrandt (Environment Canada) at jason.milbrandt@ec.gc.ca !
  13. ! !
  14. ! Last modified: 2011-03-02 !
  15. !_______________________________________________________________________________!
  16. module my_fncs_mod
  17. !==============================================================================!
  18. ! The following functions are used by the schemes in the multimoment package. !
  19. ! !
  20. ! Package version: 2.19.0 (internal bookkeeping) !
  21. ! Last modified : 2009-04-27 !
  22. !==============================================================================!
  23. implicit none
  24. private
  25. public :: NccnFNC,SxFNC,gamma,gammaDP,gser,gammln,gammp,cfg,gamminc
  26. contains
  27. !==============================================================================!
  28. REAL FUNCTION NccnFNC(Win,Tin,Pin,CCNtype)
  29. !---------------------------------------------------------------------------!
  30. ! This function returns number concentration (activated aerosols) as a
  31. ! function of w,T,p, based on polynomial approximations of detailed
  32. ! approach using a hypergeometric function, following Cohard and Pinty (2000a).
  33. !---------------------------------------------------------------------------!
  34. IMPLICIT NONE
  35. ! PASSING PARAMETERS:
  36. real, intent(in) :: Win, Tin, Pin
  37. integer, intent(in) :: CCNtype
  38. ! LOCAL PARAMETERS:
  39. real :: T,p,x,y,a,b,c,d,e,f,g,h,T2,T3,T4,x2,x3,x4,p2
  40. x= log10(Win*100.); x2= x*x; x3= x2*x; x4= x2*x2
  41. T= Tin - 273.15; T2= T*T; T3= T2*T; T4= T2*T2
  42. p= Pin*0.01; p2= p*p
  43. if (CCNtype==1) then !Maritime
  44. a= 1.47e-9*T4 -6.944e-8*T3 -9.933e-7*T2 +2.7278e-4*T -6.6853e-4
  45. b=-1.41e-8*T4 +6.662e-7*T3 +4.483e-6*T2 -2.0479e-3*T +4.0823e-2
  46. c= 5.12e-8*T4 -2.375e-6*T3 +4.268e-6*T2 +3.9681e-3*T -3.2356e-1
  47. d=-8.25e-8*T4 +3.629e-6*T3 -4.044e-5*T2 +2.1846e-3*T +9.1227e-1
  48. e= 5.02e-8*T4 -1.973e-6*T3 +3.944e-5*T2 -9.0734e-3*T +1.1256e0
  49. f= -1.424e-6*p2 +3.631e-3*p -1.986
  50. g= -0.0212*x4 +0.1765*x3 -0.3770*x2 -0.2200*x +1.0081
  51. h= 2.47e-6*T3 -3.654e-5*T2 +2.3327e-3*T +0.1938
  52. y= a*x4 + b*x3 + c*x2 + d*x + e + f*g*h
  53. NccnFNC= 10.**min(2.,max(0.,y)) *1.e6 ![m-3]
  54. else if (CCNtype==2) then !Continental
  55. a= 0.
  56. b= 0.
  57. c=-2.112e-9*T4 +3.9836e-8*T3 +2.3703e-6*T2 -1.4542e-4*T -0.0698
  58. d=-4.210e-8*T4 +5.5745e-7*T3 +1.8460e-5*T2 +9.6078e-4*T +0.7120
  59. e= 1.434e-7*T4 -1.6455e-6*T3 -4.3334e-5*T2 -7.6720e-3*T +1.0056
  60. f= 1.340e-6*p2 -3.5114e-3*p +1.9453
  61. g= 4.226e-3*x4 -5.6012e-3*x3 -8.7846e-2*x2 +2.7435e-2*x +0.9932
  62. h= 5.811e-9*T4 +1.5589e-7*T3 -3.8623e-5*T2 +1.4471e-3*T +0.1496
  63. y= a*x4 +b*x3 +c*x2 + d*x + e + (f*g*h)
  64. NccnFNC= 10.**max(0.,y) *1.e6
  65. else
  66. print*, '*** STOPPED in MODULE ### NccnFNC *** '
  67. print*, ' Parameter CCNtype incorrectly specified'
  68. stop
  69. endif
  70. END FUNCTION NccnFNC
  71. !======================================================================!
  72. real FUNCTION SxFNC(Win,Tin,Pin,Qsw,Qsi,CCNtype,WRT)
  73. !---------------------------------------------------------------------------!
  74. ! This function returns the peak supersaturation achieved during ascent with
  75. ! activation of CCN aerosols as a function of w,T,p, based on polynomial
  76. ! approximations of detailed approach using a hypergeometric function,
  77. ! following Cohard and Pinty (2000a).
  78. !---------------------------------------------------------------------------!
  79. IMPLICIT NONE
  80. ! PASSING PARAMETERS:
  81. integer, intent(IN) :: WRT
  82. integer, intent(IN) :: CCNtype
  83. real, intent(IN) :: Win, Tin, Pin, Qsw, Qsi
  84. ! LOCAL PARAMETERS:
  85. real :: Si,Sw,Qv,T,p,x,a,b,c,d,f,g,h,Pcorr,T2corr,T2,T3,T4,x2,x3,x4,p2
  86. real, parameter :: TRPL= 273.15
  87. x= log10(max(Win,1.e-20)*100.); x2= x*x; x3= x2*x; x4= x2*x2
  88. T= Tin; T2= T*T; T3= T2*T; T4= T2*T2
  89. p= Pin*0.01; p2= p*p
  90. if (CCNtype==1) then !Maritime
  91. a= -5.109e-7*T4 -3.996e-5*T3 -1.066e-3*T2 -1.273e-2*T +0.0659
  92. b= 2.014e-6*T4 +1.583e-4*T3 +4.356e-3*T2 +4.943e-2*T -0.1538
  93. c= -2.037e-6*T4 -1.625e-4*T3 -4.541e-3*T2 -5.118e-2*T +0.1428
  94. d= 3.812e-7*T4 +3.065e-5*T3 +8.795e-4*T2 +9.440e-3*T +6.14e-3
  95. f= -2.012e-6*p2 + 4.1913e-3*p - 1.785e0
  96. g= 2.832e-1*x3 -5.6990e-1*x2 +5.1105e-1*x -4.1747e-4
  97. h= 1.173e-6*T3 +3.2174e-5*T2 -6.8832e-4*T +6.7888e-2
  98. Pcorr= f*g*h
  99. T2corr= 0.9581-4.449e-3*T-2.016e-4*T2-3.307e-6*T3-1.725e-8*T4
  100. else if (CCNtype==2) then !Continental [computed for -35<T<-5C]
  101. a= 3.80e-5*T2 +1.65e-4*T +9.88e-2
  102. b= -7.38e-5*T2 -2.53e-3*T -3.23e-1
  103. c= 8.39e-5*T2 +3.96e-3*T +3.50e-1
  104. d= -1.88e-6*T2 -1.33e-3*T -3.73e-2
  105. f= -1.9761e-6*p2 + 4.1473e-3*p - 1.771e0
  106. g= 0.1539*x4 -0.5575*x3 +0.9262*x2 -0.3498*x -0.1293
  107. h=-8.035e-9*T4+3.162e-7*T3+1.029e-5*T2-5.931e-4*T+5.62e-2
  108. Pcorr= f*g*h
  109. T2corr= 0.98888-5.0525e-4*T-1.7598e-5*T2-8.3308e-8*T3
  110. else
  111. print*, '*** STOPPED in MODULE ### SxFNC *** '
  112. print*, ' Parameter CCNtype incorrectly specified'
  113. stop
  114. endif
  115. Sw= (a*x3 + b*x2 +c*x + d) + Pcorr
  116. Sw= 1. + 0.01*Sw
  117. Qv= Qsw*Sw
  118. Si= Qv/Qsi
  119. Si= Si*T2corr
  120. if (WRT.eq.1) then
  121. SxFNC= Sw
  122. else
  123. SxFNC= Si
  124. endif
  125. if (Win.le.0.) SxFNC= 1.
  126. END function SxFNC
  127. !======================================================================!
  128. real FUNCTION gamma(xx)
  129. ! Modified from "Numerical Recipes"
  130. IMPLICIT NONE
  131. ! PASSING PARAMETERS:
  132. real, intent(IN) :: xx
  133. ! LOCAL PARAMETERS:
  134. integer :: j
  135. real*8 :: ser,stp,tmp,x,y,cof(6),gammadp
  136. SAVE cof,stp
  137. DATA cof,stp/76.18009172947146d0,-86.50532032941677d0, &
  138. 24.01409824083091d0,-1.231739572450155d0,.1208650973866179d-2, &
  139. -.5395239384953d-5,2.5066282746310005d0/
  140. x=dble(xx)
  141. y=x
  142. tmp=x+5.5d0
  143. tmp=(x+0.5d0)*log(tmp)-tmp
  144. ser=1.000000000190015d0
  145. ! do j=1,6 !original
  146. do j=1,4
  147. !!do j=1,3 !gives result to within ~ 3 %
  148. y=y+1.d0
  149. ser=ser+cof(j)/y
  150. enddo
  151. gammadp=tmp+log(stp*ser/x)
  152. gammadp= exp(gammadp)
  153. #if (DWORDSIZE == 8 && RWORDSIZE == 8)
  154. gamma = gammadp
  155. #elif (DWORDSIZE == 8 && RWORDSIZE == 4)
  156. gamma = sngl(gammadp)
  157. #else
  158. This is a temporary hack assuming double precision is 8 bytes.
  159. #endif
  160. END FUNCTION gamma
  161. !======================================================================!
  162. ! ! !
  163. ! ! ! -- USED BY DIAGNOSTIC-ALPHA DOUBLE-MOMENT (SINGLE-PRECISION) VERSION --
  164. ! ! ! FOR FUTURE VERSIONS OF M-Y PACKAGE WITH, THIS S/R CAN BE USED
  165. ! ! !
  166. ! ! ! real FUNCTION diagAlpha(Dm,x)
  167. ! ! !
  168. ! ! ! IMPLICIT NONE
  169. ! ! !
  170. ! ! ! integer :: x
  171. ! ! ! real :: Dm
  172. ! ! ! real, dimension(5) :: c1,c2,c3,c4
  173. ! ! ! real, parameter :: pi = 3.14159265
  174. ! ! ! real, parameter :: alphaMAX= 80.e0
  175. ! ! ! data c1 /19.0, 12.0, 4.5, 5.5, 3.7/
  176. ! ! ! data c2 / 0.6, 0.7, 0.5, 0.7, 0.3/
  177. ! ! ! data c3 / 1.8, 1.7, 5.0, 4.5, 9.0/
  178. ! ! ! data c4 /17.0, 11.0, 5.5, 8.5, 6.5/
  179. ! ! ! diagAlpha= c1(x)*tanh(c2(x)*(1.e3*Dm-c3(x)))+c4(x)
  180. ! ! ! if (x==5.and.Dm>0.008) diagAlpha= 1.e3*Dm-2.6
  181. ! ! ! diagAlpha= min(diagAlpha, alphaMAX)
  182. ! ! !
  183. ! ! ! END function diagAlpha
  184. ! ! !
  185. ! ! ! !======================================================================!
  186. ! ! !
  187. ! ! ! -- USED BY DIAGNOSTIC-ALPHA DOUBLE-MOMENT (SINGLE-PRECISION) VERSION --
  188. ! ! ! FOR FUTURE VERSIONS OF M-Y PACKAGE WITH, THIS S/R CAN BE USED
  189. ! ! !
  190. ! ! ! real FUNCTION solveAlpha(Q,N,Z,Cx,rho)
  191. ! ! !
  192. ! ! ! IMPLICIT NONE
  193. ! ! !
  194. ! ! ! ! PASSING PARAMETERS:
  195. ! ! ! real, intent(IN) :: Q, N, Z, Cx, rho
  196. ! ! !
  197. ! ! ! ! LOCAL PARAMETERS:
  198. ! ! ! real :: a,g,a1,g1,g2,tmp1
  199. ! ! ! integer :: i
  200. ! ! ! real, parameter :: alphaMax= 40.
  201. ! ! ! real, parameter :: epsQ = 1.e-14
  202. ! ! ! real, parameter :: epsN = 1.e-3
  203. ! ! ! real, parameter :: epsZ = 1.e-32
  204. ! ! !
  205. ! ! ! ! Q mass mixing ratio
  206. ! ! ! ! N total concentration
  207. ! ! ! ! Z reflectivity
  208. ! ! ! ! Cx (pi/6)*RHOx
  209. ! ! ! ! rho air density
  210. ! ! ! ! a alpha (returned as solveAlpha)
  211. ! ! ! ! g function g(a)= [(6+a)(5+a)(4+a)]/[(3+a)(2+a)(1+a)],
  212. ! ! ! ! where g = (Cx/(rho*Q))**2.*(Z*N)
  213. ! ! !
  214. ! ! !
  215. ! ! ! if (Q==0. .or. N==0. .or. Z==0. .or. Cx==0. .or. rho==0.) then
  216. ! ! ! ! For testing/debugging only; this module should never be called
  217. ! ! ! ! if the above condition is true.
  218. ! ! ! print*,'*** STOPPED in MODULE ### solveAlpha *** '
  219. ! ! ! print*,'*** : ',Q,N,Z,Cx*1.9099,rho
  220. ! ! ! stop
  221. ! ! ! endif
  222. ! ! !
  223. ! ! ! IF (Q>epsQ .and. N>epsN .and. Z>epsZ ) THEN
  224. ! ! !
  225. ! ! ! tmp1= Cx/(rho*Q)
  226. ! ! ! g = tmp1*Z*tmp1*N ! g = (Z*N)*[Cx / (rho*Q)]^2
  227. ! ! !
  228. ! ! ! !Note: The above order avoids OVERFLOW, since tmp1*tmp1 is very large
  229. ! ! !
  230. ! ! ! !----------------------------------------------------------!
  231. ! ! ! ! !Solve alpha numerically: (brute-force; for testing only)
  232. ! ! ! ! a= 0.
  233. ! ! ! ! g2= 999.
  234. ! ! ! ! do i=0,4000
  235. ! ! ! ! a1= i*0.01
  236. ! ! ! ! g1= (6.+a1)*(5.+a1)*(4.+a1)/((3.+a1)*(2.+a1)*(1.+a1))
  237. ! ! ! ! if(abs(g-g1)<abs(g-g2)) then
  238. ! ! ! ! a = a1
  239. ! ! ! ! g2= g1
  240. ! ! ! ! endif
  241. ! ! ! ! enddo
  242. ! ! ! !----------------------------------------------------------!
  243. ! ! !
  244. ! ! ! !Piecewise-polynomial approximation of g(a) to solve for a: [2004-11-29]
  245. ! ! ! if (g>=20.) then
  246. ! ! ! a= 0.
  247. ! ! ! else
  248. ! ! ! g2= g*g
  249. ! ! ! if (g<20. .and.g>=13.31) a= 3.3638e-3*g2 - 1.7152e-1*g + 2.0857e+0
  250. ! ! ! if (g<13.31.and.g>=7.123) a= 1.5900e-2*g2 - 4.8202e-1*g + 4.0108e+0
  251. ! ! ! if (g<7.123.and.g>=4.200) a= 1.0730e-1*g2 - 1.7481e+0*g + 8.4246e+0
  252. ! ! ! if (g<4.200.and.g>=2.946) a= 5.9070e-1*g2 - 5.7918e+0*g + 1.6919e+1
  253. ! ! ! if (g<2.946.and.g>=1.793) a= 4.3966e+0*g2 - 2.6659e+1*g + 4.5477e+1
  254. ! ! ! if (g<1.793.and.g>=1.405) a= 4.7552e+1*g2 - 1.7958e+2*g + 1.8126e+2
  255. ! ! ! if (g<1.405.and.g>=1.230) a= 3.0889e+2*g2 - 9.0854e+2*g + 6.8995e+2
  256. ! ! ! if (g<1.230) a= alphaMax
  257. ! ! ! endif
  258. ! ! !
  259. ! ! ! solveAlpha= max(0.,min(a,alphaMax))
  260. ! ! !
  261. ! ! ! ELSE
  262. ! ! !
  263. ! ! ! solveAlpha= 0.
  264. ! ! !
  265. ! ! ! ENDIF
  266. ! ! !
  267. ! ! ! END FUNCTION solveAlpha
  268. !======================================================================!
  269. FUNCTION gammaDP(xx)
  270. ! Modified from "Numerical Recipes"
  271. IMPLICIT NONE
  272. ! PASSING PARAMETERS:
  273. DOUBLE PRECISION, INTENT(IN) :: xx
  274. ! LOCAL PARAMETERS:
  275. DOUBLE PRECISION :: gammaDP
  276. INTEGER :: j
  277. DOUBLE PRECISION :: ser,stp,tmp,x,y,cof(6)
  278. SAVE cof,stp
  279. DATA cof,stp/76.18009172947146d0,-86.50532032941677d0, &
  280. 24.01409824083091d0,-1.231739572450155d0,.1208650973866179d-2, &
  281. -.5395239384953d-5,2.5066282746310005d0/
  282. x=xx
  283. y=x
  284. tmp=x+5.5d0
  285. tmp=(x+0.5d0)*log(tmp)-tmp
  286. ser=1.000000000190015d0
  287. ! do j=1,6 !original
  288. do j=1,4
  289. !!do j=1,3 !gives result to within ~ 3 %
  290. y=y+1.d0
  291. ser=ser+cof(j)/y
  292. enddo
  293. gammaDP=tmp+log(stp*ser/x)
  294. gammaDP= exp(gammaDP)
  295. END FUNCTION gammaDP
  296. !======================================================================!
  297. SUBROUTINE gser(gamser,a,x,gln)
  298. ! USES gammln
  299. ! Returns the incomplete gamma function P(a,x) evaluated by its series
  300. ! representation as gamser. Also returns GAMMA(a) as gln.
  301. implicit none
  302. integer :: itmax
  303. real :: a,gamser,gln,x,eps
  304. parameter (itmax=100, eps=3.e-7)
  305. integer :: n
  306. real :: ap,de1,summ
  307. gln=gammln(a)
  308. if(x.le.0.)then
  309. if(x.lt.0.)pause 'x <0 in gser'
  310. gamser=0.
  311. return
  312. endif
  313. ap=a
  314. summ=1./a
  315. de1=summ
  316. do n=1,itmax
  317. ap=ap+1.
  318. de1=de1*x/ap
  319. summ=summ+de1
  320. if(abs(de1).lt.abs(summ)*eps) goto 1
  321. enddo
  322. pause 'a too large, itmax too small in gser'
  323. 1 gamser=summ*exp(-x+a*log(x)-gln)
  324. return
  325. END SUBROUTINE gser
  326. !======================================================================!
  327. real FUNCTION gammln(xx)
  328. ! Returns value of ln(GAMMA(xx)) for xx>0
  329. ! (modified from "Numerical Recipes")
  330. IMPLICIT NONE
  331. ! PASSING PARAMETERS:
  332. real, intent(IN) :: xx
  333. ! LOCAL PARAMETERS:
  334. integer :: j
  335. real*8 :: ser,stp,tmp,x,y,cof(6)
  336. SAVE cof,stp
  337. DATA cof,stp/76.18009172947146d0,-86.50532032941677d0, &
  338. 24.01409824083091d0,-1.231739572450155d0,.1208650973866179d-2, &
  339. -.5395239384953d-5,2.5066282746310005d0/
  340. x=dble(xx)
  341. y=x
  342. tmp=x+5.5d0
  343. tmp=(x+0.5d0)*log(tmp)-tmp
  344. ser=1.000000000190015d0
  345. do j=1,6 !original
  346. ! do j=1,4
  347. y=y+1.d0
  348. ser=ser+cof(j)/y
  349. enddo
  350. #if (DWORDSIZE == 8 && RWORDSIZE == 8)
  351. gammln= tmp+log(stp*ser/x)
  352. #elif (DWORDSIZE == 8 && RWORDSIZE == 4)
  353. gammln= sngl( tmp+log(stp*ser/x) )
  354. #else
  355. This is a temporary hack assuming double precision is 8 bytes.
  356. #endif
  357. END FUNCTION gammln
  358. !======================================================================!
  359. real FUNCTION gammp(a,x)
  360. ! USES gcf,gser
  361. ! Returns the incomplete gamma function P(a,x)
  362. implicit none
  363. real :: a,x,gammcf,gamser,gln
  364. if(x.lt.0..or.a.le.0.) pause 'bad arguments in gammq'
  365. if(x.lt.a+1.)then
  366. call gser(gamser,a,x,gln)
  367. gammp=gamser
  368. else
  369. call cfg(gammcf,a,x,gln)
  370. gammp=1.-gammcf
  371. endif
  372. return
  373. END FUNCTION gammp
  374. !======================================================================!
  375. SUBROUTINE cfg(gammcf,a,x,gln)
  376. ! USES gammln
  377. ! Returns the incomplete gamma function (Q(a,x) evaluated by tis continued fraction
  378. ! representation as gammcf. Also returns ln(GAMMA(a)) as gln. ITMAX is the maximum
  379. ! allowed number of iterations; EPS is the relative accuracy; FPMIN is a number near
  380. ! the smallest representable floating-point number.
  381. implicit none
  382. integer :: i,itmax
  383. real :: a,gammcf,gln,x,eps,fpmin
  384. real :: an,b,c,d,de1,h
  385. parameter (itmax=100,eps=3.e-7)
  386. gln=gammln(a)
  387. b=x+1.-a
  388. c=1./fpmin
  389. d=1./b
  390. h=d
  391. do i= 1,itmax
  392. an=-i*(i-a)
  393. b=b+2.
  394. d=an*d+b
  395. if(abs(d).lt.fpmin)d=fpmin
  396. c=b+an/c
  397. if(abs(c).lt.fpmin) c=fpmin
  398. d=1./d
  399. de1=d*c
  400. h=h*de1
  401. if(abs(de1-1.).lt.eps) goto 1
  402. enddo
  403. pause 'a too large, itmax too small in gcf'
  404. 1 gammcf=exp(-x+a*log(x)-gln)*h
  405. return
  406. END SUBROUTINE cfg
  407. !======================================================================!
  408. real FUNCTION gamminc(p,xmax)
  409. ! USES gammp, gammln
  410. ! Returns incomplete gamma function, gamma(p,xmax)= P(p,xmax)*GAMMA(p)
  411. real :: p,xmax
  412. gamminc= gammp(p,xmax)*exp(gammln(p))
  413. end FUNCTION gamminc
  414. !======================================================================!
  415. ! real function x_tothe_y(x,y)
  416. !
  417. ! implicit none
  418. ! real, intent(in) :: x,y
  419. ! x_tothe_y= exp(y*log(x))
  420. !
  421. ! end function x_tothe_y
  422. !======================================================================!
  423. end module my_fncs_mod
  424. !________________________________________________________________________________________!
  425. module my_sedi_mod
  426. !================================================================================!
  427. ! The following subroutines are used by the schemes in the multimoment package. !
  428. ! !
  429. ! Package version: 2.19.0 (internal bookkeeping) !
  430. ! Last modified : 2011-01-07 !
  431. !================================================================================!
  432. implicit none
  433. private
  434. public :: SEDI_main_1b,SEDI_main_2,countColumns
  435. contains
  436. !=====================================================================================!
  437. SUBROUTINE SEDI_main_2(QX,NX,cat,Q,T,DE,iDE,gamfact,epsQ,epsN,afx,bfx,cmx,dmx, &
  438. ckQx1,ckQx2,ckQx4,LXP,ni,nk,VxMax,DxMax,dt,DZ,massFlux, &
  439. ktop_sedi,GRAV,massFlux3D)
  440. !-------------------------------------------------------------------------------------!
  441. ! DOUBLE-MOMENT version of sedimentation subroutine for categories whose
  442. ! fall velocity equation is V(D) = gamfact * afx * D^bfx
  443. !-------------------------------------------------------------------------------------!
  444. ! Passing parameters:
  445. !
  446. ! VAR Description
  447. ! --- ------------
  448. ! QX mass mixing ratio of category x
  449. ! NX number concentration of category x
  450. ! cat: hydrometeor category:
  451. ! 1 rain
  452. ! 2 ice
  453. ! 3 snow
  454. ! 4 graupel
  455. ! 5 hail
  456. !-------------------------------------------------------------------------------------!
  457. use my_fncs_mod
  458. implicit none
  459. ! PASSING PARAMETERS:
  460. real, dimension(:,:), intent(inout) :: QX,NX,Q,T
  461. real, dimension(:), intent(out) :: massFlux
  462. real, optional, dimension(:,:), intent(out) :: massFlux3D
  463. real, dimension(:,:), intent(in) :: DE,iDE,DZ
  464. real, intent(in) :: epsQ,epsN,VxMax,LXP,afx,bfx,cmx,dmx,ckQx1,ckQx2,ckQx4,DxMax,dt,GRAV
  465. integer, dimension(:), intent(in) :: ktop_sedi
  466. integer, intent(in) :: ni,nk,cat
  467. ! LOCAL PARAMETERS:
  468. logical :: slabHASmass,locallim,QxPresent
  469. integer :: nnn,a,i,k,counter,l,km1,kp1,ks,kw,idzmin
  470. integer, dimension(nk) :: flim_Q,flim_N
  471. integer, dimension(ni) :: activeColumn,npassx,ke
  472. real :: VqMax,VnMax,iLAMx,iLAMxB0,tmp1,tmp2,tmp3,Dx,iDxMax,icmx, &
  473. VincFact,ratio_Vn2Vq,zmax_Q,zmax_N,tempo,idmx,Nos_Thompson, &
  474. No_s,iLAMs
  475. real, dimension(ni,nk) :: VVQ,VVN,RHOQX,gamfact
  476. real, dimension(ni) :: dzMIN,dtx,VxMaxx
  477. real, dimension(nk) :: vp_Q,vp_N,zt_Q,zt_N,zb_Q,zb_N,dzi,Q_star,N_star
  478. real, dimension(0:nk) :: zz
  479. real, parameter :: epsilon = 1.e-2
  480. real, parameter :: thrd = 1./3.
  481. real, parameter :: sxth = 1./6.
  482. real, parameter :: CoMAX = 2.0
  483. !-------------------------------------------------------------------------------------!
  484. massFlux = 0.
  485. !Factor to estimate increased V from size-sorting:
  486. ! - this factor should be higher for categories with more time-splitting, since Vmax
  487. ! increases after each sedimentation split step (to be tuned)
  488. VincFact = 1.
  489. if (present(massFlux3D)) massFlux3D= 0. !(for use in MAIN for diagnostics)
  490. !Determine for which slabs and columns sedimentation should be computes:
  491. call countColumns(QX,ni,nk,epsQ,counter,activeColumn,ktop_sedi)
  492. ratio_Vn2Vq= ckQx2/ckQx1
  493. iDxMax= 1./DxMax
  494. icmx = 1./cmx
  495. idmx = 1./dmx
  496. ks = nk
  497. ke = ktop_sedi !(i-array) - formerly ke=1; now depends on max. level with hydrometeor
  498. kw = -1 !direction of vertical leveling; -1 implies nk is bottom
  499. VVQ = 0.
  500. VVN = 0.
  501. VqMax= 0.
  502. VnMax= 0.
  503. DO a= 1,counter
  504. i= activeColumn(a)
  505. VVQ(i,:) = 0.
  506. do k= ktop_sedi(i),nk !formerly do k= 1,nk
  507. QxPresent = (QX(i,k)>epsQ .and. NX(i,k)>epsN)
  508. if (QxPresent) VVQ(i,k)= calcVV()*ckQx1
  509. if (present(massFlux3D)) massFlux3D(i,k)= VVQ(i,k)*DE(i,k)*QX(i,k) !(for use in MAIN)
  510. enddo !k-loop
  511. Vxmaxx(i)= min( VxMax, maxval(VVQ(i,:))*VincFact )
  512. !note: dzMIN is min. value in column (not necessarily lowest layer in general)
  513. dzMIN(i) = minval(DZ(i,:))
  514. npassx(i)= max(1, nint( dt*Vxmaxx(i)/(CoMAX*dzMIN(i)) ))
  515. dtx(i) = dt/float(npassx(i))
  516. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  517. DO nnn= 1,npassx(i)
  518. locallim = (nnn==1)
  519. do k= ktop_sedi(i),nk !formerly do k= 1,nk
  520. RHOQX(i,k) = DE(i,k)*QX(i,k)
  521. QxPresent = (QX(i,k)>epsQ .and. NX(i,k)>epsN)
  522. if (QxPresent) then
  523. if (locallim) then !to avoid re-computing VVQ on first pass
  524. VVQ(i,k)= -VVQ(i,k)
  525. else
  526. VVQ(i,k)= -calcVV()*ckQx1
  527. endif
  528. VVN(i,k)= VVQ(i,k)*ratio_Vn2Vq
  529. VqMax = max(VxMAX,-VVQ(i,k))
  530. VnMax = max(VxMAX,-VVN(i,k))
  531. else
  532. VVQ(i,k)= 0.
  533. VVN(i,k)= 0.
  534. VqMax = 0.
  535. VnMax = 0.
  536. endif
  537. enddo !k-loop
  538. !sum instantaneous surface mass flux at each split step: (for division later)
  539. massFlux(i)= massFlux(i) - VVQ(i,nk)*DE(i,nk)*QX(i,nk)
  540. !-- Perform single split sedimentation step:
  541. ! (formerly by calls to s/r 'blg4sedi', a modified [JM] version of 'blg2.ftn')
  542. zz(ks)= 0.
  543. do k= ks,ke(i),kw
  544. zz(k+kw)= zz(k)+dz(i,k)
  545. dzi(k) = 1./dz(i,k)
  546. vp_Q(k) = 0.
  547. vp_N(k) = 0.
  548. enddo
  549. do k=ks,ke(i),kw
  550. zb_Q(k)= zz(k) + VVQ(i,k)*dtx(i)
  551. zb_N(k)= zz(k) + VVN(i,k)*dtx(i)
  552. enddo
  553. zt_Q(ke(i))= zb_Q(ke(i)) + dz(i,ke(i))
  554. zt_N(ke(i))= zb_N(ke(i)) + dz(i,ke(i))
  555. do k= ks,ke(i)-kw,kw
  556. zb_Q(k)= min(zb_Q(k+kw)-epsilon*dz(i,k), zz(k)+VVQ(i,k)*dtx(i))
  557. zb_N(k)= min(zb_N(k+kw)-epsilon*dz(i,k), zz(k)+VVN(i,k)*dtx(i))
  558. zt_Q(k)= zb_Q(k+kw)
  559. zt_N(k)= zb_N(k+kw)
  560. enddo
  561. do k=ks,ke(i),kw !formerly k=1,nk
  562. Q_star(k)= RHOQX(i,k)*dz(i,k)/(zt_Q(k)-zb_Q(k))
  563. N_star(k)= NX(i,k)*dz(i,k)/(zt_N(k)-zb_N(k))
  564. enddo
  565. if (locallim) then
  566. zmax_Q= abs(VqMax*dtx(i))
  567. zmax_N= abs(VnMax*dtx(i))
  568. do l=ks,ke(i),kw
  569. flim_Q(l)= l
  570. flim_N(l)= l
  571. do k= l,ke(i),kw
  572. if (zmax_Q.ge.zz(k)-zz(l+kw)) flim_Q(l)= k
  573. if (zmax_N.ge.zz(k)-zz(l+kw)) flim_N(l)= k
  574. enddo
  575. enddo
  576. endif
  577. do l=ks,ke(i),kw
  578. do k=l,flim_Q(l),kw
  579. vp_Q(l)= vp_Q(l) + Q_star(k)*max(0.,min(zz(l+kw),zt_Q(k))-max(zz(l),zb_Q(k)))
  580. enddo
  581. do k=l,flim_N(l),kw
  582. vp_N(l)= vp_N(l) + N_star(k)*max(0.,min(zz(l+kw),zt_N(k))-max(zz(l),zb_N(k)))
  583. enddo
  584. enddo
  585. do k=ks,ke(i),kw
  586. RHOQX(i,k)= vp_Q(k)*dzi(k)
  587. NX(i,k)= vp_N(k)*dzi(k)
  588. enddo
  589. !--
  590. do k= ktop_sedi(i),nk !formerly do k= 1,nk
  591. QX(i,k)= RHOQX(i,k)*iDE(i,k)
  592. !Prevent levels with zero N and nonzero Q and size-limiter:
  593. QxPresent= (QX(i,k)>epsQ .and. NX(i,k)>epsN)
  594. if (QxPresent) then !size limiter
  595. Dx= (DE(i,k)*QX(i,k)/(NX(i,k)*cmx))**idmx
  596. if (cat==1 .and. Dx>3.e-3) then
  597. tmp1 = Dx-3.e-3; tmp1= tmp1*tmp1
  598. tmp2 = (Dx/DxMAX); tmp2= tmp2*tmp2*tmp2
  599. NX(i,k)= NX(i,k)*max((1.+2.e4*tmp1),tmp2)
  600. else
  601. NX(i,k)= NX(i,k)*(max(Dx,DxMAX)*iDxMAX)**dmx !impose Dx_max
  602. endif
  603. else !here, "QxPresent" implies correlated QX and NX
  604. Q(i,k) = Q(i,k) + QX(i,k)
  605. T(i,k) = T(i,k) - LXP*QX(i,k) !LCP for rain; LSP for i,s,g,h
  606. QX(i,k)= 0.
  607. NX(i,k)= 0.
  608. endif
  609. enddo
  610. ENDDO !nnn-loop
  611. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  612. !compute average mass flux during the full time step: (used to compute the
  613. !instantaneous sedimentation rate [liq. equiv. volume flux] in the main s/r)
  614. massFlux(i)= massFlux(i)/float(npassx(i))
  615. ENDDO !a(i)-loop
  616. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  617. CONTAINS
  618. real function calcVV()
  619. !Calculates portion of moment-weighted fall velocities
  620. iLAMx = ((QX(i,k)*DE(i,k)/NX(i,k))*ckQx4)**idmx
  621. iLAMxB0 = iLAMx**bfx
  622. calcVV = gamfact(i,k)*iLAMxB0
  623. end function calcVV
  624. END SUBROUTINE SEDI_main_2
  625. !=====================================================================================!
  626. SUBROUTINE SEDI_main_1b(QX,cat,T,DE,iDE,gamfact,epsQ,afx,bfx,icmx,dmx,ckQx1,ckQx4, &
  627. ni,nk,VxMax,DxMax,dt,DZ,massFlux,No_x,ktop_sedi,GRAV, &
  628. massFlux3D)
  629. !-------------------------------------------------------------------------------------!
  630. ! SINGLE-MOMENT version of sedimentation subroutine for categories whose
  631. ! fall velocity equation is V(D) = gamfact * afx * D^bfx
  632. !-------------------------------------------------------------------------------------!
  633. ! Passing parameters:
  634. !
  635. ! VAR Description
  636. ! --- ------------
  637. ! QX mass mixing ratio of category x
  638. ! cat: hydrometeor category:
  639. ! 1 rain
  640. ! 2 ice
  641. ! 3 snow
  642. ! 4 graupel
  643. ! 5 hail
  644. !-------------------------------------------------------------------------------------!
  645. use my_fncs_mod
  646. implicit none
  647. ! PASSING PARAMETERS:
  648. real, dimension(:,:), intent(inout) :: QX,T
  649. real, dimension(:), intent(out) :: massFlux
  650. real, optional, dimension(:,:), intent(out) :: massFlux3D
  651. real, dimension(:,:), intent(in) :: DE,iDE,DZ
  652. real, intent(in) :: epsQ,VxMax,afx,bfx,icmx,dmx,ckQx1,ckQx4,DxMax,dt,GRAV,No_x
  653. integer, dimension(:), intent(in) :: ktop_sedi
  654. integer, intent(in) :: ni,nk,cat !,ktop_sedi
  655. ! LOCAL PARAMETERS:
  656. logical :: slabHASmass,locallim,QxPresent
  657. integer :: nnn,a,i,k,counter,l,km1,kp1,ks,kw,idzmin !,ke
  658. integer, dimension(nk) :: flim_Q
  659. integer, dimension(ni) :: activeColumn,npassx,ke
  660. real :: VqMax,iLAMx,iLAMxB0,tmp1,tmp2,Dx,iDxMax,VincFact,NX,iNo_x, &
  661. zmax_Q,zmax_N,tempo
  662. real, dimension(ni,nk) :: VVQ,RHOQX,gamfact
  663. real, dimension(ni) :: dzMIN,dtx,VxMaxx
  664. real, dimension(nk) :: vp_Q,zt_Q,zb_Q,dzi,Q_star
  665. real, dimension(0:nk) :: zz
  666. real, parameter :: epsilon = 1.e-2
  667. real, parameter :: thrd = 1./3.
  668. real, parameter :: sxth = 1./6.
  669. real, parameter :: CoMAX = 2.0
  670. !-------------------------------------------------------------------------------------!
  671. massFlux= 0.
  672. !Factor to estimate increased V from size-sorting:
  673. ! - this factor should be higher for categories with more time-splitting, since Vmax
  674. ! increases after each sedimentation split step (to be tuned)
  675. VincFact= 1.
  676. if (present(massFlux3D)) massFlux3D= 0. !(for use in MAIN for diagnostics)
  677. !Determine for which slabs and columns sedimentation should be computes:
  678. call countColumns(QX,ni,nk,epsQ,counter,activeColumn,ktop_sedi)
  679. iNo_x = 1./No_x
  680. iDxMax= 1./DxMax
  681. ks = nk
  682. ke = ktop_sedi !(i-array) - old: ke=1
  683. kw = -1 !direction of vertical leveling
  684. VVQ = 0.
  685. VqMax= 0.
  686. DO a= 1,counter
  687. i= activeColumn(a)
  688. VVQ(i,:) = 0.
  689. do k= ktop_sedi(i),nk !do k= 1,nk
  690. QxPresent = (QX(i,k)>epsQ)
  691. ! if (QxPresent) VVQ(i,k)= calcVV()*ckQx1
  692. if (QxPresent) then
  693. !ice:
  694. if (cat==2) then
  695. NX = 5.*exp(0.304*(273.15-max(233.,T(i,k))))
  696. iLAMx = (ckQx4*QX(i,k)*DE(i,k)/NX)**thrd
  697. !snow:
  698. else if (cat==3) then
  699. iNo_x = 1./min(2.e+8, 2.e+6*exp(-0.12*min(-0.001,T(i,k)-273.15)))
  700. iLAMx = sqrt(sqrt(QX(i,k)*DE(i,k)*icmx*sxth*iNo_x))
  701. !rain, graupel, hail:
  702. else
  703. iLAMx = sqrt(sqrt(QX(i,k)*DE(i,k)*icmx*sxth*iNo_x))
  704. endif
  705. VVQ(i,k) = -gamfact(i,k)*ckQx1*iLAMx**bfx
  706. ! VqMax = max(VxMAX,-VVQ(i,k))
  707. endif
  708. if (present(massFlux3D)) massFlux3D(i,k)= -VVQ(i,k)*DE(i,k)*QX(i,k) !(for use in MAIN)
  709. enddo !k-loop
  710. Vxmaxx(i)= min( VxMax, maxval(VVQ(i,:))*VincFact )
  711. !note: dzMIN is min. value in column (not necessarily lowest layer in general)
  712. dzMIN(i) = minval(DZ(i,:))
  713. npassx(i)= max(1, nint( dt*Vxmaxx(i)/(CoMAX*dzMIN(i)) ))
  714. dtx(i) = dt/float(npassx(i))
  715. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  716. DO nnn= 1,npassx(i)
  717. locallim = (nnn==1)
  718. do k= ktop_sedi(i),nk !do k= 1,nk
  719. RHOQX(i,k) = DE(i,k)*QX(i,k)
  720. QxPresent = (QX(i,k)>epsQ)
  721. if (QxPresent) then
  722. !ice:
  723. if (cat==2) then
  724. NX = 5.*exp(0.304*(273.15-max(233.,T(i,k))))
  725. iLAMx = (ckQx4*QX(i,k)*DE(i,k)/NX)**thrd
  726. !snow:
  727. else if (cat==3) then
  728. iNo_x = 1./min(2.e+8, 2.e+6*exp(-0.12*min(-0.001,T(i,k)-273.15)))
  729. iLAMx = sqrt(sqrt(QX(i,k)*DE(i,k)*icmx*sxth*iNo_x))
  730. !rain, graupel, hail:
  731. else
  732. iLAMx = sqrt(sqrt(QX(i,k)*DE(i,k)*icmx*sxth*iNo_x))
  733. endif
  734. VVQ(i,k) = -gamfact(i,k)*ckQx1*iLAMx**bfx
  735. VqMax = max(VxMAX,-VVQ(i,k))
  736. endif
  737. enddo !k-loop
  738. !-- Perform single split sedimentation step: (formerly by calls to s/r 'blg4sedi')
  739. zz(ks)= 0.
  740. do k= ks,ke(i),kw
  741. zz(k+kw)= zz(k)+dz(i,k)
  742. dzi(k) = 1./dz(i,k)
  743. vp_Q(k) = 0.
  744. enddo
  745. do k=ks,ke(i),kw
  746. zb_Q(k)= zz(k) + VVQ(i,k)*dtx(i)
  747. enddo
  748. zt_Q(ke(i))= zb_Q(ke(i)) + dz(i,ke(i))
  749. do k= ks,ke(i)-kw,kw
  750. zb_Q(k)= min(zb_Q(k+kw)-epsilon*dz(i,k), zz(k)+VVQ(i,k)*dtx(i))
  751. zt_Q(k)= zb_Q(k+kw)
  752. enddo
  753. do k=ks,ke(i),kw !k=1,nk
  754. Q_star(k)= RHOQX(i,k)*dz(i,k)/(zt_Q(k)-zb_Q(k))
  755. enddo
  756. if (locallim) then
  757. zmax_Q= abs(VqMax*dtx(i))
  758. do l=ks,ke(i),kw
  759. flim_Q(l)= l
  760. do k= l,ke(i),kw
  761. if (zmax_Q.ge.zz(k)-zz(l+kw)) flim_Q(l)= k
  762. enddo
  763. enddo
  764. endif
  765. do l=ks,ke(i),kw
  766. do k=l,flim_Q(l),kw
  767. vp_Q(l)= vp_Q(l) + Q_star(k)*max(0.,min(zz(l+kw),zt_Q(k))-max(zz(l),zb_Q(k)))
  768. enddo
  769. enddo
  770. do k=ks,ke(i),kw
  771. RHOQX(i,k)= vp_Q(k)*dzi(k)
  772. enddo
  773. !--
  774. do k= ktop_sedi(i),nk ! do k= 1,nk
  775. QX(i,k)= RHOQX(i,k)*iDE(i,k)
  776. enddo
  777. !sum instantaneous flux at each split step: (for division later)
  778. massFlux(i)= massFlux(i) - VVQ(i,nk)*DE(i,nk)*QX(i,nk)
  779. ENDDO !nnn-loop
  780. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  781. !compute average flux during the full time step: (this will be used to compute
  782. ! the instantaneous sedimentation rate [volume flux] in the main s/r)
  783. massFlux(i)= massFlux(i)/float(npassx(i))
  784. ENDDO !a(i)-loop
  785. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  786. END SUBROUTINE SEDI_main_1b
  787. !=====================================================================================!
  788. SUBROUTINE countColumns(QX,ni,nk,minQX,counter,activeColumn,ktop_sedi)
  789. ! Searches the hydrometeor array QX(ni,nk) for non-zero (>minQX) values.
  790. ! Returns the array if i-indices (activeColumn) for the columns (i)
  791. ! which contain at least one non-zero value, as well as the number of such
  792. ! columns (counter).
  793. implicit none
  794. !PASSING PARAMETERS:
  795. integer, intent(in) :: ni,nk !,ktop_sedi
  796. integer, dimension(:), intent(in) :: ktop_sedi
  797. integer, intent(out) :: counter
  798. integer, dimension(:), intent(out) :: activeColumn
  799. real, dimension(:,:), intent(in) :: QX
  800. real, intent(in) :: minQX
  801. !LOCAL PARAMETERS:
  802. integer :: i !,k
  803. integer, dimension(ni) :: k
  804. ! k= ktop_sedi-1 ! k=0
  805. counter = 0
  806. activeColumn= 0
  807. do i=1,ni
  808. k(i)= ktop_sedi(i)-1 ! k=0
  809. do
  810. k(i)=k(i)+1
  811. if (QX(i,k(i))>minQX) then
  812. counter=counter+1
  813. activeColumn(counter)=i
  814. k(i)=0
  815. exit
  816. else
  817. if (k(i)==nk) then
  818. k(i)=0
  819. exit
  820. endif
  821. endif
  822. enddo
  823. enddo !i-loop
  824. END SUBROUTINE countColumns
  825. !=====================================================================================!
  826. end module my_sedi_mod
  827. !________________________________________________________________________________________!
  828. module my_dmom_mod
  829. implicit none
  830. private
  831. public :: mp_milbrandt2mom_main
  832. contains
  833. !_______________________________________________________________________________________!
  834. SUBROUTINE mp_milbrandt2mom_main(W_omega,T,Q,QC,QR,QI,QN,QG,QH,NC,NR,NY,NN,NG,NH,PS,TM, &
  835. QM,QCM,QRM,QIM,QNM,QGM,QHM,NCM,NRM,NYM,NNM,NGM,NHM,PSM,S,RT_rn1,RT_rn2,RT_fr1,RT_fr2,&
  836. RT_sn1,RT_sn2,RT_sn3,RT_pe1,RT_pe2,RT_peL,RT_snd,GZ,T_TEND,Q_TEND,QCTEND,QRTEND, &
  837. QITEND,QNTEND,QGTEND,QHTEND,NCTEND,NRTEND,NYTEND,NNTEND,NGTEND,NHTEND,dt,NI,N,NK, &
  838. J,KOUNT,CCNtype,precipDiag_ON,sedi_ON,warmphase_ON,autoconv_ON,icephase_ON,snow_ON, &
  839. initN,dblMom_c,dblMom_r,dblMom_i,dblMom_s,dblMom_g,dblMom_h,Dm_c,Dm_r,Dm_i,Dm_s, &
  840. Dm_g,Dm_h,ZET,ZEC,SLW,VIS,VIS1,VIS2,VIS3,h_CB,h_ML1,h_ML2,h_SN,SS01,SS02,SS03,SS04, &
  841. SS05,SS06,SS07,SS08,SS09,SS10,SS11,SS12,SS13,SS14,SS15,SS16,SS17,SS18,SS19,SS20)
  842. use my_fncs_mod
  843. use my_sedi_mod
  844. !--WRF:
  845. use module_model_constants, ONLY: CPD => cp, CPV => cpv, RGASD => r_d, RGASV => r_v, &
  846. EPS1 => EP_2, DELTA => EP_1, CAPPA => rcp, GRAV => g, CHLC => XLV, CHLF => XLF
  847. !==
  848. implicit none
  849. !CALLING PARAMETERS:
  850. integer, intent(in) :: NI,NK,N,J,KOUNT,CCNtype
  851. real, intent(in) :: dt
  852. real, dimension(:), intent(in) :: PS,PSM
  853. real, dimension(:), intent(out) :: h_CB,h_ML1,h_ML2,h_SN
  854. real, dimension(:), intent(out) :: RT_rn1,RT_rn2,RT_fr1,RT_fr2,RT_sn1,RT_sn2, &
  855. RT_sn3,RT_pe1,RT_pe2,RT_peL,ZEC,RT_snd
  856. real, dimension(:,:), intent(in) :: W_omega,S,GZ
  857. real, dimension(:,:), intent(inout) :: T,Q,QC,QR,QI,QN,QG,QH,NC,NR,NY,NN,NG,NH, &
  858. TM,QM,QCM,QRM,QIM,QNM,QGM,QHM,NCM,NRM,NYM,NNM,NGM,NHM
  859. real, dimension(:,:), intent(out) :: T_TEND,QCTEND,QRTEND,QITEND,QNTEND, &
  860. QGTEND,QHTEND,Q_TEND,NCTEND,NRTEND,NYTEND,NNTEND,NGTEND,NHTEND,ZET,Dm_c, &
  861. Dm_r,Dm_i,Dm_s,Dm_g,Dm_h,SLW,VIS,VIS1,VIS2,VIS3,SS01,SS02,SS03,SS04,SS05,SS06, &
  862. SS07,SS08,SS09,SS10,SS11,SS12,SS13,SS14,SS15,SS16,SS17,SS18,SS19,SS20
  863. logical, intent(in) :: dblMom_c,dblMom_r,dblMom_i,dblMom_s, &
  864. dblMom_g,dblMom_h,precipDiag_ON,sedi_ON,icephase_ON,snow_ON,warmphase_ON, &
  865. autoconv_ON,initN
  866. !_______________________________________________________________________________________
  867. ! !
  868. ! Milbrandt-Yau Multimoment Bulk Microphysics Scheme !
  869. ! - double-moment version - !
  870. !_______________________________________________________________________________________!
  871. ! Package version: 2.19.0 (internal bookkeeping) !
  872. ! Last modified : 2011-03-02 !
  873. !_______________________________________________________________________________________!
  874. !
  875. ! Author:
  876. ! J. Milbrandt, McGill University (August 2004)
  877. !
  878. ! Major revisions:
  879. !
  880. ! 001 J. Milbrandt (Dec 2006) - Converted the full Milbrandt-Yau (2005) multimoment
  881. ! (RPN) scheme to an efficient fixed-dispersion double-moment
  882. ! version
  883. ! 002 J. Milbrandt (Mar 2007) - Added options for single-moment/double-moment for
  884. ! each hydrometeor category
  885. ! 003 J. Milbrandt (Feb 2008) - Modified single-moment version for use in GEM-LAM-2.5
  886. ! 004 J. Milbrandt (Nov 2008) - Modified double-moment version for use in 2010 Vancouver
  887. ! Olympics GEM-LAM configuration
  888. ! 005 J. Milbrandt (Aug 2009) - Modified (dmom) for PHY_v5.0.4, for use in V2010 system:
  889. ! + reduced ice/snow capacitance to C=0.25D (from C=0.5D)
  890. ! + added diagnostic fields (VIS, levels, etc.)
  891. ! + added constraints to snow size distribution (No_s and
  892. ! LAMDA_s limits, plus changed m-D parameters
  893. ! + modified solid-to-liquid ratio calculation, based on
  894. ! volume flux (and other changes)
  895. ! + added back sedimentation of ice category
  896. ! + modified condition for conversion of graupel to hail
  897. ! + corrected bug it diagnostic "ice pellets" vs. "hail"
  898. ! + minor bug corrections (uninitialized values, etc.)
  899. ! 006 J. Milbrandt (Jan 2011) - Bug fixes and minor code clean-up from PHY_v5.1.3 version
  900. ! + corrected latent heat constants in thermodynamic functions
  901. ! (ABi and ABw) for sublimation and evaporation
  902. ! + properly initialized variables No_g and No_h
  903. ! + changed max ice crystal size (fallspeed) to 5 mm (2 m s-1)
  904. ! + imposed maximum ice number concentration of 1.e+7 m-3
  905. ! + removed unused supersaturation reduction
  906. !
  907. ! Object:
  908. ! Computes changes to the temperature, water vapor mixing ratio, and the
  909. ! mixing ratios and total number concentrations of six hydrometeor species
  910. ! resulting from cloud microphysical interactions at saturated grid points.
  911. ! Liquid and solid surface precipitation rates from sedimenting hydrometeor
  912. ! categories are also computed.
  913. !
  914. ! This subroutine and the associated modules form the single/double-moment
  915. ! switchable verion of the multimoment bulk microphysics package, the full
  916. ! version of which is described in the references below.
  917. !
  918. ! References: Milbrandt and Yau, (2005a), J. Atmos. Sci., vol.62, 3051-3064
  919. ! --------- and ---, (2005b), J. Atmos. Sci., vol.62, 3065-3081
  920. ! (and references therein)
  921. !
  922. ! Please report bugs to: jason.milbrandt@ec.gc.ca
  923. !_______________________________________________________________________________________!
  924. !
  925. ! Arguments: Description: Units:
  926. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  927. ! - Input -
  928. !
  929. ! NI number of x-dir points (in local subdomain)
  930. ! NK number of vertical levels
  931. ! N not used (to be removed)
  932. ! J y-dir index (local subdomain)
  933. ! KOUNT current model time step number
  934. ! dt model time step [s]
  935. ! CCNtype switch for airmass type
  936. ! 1 = maritime --> N_c = 80 cm-3 (1-moment cloud)
  937. ! 2 = continental 1 --> N_c = 200 cm-3 " "
  938. ! 3 = continental 2 (polluted) --> N_c = 500 cm-3 " "
  939. ! 4 = land-sea-mask-dependent (TBA)
  940. ! W_omega vertical velocity [Pa s-1]
  941. ! S sigma (=p/p_sfc)
  942. ! GZ geopotential
  943. ! dblMom_(x) logical switch for double(T)-single(F)-moment for category (x)
  944. ! precipDiag_ON logical switch, .F. to suppress calc. of sfc precip types
  945. ! sedi_ON logical switch, .F. to suppress sedimentation
  946. ! warmphase_ON logical switch, .F. to suppress warm-phase (Part II)
  947. ! autoconv_ON logical switch, .F. to supppress autoconversion (cld->rn)
  948. ! icephase_ON logical switch, .F. to suppress ice-phase (Part I)
  949. ! snow_ON logical switch, .F. to suppress snow initiation
  950. !
  951. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  952. ! - Input/Output -
  953. !
  954. ! T air temperature at time (t*) [K]
  955. ! TM air temperature at time (t-dt) [K]
  956. ! Q water vapor mixing ratio at (t*) [kg kg-1]
  957. ! QM water vapor mixing ratio at (t-dt) [kg kg-1]
  958. ! PS surface pressure at time (t*) [Pa]
  959. ! PSM surface pressure at time (t-dt) [Pa]
  960. !
  961. ! For x = (C,R,I,N,G,H): C = cloud
  962. ! R = rain
  963. ! I = ice (pristine) [except 'NY', not 'NI']
  964. ! N = snow
  965. ! G = graupel
  966. ! H = hail
  967. !
  968. ! Q(x) mixing ratio for hydrometeor x at (t*) [kg kg-1]
  969. ! Q(x)M mixing ratio for hydrometeor x at (t-dt) [kg kg-1]
  970. ! N(x) total number concentration for hydrometeor x (t*) [m-3]
  971. ! N(x)M total number concentration for hydrometeor x (t-dt) [m-3]
  972. !
  973. ! Note: The arrays "VM" (e.g. variables TM,QM,QCM etc.) are declared as INTENT(INOUT)
  974. ! such that their values are modified in the code [VM = 0.5*(VM + V)].
  975. ! This is to approxiate the values at time level (t), which are needed by
  976. ! this routine but are unavailable to the PHYSICS. The new values are discared
  977. ! by the calling routine ('vkuocon6.ftn'). However, care should be taken with
  978. ! interfacing with other modelling systems. For GEM/MC2, it does not matter if
  979. ! VM is modified since the calling module passes back only the tendencies
  980. ! (VTEND) to the model.
  981. !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -!
  982. ! - Output -
  983. !
  984. ! Q_TEND tendency for water vapor mixing ratio [kg kg-1 s-1]
  985. ! T_TEND tendency for air temperature [K s-1]
  986. ! Q(x)TEND tendency for mixing ratio for hydrometeor x [kg kg-1 s-1]
  987. ! N(x)TEND tendency for number concentration for hydrometeor x [m-3 s-1]
  988. ! Dm_(x) mean-mass diameter for hydrometeor x [m]
  989. ! H_CB height of cloud base [m]
  990. ! h_ML1 height of first melting level from ground [m]
  991. ! h_ML2 height of first melting level from top [m]
  992. ! h_SN height of snow level [m]
  993. ! RT_rn1 precipitation rate (at sfc) of liquid rain [m+3 m-2 s-1]
  994. ! RT_rn2 precipitation rate (at sfc) of liquid drizzle [m+3 m-2 s-1]
  995. ! RT_fr1 precipitation rate (at sfc) of freezing rain [m+3 m-2 s-1]
  996. ! RT_fr2 precipitation rate (at sfc) of freezing drizzle [m+3 m-2 s-1]
  997. ! RT_sn1 precipitation rate (at sfc) of ice crystals (liq-eq) [m+3 m-2 s-1]
  998. ! RT_sn2 precipitation rate (at sfc) of snow (liq-equiv) [m+3 m-2 s-1]
  999. ! RT_sn3 precipitation rate (at sfc) of graupel (liq-equiv) [m+3 m-2 s-1]
  1000. ! RT_snd precipitation rate (at sfc) of snow (frozen) [m+3 m-2 s-1]
  1001. ! RT_pe1 precipitation rate (at sfc) of ice pellets (liq-eq) [m+3 m-2 s-1]
  1002. ! RT_pe2 precipitation rate (at sfc) of hail (total; liq-eq) [m+3 m-2 s-1]
  1003. ! RT_peL precipitation rate (at sfc) of hail (large only) [m+3 m-2 s-1]
  1004. ! SSxx S/S terms (for testing purposes)
  1005. ! SLW supercooled liquid water content [kg m-3]
  1006. ! VIS visibility resulting from fog, rain, snow [m]
  1007. ! VIS1 visibility component through liquid cloud (fog) [m]
  1008. ! VIS2 visibility component through rain [m]
  1009. ! VIS3 visibility component through snow [m]
  1010. ! ZET total equivalent radar reflectivity [dBZ]
  1011. ! ZEC composite (column-max) of ZET [dBZ]
  1012. !_______________________________________________________________________________________!
  1013. !LOCAL VARIABLES:
  1014. !Variables to count active grid points:
  1015. logical :: log1,log2,log3,log4,doneK,rainPresent,calcDiag,CB_found,ML_found, &
  1016. SN_found
  1017. logical, dimension(size(QC,dim=1),size(QC,dim=2)) :: activePoint
  1018. integer, dimension(size(QC,dim=1)) :: ktop_sedi
  1019. integer :: i,k,niter,ll,start
  1020. real :: tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7,tmp8,tmp9,tmp10, &
  1021. VDmax,NNUmax,X,D,DEL,QREVP,NuDEPSOR,NuCONTA,NuCONTB,NuCONTC,iMUkin,Ecg,Erg, &
  1022. NuCONT,GG,Na,Tcc,F1,F2,Kdiff,PSIa,Kn,source,sink,sour,ratio,qvs0,Kstoke, &
  1023. DELqvs,ft,esi,Si,Simax,Vq,Vn,Vz,LAMr,No_r_DM,No_i,No_s,No_g,No_h,D_sll, &
  1024. iABi,ABw,VENTr,VENTs,VENTg,VENTi,VENTh,Cdiff,Ka,MUdyn,MUkin,DEo,Ng_tail, &
  1025. gam,ScTHRD,Tc,mi,ff,Ec,Ntr,Dho,DMrain,Ech,DMice,DMsnow,DMgrpl,DMhail, &
  1026. ssat,Swmax,dey,Esh,Eii,Eis,Ess,Eig,Eih,FRAC,JJ,Dirg,Dirh,Dsrs,Dsrg,Dsrh, &
  1027. Dgrg,Dgrh,SIGc,L,TAU,DrAUT,DrINIT,Di,Ds,Dg,Dh,qFact,nFact,Ki,Rz,NgCNgh, &
  1028. vr0,vi0,vs0,vg0,vh0,Dc,Dr,QCLcs,QCLrs,QCLis,QCLcg,QCLrg,QCLig,NhCNgh, &
  1029. QCLch,QCLrh,QCLsh,QMLir,QMLsr,QMLgr,QMLhr,QCLih,QVDvg,QVDvh,QSHhr, &
  1030. QFZci,QNUvi,QVDvi,QCNis,QCNis1,QCNis2,QCLir,QCLri,QCNsg,QCLsr,QCNgh, &
  1031. QCLgr,QHwet,QVDvs,QFZrh,QIMsi,QIMgi,NMLhr,NVDvh,NCLir,NCLri,NCLrh, &
  1032. NCLch,NCLsr,NCLirg,NCLirh,NrFZrh,NhFZrh,NCLsrs,NCLsrg,NCLsrh,NCLgrg, &
  1033. NCLgrh,NVDvg,NMLgr,NiCNis,NsCNis,NVDvs,NMLsr,NCLsh,NCLss,NNUvi,NFZci,NVDvi, &
  1034. NCLis,NCLig,NCLih,NMLir,NCLrs,NCNsg,NCLcs,NCLcg,NIMsi,NIMgi,NCLgr,NCLrg, &
  1035. NSHhr,RCAUTR,RCACCR,CCACCR,CCSCOC,CCAUTR,CRSCOR,ALFx,des_pmlt,Ecs,des,ides, &
  1036. LAMx,iLAMx,iLAMxB0,Dx,ffx,iLAMc,iNCM,iNRM,iNYM,iNNM,iNGM,iLAMs_D3, &
  1037. iLAMg,iLAMg2,iLAMgB0,iLAMgB1,iLAMgB2,iLAMh,iLAMhB0,iLAMhB1,iLAMhB2,iNHM, &
  1038. iLAMi,iLAMi2,iLAMi3,iLAMi4,iLAMi5,iLAMiB0,iLAMiB1,iLAMiB2,iLAMr6,iLAMh2, &
  1039. iLAMs,iLAMs2,iLAMsB0,iLAMsB1,iLAMsB2,iLAMr,iLAMr2,iLAMr3,iLAMr4,iLAMr5, &
  1040. iLAMc2,iLAMc3,iLAMc4,iLAMc5,iLAMc6,iQCM,iQRM,iQIM,iQNM,iQGM,iQHM,iEih,iEsh, &
  1041. N_c,N_r,N_i,N_s,N_g,N_h,fluxV_i,fluxV_g,fluxV_s,rhos_mlt,fracLiq
  1042. !Variables that only need to be calulated on the first step (and saved):
  1043. real, save :: idt,iMUc,cmr,cmi,cms,cmg,cmh,icmr,icmi,icmg,icms,icmh,idew,idei, &
  1044. ideh,ideg,GC1,imso,icexc9,cexr1,cexr2,cexr3,No_s_SM,No_r,idms,imgo,icexs2, &
  1045. cexr4,cexr5,cexr6,cexr9,icexr9,ckQr1,ckQr2,ckQr3,ckQi1,ckQi2,ckQi3,ckQi4, &
  1046. icexi9,ckQs1,ckQs2,cexs1,cexs2,ckQg1,ckQg2,ckQg4,ckQh1,ckQh2,ckQh4,GR37,dms, &
  1047. LCP,LFP,LSP,ck5,ck6,PI2,PIov4,PIov6,CHLS,iCHLF,cxr,cxi,Gzr,Gzi,Gzs,Gzg,Gzh, &
  1048. N_c_SM,iGC1,GC2,GC3,GC4,GC5,iGC5,GC6,GC7,GC8,GC11,GC12,GC13,GC14,iGR34,mso, &
  1049. GC15,GR1,GR3,GR13,GR14,GR15,GR17,GR31,iGR31,GR32,GR33,GR34,GR35,GR36,GI4, &
  1050. GI6,GI20,GI21,GI22,GI31,GI32,GI33,GI34,GI35,iGI31,GI11,GI36,GI37,GI40,iGG34, &
  1051. GS09,GS11,GS12,GS13,iGS20,GS31,iGS31,GS32,GS33,GS34,GS35,GS36,GS40,iGS40, &
  1052. GS50,GG09,GG11,GG12,GG13,GG31,iGG31,GG32,GG33,GG34,GG35,GG36,GG40,iGG99,GH09,&
  1053. GH11,GH12,GH13,GH31,GH32,GH33,GH40,GR50,GG50,iGH34,GH50,iGH99,iGH31,iGS34, &
  1054. iGS20_D3,GS40_D3,cms_D3,eds,fds,rfact_FvFm
  1055. !Size distribution parameters:
  1056. real, parameter :: MUc = 3. !shape parameter for cloud
  1057. real, parameter :: alpha_c = 1. !shape parameter for cloud
  1058. real, parameter :: alpha_r = 0. !shape parameter for rain
  1059. real, parameter :: alpha_i = 0. !shape parameter for ice
  1060. real, parameter :: alpha_s = 0. !shape parameter for snow
  1061. real, parameter :: alpha_g = 0. !shape parameter for graupel
  1062. real, parameter :: alpha_h = 0. !shape parameter for hail
  1063. real, parameter :: No_s_max = 1.e+8 !max. allowable intercept for snow [m-4]
  1064. real, parameter :: lamdas_min= 500. !min. allowable LAMDA_s [m-1]
  1065. !For single-moment:
  1066. real, parameter :: No_r_SM = 1.e+7 !intercept parameter for rain [m-4]
  1067. real, parameter :: No_g_SM = 4.e+6 !intercept parameter for graupel [m-4]
  1068. real, parameter :: No_h_SM = 1.e+5 !intercept parameter for hail [m-4]
  1069. !note: No_s = f(T), rather than a fixed value
  1070. !------------------------------------!
  1071. ! Symbol convention: (dist. params.) ! MY05: Milbrandt & Yau, 2005a,b (JAS)
  1072. ! MY05 F94 CP00 ! F94: Ferrier, 1994 (JAS)
  1073. ! ------ -------- ------ ! CP00: Cohard & Pinty, 2000a,b (QJGR)
  1074. ! ALFx ALPHAx MUx-1 !
  1075. ! MUx (1) ALPHAx !
  1076. ! ALFx+1 ALPHAx+1 MUx !
  1077. !-------------------

Large files files are truncated, but you can click here to view the full file