FV3 Bundle
bldriver.F90
Go to the documentation of this file.
1 MODULE bldriver
2 
3 !This subroutine takes the model prognostic variables as its inputs and produces
4 !the three components of the tri-diagonal matrix used to compute BL diffusion.
5 !Diffusion coefficient is computed using Louis-Lock formulation.
6 
9 
10 IMPLICIT NONE
11 
12 PRIVATE
13 PUBLIC bl_driver
14 
15 !Saturation vapor pressure table ESTBLX initialization.
16 !To be defined for entire module:
17 integer, parameter :: degsubs = 100
18 real(kind_real), parameter :: tmintbl = 150.0, tmaxtbl = 333.0
19 integer, parameter :: tablesize = nint(tmaxtbl-tmintbl)*degsubs + 1
20 
21 CONTAINS
22 
23 subroutine bl_driver ( IM, JM, LM, DT, U, V, TH, Q, P, QIT, QLT, FRLAND, FROCEAN, VARFLT, &
24  ZPBL, CM, CT, CQ, TURBPARAMS, TURBPARAMSI, &
25  USTAR, BSTAR, &
26  AKS, BKS, CKS, AKQ, BKQ, CKQ, AKV, BKV, CKV, EKV, FKV &
27  )
28 
29 IMPLICIT NONE
30 
31 !INPUTS
32 INTEGER, INTENT(IN) :: im, jm, lm
33 REAL(kind_real), INTENT(IN) :: dt
34 
35 REAL(kind_real), INTENT(IN), DIMENSION(:) :: turbparams
36 INTEGER, INTENT(IN), DIMENSION(:) :: turbparamsi
37 
38 REAL(kind_real), INTENT(IN), DIMENSION(IM,JM,LM) :: u, v, th, q, qit, qlt
39 REAL(kind_real), INTENT(IN), DIMENSION(IM,JM,0:LM) :: p
40 REAL(kind_real), INTENT(IN), DIMENSION(IM,JM) :: frland, varflt, frocean
41 
42 REAL(kind_real), INTENT(IN), DIMENSION(IM,JM) :: cm, cq
43 
44 REAL(kind_real), INTENT(IN), DIMENSION(IM,JM) :: ustar, bstar
45 
46 !INOUTS
47 REAL(kind_real), INTENT(INOUT), DIMENSION(IM,JM) :: zpbl, ct
48 
49 !OUTPUTS
50 REAL(kind_real), INTENT(OUT), DIMENSION(IM,JM,LM) :: aks, bks, cks
51 REAL(kind_real), INTENT(OUT), DIMENSION(IM,JM,LM) :: akq, bkq, ckq
52 REAL(kind_real), INTENT(OUT), DIMENSION(IM,JM,LM) :: akv, bkv, ckv, ekv, fkv
53 
54 !LOCALS
55 INTEGER :: i,j
56 REAL(kind_real), DIMENSION(IM,JM,LM) :: pf, pif, qi, ql, tv, thv, zf, dmi
57 REAL(kind_real), DIMENSION(IM,JM,0:LM) :: pi, z
58 REAL(kind_real), DIMENSION(IM,JM,1:LM-1) :: rdz
59 REAL(kind_real), DIMENSION(IM,JM,LM) :: t
60 REAL(kind_real), DIMENSION(IM,JM,0:LM) :: km, kh
61 
62 REAL(kind_real), DIMENSION(IM,JM,0:LM) :: ri, du
63 REAL(kind_real), DIMENSION(IM,JM,0:LM) :: alh_x, kmls_x, khls_x
64 
65 REAL(kind_real), DIMENSION(IM,JM,LM) :: radlw !dh Note that this is really an input but we would rather not put it in the traj
66  !so for now do not use. Later on add approximate numbers.
67 
68 !Turb constants
69 REAL(kind_real) :: louis,lambdam,lambdam2,lambdah,lambdah2,zkmenv,zkhenv,minthick,minshear,c_b,lambda_b,akhmmax
70 REAL(kind_real) :: prandtlsfc,prandtlrad,beta_rad,beta_surf,khradfac,khsfcfac,tpfac_surf,entrate_surf,pceff_surf,louis_memory
71 INTEGER :: kpblmin, lock_on, pblht_option, radlw_dep
72 
73 !QSATVP TABLE
74 integer, parameter :: degsubs = 100
75 real(kind_real), parameter :: tmintbl = 150.0, tmaxtbl = 333.0
76 integer, parameter :: tablesize = nint(tmaxtbl-tmintbl)*degsubs + 1
77 real(kind_real), dimension(TABLESIZE) :: estblx
78 
79  !Compute saturation vapour pressure lookup table
80  call esinit(estblx)
81 
82  !Initialize outputs
83  aks = 0.0
84  bks = 0.0
85  cks = 0.0
86  akq = 0.0
87  bkq = 0.0
88  ckq = 0.0
89  akv = 0.0
90  bkv = 0.0
91  ckv = 0.0
92  ekv = 0.0
93  fkv = 0.0
94 
95  !Caclulate temperature from Exner pressure.
96  pf = 0.5*(p(:,:,0:lm-1) + p(:,:,1:lm))
97  pif = (pf/p00)**(rgas/cp)
98  t = pif*th
99 
100  !TurbParams, this goes at the level above.
101  !TurbParams(1) = 5.0 !LOUIS
102  !TurbParams(2) = 160.0 !LAMBDAM
103  !TurbParams(3) = 1.0 !LAMBDAM2
104  !TurbParams(4) = 160.0 !LAMBDAH
105  !TurbParams(5) = 1.0 !LAMBDAH2
106  !TurbParams(6) = 3000. !ZKMENV
107  !TurbParams(7) = 3000. !ZKHENV
108  !TurbParams(8) = 0.1 !MINTHICK
109  !TurbParams(9) = 0.0030 !MINSHEAR
110  !TurbParams(10) = 2.5101471e-8 !C_B
111  !TurbParams(11) = 1500. !LAMBDA_B
112  !TurbParams(12) = 500. !AKHMMAX
113  !TurbParams(13) = 1.0 !PRANDTLSFC
114  !TurbParams(14) = 0.75 !PRANDTLRAD
115  !TurbParams(15) = 0.50 !BETA_RAD
116  !TurbParams(16) = 0.25 !BETA_SURF
117  !TurbParams(17) = 0.85 !KHRADFAC
118  !TurbParams(18) = 0.45 !KHSFCFAC
119  !TurbParams(19) = 20.0 !TPFAC_SURF
120  !TurbParams(20) = 1.5e-3 !ENTRATE_SURF
121  !TurbParams(21) = 0.5 !PCEFF_SURF
122  !TurbParams(22) = -999. !LOUIS_MEMORY
123 
124  !TurbParamsI(1) = count(PREF < 50000.) !KPBLMIN
125  !TurbParamsI(2) = 1 !LOCK_ON
126  !TurbParamsI(3) = 1 !PBLHT_OPTION
127  !TurbParamsI(4) = 0 !RADLW_DEP
128 
129  !Turbulence constants
130  louis = turbparams(1)
131  lambdam = turbparams(2)
132  lambdam2 = turbparams(3)
133  lambdah = turbparams(4)
134  lambdah2 = turbparams(5)
135  zkmenv = turbparams(6)
136  zkhenv = turbparams(7)
137  minthick = turbparams(8)
138  minshear = turbparams(9)
139  c_b = turbparams(10)
140  lambda_b = turbparams(11)
141  akhmmax = turbparams(12)
142  prandtlsfc = turbparams(13)
143  prandtlrad = turbparams(14)
144  beta_rad = turbparams(15)
145  beta_surf = turbparams(16)
146  khradfac = turbparams(17)
147  khsfcfac = turbparams(18)
148  tpfac_surf = turbparams(19)
149  entrate_surf = turbparams(20)
150  pceff_surf = turbparams(21)
151  louis_memory = turbparams(22)
152 
153  kpblmin = turbparamsi(1)
154  lock_on = turbparamsi(2)
155  pblht_option = turbparamsi(3)
156  radlw_dep = turbparamsi(4)
157 
158  !Initialise arrays
159  kh = 0.0
160  km = 0.0
161  ri = 0.0
162  du = 0.0
163 
164  !If over the ocean then Ts' = 0. That is the perturbation of surface temperature
165  !is negligible. If over land then it is not. But temperature transfer is quick so
166  !T1'-Ts' = 0. So set CT to 0 over land and 1 over ocean.
167  !In between use fraction to take percentage of increment.
168  DO i = 1,im
169  DO j = 1,jm
170  IF (frocean(i,j).eq.1.0) then
171  ct(i,j) = frocean(i,j) * ct(i,j)
172  endif
173  enddo
174  enddo
175 
176  !Call the subroutine to get levels, RDZ and DMI
177  call preliminary( im*jm , & !IN
178  lm , & !IN
179  dt , & !IN
180  t , & !IN
181  q , & !IN
182  p , & !IN
183  th , & !IN
184  qit , & !IN
185  qlt , & !IN
186  zf , & !OUT
187  z , & !OUT
188  tv , & !OUT
189  thv , & !OUT
190  rdz , & !OUT
191  dmi , & !OUT
192  pf & !OUT
193  )
194 
195  !GET LOUIS DIFFUSIVITIES
196  call louis_diff( im*jm , & !IN
197  lm , & !IN
198  kh , & !OUT
199  km , & !OUT
200  ri , & !OUT
201  du , & !OUT
202  zpbl , & !IN
203  zf , & !IN
204  z , & !IN
205  thv , & !IN
206  u , & !IN
207  v , & !IN
208  louis , & !IN
209  minshear , & !IN
210  minthick , & !IN
211  lambdam , & !IN
212  lambdam2 , & !IN
213  lambdah , & !IN
214  lambdah2 , & !IN
215  zkmenv , & !IN
216  zkhenv , & !IN
217  akhmmax , & !IN
218  alh_x , & !OUT
219  kmls_x , & !OUT
220  khls_x & !OUT
221  )
222 
223  !Optional - overwrite diffusivities using the Lock et al scheme.
224  CALL lock_diff( im*jm , & !IN
225  lm , & !IN
226  radlw , & !IN
227  ustar , & !IN
228  bstar , & !IN
229  frland , & !IN
230  t , & !IN
231  q , & !IN
232  qit , & !IN
233  qlt , & !IN
234  u , & !IN
235  v , & !IN
236  zf , & !IN
237  pf , & !IN
238  z , & !IN
239  p , & !IN
240  km , & !INOUT
241  kh , & !INOUT
242  prandtlsfc , & !IN
243  prandtlrad , & !IN
244  beta_surf , & !IN
245  beta_rad , & !IN
246  tpfac_surf , & !IN
247  entrate_surf , & !IN
248  pceff_surf , & !IN
249  khradfac , & !IN
250  khsfcfac , & !IN
251  radlw_dep , & !IN
252  estblx & !IN
253  )
254 
255  call tridiag_setup( im*jm , & !IN
256  lm , & !IN
257  dt , & !IN
258  kpblmin , & !IN
259  zf , & !IN
260  pf , & !IN
261  rdz , & !IN
262  dmi , & !IN
263  p , & !IN
264  tv , & !IN
265  ct , & !IN
266  cq , & !IN
267  cm , & !IN
268  t , & !IN
269  q , & !IN
270  th , & !IN
271  u , & !IN
272  v , & !IN
273  kh , & !INOUT
274  km , & !INOUT
275  akq, aks, akv , & !OUT
276  bkq, bks, bkv , & !OUT
277  ckq, cks, ckv , & !OUT
278  ekv , & !OUT
279  zpbl & !OUT
280  )
281 
282  call orodrag( im*jm , & !IN
283  lm , & !IN
284  dt , & !IN
285  lambda_b , & !IN
286  c_b , & !IN
287  fkv , & !OUT
288  bkv , & !INOUT
289  u , & !IN
290  v , & !IN
291  zf , & !IN
292  varflt , & !IN
293  p & !IN
294  )
295 
296 
297 end subroutine bl_driver
298 
299 
300 subroutine preliminary( IRUN, LM, DT, T, QV, PHALF, TH, QIT, QLT, &
301  ZFULL, ZHALF, TV, PV, RDZ, DMI, PFULL &
302  )
304  !Subroutine to set up priliminary
305 
306  IMPLICIT NONE
307 
308  !INTPUTS
309  integer, intent(IN) :: IRUN, LM
310  real(kind_real), intent(IN) :: DT
311  real(kind_real), intent(IN), dimension(IRUN,LM) :: T, QV, TH, QIT, QLT
312  real(kind_real), intent(IN), dimension(IRUN,LM+1) :: PHALF
313 
314  !OUTPUTS
315  real(kind_real), intent(OUT), dimension(IRUN, LM ) :: ZFULL, TV, PV, DMI, PFULL
316  real(kind_real), intent(OUT), dimension(IRUN, LM+1) :: ZHALF
317  real(kind_real), intent(OUT), dimension(IRUN,1:LM-1) :: RDZ
318 
319  !LOCALS
320  integer :: I,L
321  real(kind_real) :: PKE_atL, PKE_atLp1, TVE
322  real(kind_real) :: QL_tot, QI_tot
323 
324  do i = 1, irun
325 
326  !Compute the edge heights using Arakawa-Suarez hydrostatic equation
327  zhalf(i,lm+1) = 0.0
328  do l = lm, 1, -1
329  pke_atlp1 = (phalf(i,l+1)/p00)**kappa
330  pke_atl = (phalf(i,l )/p00)**kappa
331 
332  zhalf(i,l) = zhalf(i,l+1) + (cp/grav)*th(i,l)*(pke_atlp1-pke_atl)
333  end do
334 
335  !Layer height, pressure, and virtual temperatures
336  do l = 1, lm
337  ql_tot = qit(i,l)
338  qi_tot = qlt(i,l)
339 
340  zfull(i,l) = 0.5*(zhalf(i,l)+zhalf(i,l+1))
341  pfull(i,l) = 0.5*(phalf(i,l)+phalf(i,l+1))
342 
343  tv(i,l) = t(i,l) *( 1.0 + vireps *qv(i,l) - ql_tot - qi_tot )
344  pv(i,l) = tv(i,l)*(th(i,l)/t(i,l))
345  end do
346 
347  do l = 1, lm-1
348  tve = (tv(i,l) + tv(i,l+1))*0.5
349 
350  ! Miscellaneous factors
351  rdz(i,l) = phalf(i,l+1) / ( rgas * tve )
352  rdz(i,l) = rdz(i,l) / (zfull(i,l)-zfull(i,l+1))
353  end do
354 
355  do l = 1, lm
356  dmi(i,l) = (grav*dt)/(phalf(i,l+1)-phalf(i,l))
357  end do
358 
359  !Running 1-2-1 smooth of bottom 5 levels of Virtual Pot. Temp.
360  pv(i,lm ) = pv(i,lm-1)*0.25 + pv(i,lm )*0.75
361  pv(i,lm-1) = pv(i,lm-2)*0.25 + pv(i,lm-1)*0.50 + pv(i,lm )*0.25
362  pv(i,lm-2) = pv(i,lm-3)*0.25 + pv(i,lm-2)*0.50 + pv(i,lm-1)*0.25
363  pv(i,lm-3) = pv(i,lm-4)*0.25 + pv(i,lm-3)*0.50 + pv(i,lm-2)*0.25
364  pv(i,lm-4) = pv(i,lm-5)*0.25 + pv(i,lm-4)*0.50 + pv(i,lm-3)*0.25
365  pv(i,lm-5) = pv(i,lm-6)*0.25 + pv(i,lm-5)*0.50 + pv(i,lm-4)*0.25
366 
367  end do
368 
369 end subroutine preliminary
370 
371 
372 
373 subroutine louis_diff( IRUN,LM,KH,KM,RI,DU,ZPBL,ZZ,ZE,PV,UU,VV,LOUIS,MINSHEAR,MINTHICK,&
374  LAMBDAM,LAMBDAM2,LAMBDAH,LAMBDAH2,ZKMENV,ZKHENV,AKHMMAX,ALH_DIAG,KMLS_DIAG,KHLS_DIAG)
376  !Subroutine to compute eddy diffussivity using the Louis (1979) method.
377  !Simplifications are made compared with the NL stability functions f(Ri).
378  !Gradient is very steep for near neutral boundary layer conditions.
379 
380  IMPLICIT NONE
381 
382  !INPUTS
383  integer, intent(IN ) :: IRUN,LM
384  real(kind_real), intent(IN ) :: LOUIS ! Louis scheme parameters (usually 5).
385  real(kind_real), intent(IN ) :: MINSHEAR ! Min shear allowed in Ri calculation (s-1).
386  real(kind_real), intent(IN ) :: MINTHICK ! Min layer thickness (m).
387  real(kind_real), intent(IN ) :: AKHMMAX ! Maximum allowe diffusivity (m+2 s-1).
388  real(kind_real), intent(IN ) :: LAMBDAM ! Blackadar(1962) length scale parameter for momentum (m).
389  real(kind_real), intent(IN ) :: LAMBDAM2 ! Second Blackadar parameter for momentum (m).
390  real(kind_real), intent(IN ) :: LAMBDAH ! Blackadar(1962) length scale parameter for heat (m).
391  real(kind_real), intent(IN ) :: LAMBDAH2 ! Second Blackadar parameter for heat (m).
392  real(kind_real), intent(IN ) :: ZKMENV ! Transition height for Blackadar param for momentum (m)
393  real(kind_real), intent(IN ) :: ZKHENV ! Transition height for Blackadar param for heat (m)
394  real(kind_real), intent(IN ) :: ZZ(IRUN,LM) ! Height of layer center above the surface (m).
395  real(kind_real), intent(IN ) :: PV(IRUN,LM) ! Virtual potential temperature at layer center (K).
396  real(kind_real), intent(IN ) :: UU(IRUN,LM) ! Eastward velocity at layer center (m s-1).
397  real(kind_real), intent(IN ) :: VV(IRUN,LM) ! Northward velocity at layer center (m s-1).
398  real(kind_real), intent(IN ) :: ZE(IRUN,LM+1) ! Height of layer base above the surface (m).
399  real(kind_real), intent(IN ) :: ZPBL(IRUN) ! PBL Depth (m)
400 
401  !OUTPUTS
402  !These are 1:LM+1 here but 0:LM in the GC - MAYBE JUST SORT THIS OUT?
403  !Old code only passed in 1:LM-1 from GC which is 2:LM here.
404  real(kind_real), intent( OUT) :: KM(IRUN,LM+1) ! Momentum diffusivity at base of each layer (m+2 s-1).
405  real(kind_real), intent( OUT) :: KH(IRUN,LM+1) ! Heat diffusivity at base of each layer (m+2 s-1).
406  real(kind_real), intent( OUT) :: RI(IRUN,LM+1) ! Richardson number
407  real(kind_real), intent( OUT) :: DU(IRUN,LM+1) ! Magnitude of wind shear (s-1).
408  real(kind_real), intent( OUT) :: ALH_DIAG(IRUN,LM+1) ! Blackadar Length Scale diagnostic (m) [Optional]
409  real(kind_real), intent( OUT) :: KMLS_DIAG(IRUN,LM+1) ! Momentum diffusivity at base of each layer (m+2 s-1).
410  real(kind_real), intent( OUT) :: KHLS_DIAG(IRUN,LM+1) ! Heat diffusivity at base of each layer (m+2 s-1).
411 
412  !LOCALS
413  integer :: L,Levs,i,j,k
414  real(kind_real) :: ALH, ALM, DZ, DT, TM, PS, LAMBDAM_X, LAMBDAH_X
415  real(kind_real) :: pbllocal, alhfac,almfac
416 
417  almfac = 1.2
418  alhfac = 1.2
419 
420  do i = 1, irun !Loop of columns
421 
422  alh_diag(i, 1) = 0.0
423  alh_diag(i,lm+1) = 0.0
424 
425  kh(i, 1) = 0.0
426  kh(i,lm+1) = 0.0
427  km(i, 1) = 0.0
428  km(i,lm+1) = 0.0
429  du(i, 1) = 0.0
430  du(i,lm+1) = 0.0
431  ri(i, 1) = 0.0
432  ri(i,lm+1) = 0.0
433  kmls_diag(i, 1) = 0.0
434  kmls_diag(i,lm+1) = 0.0
435  khls_diag(i, 1) = 0.0
436  khls_diag(i,lm+1) = 0.0
437 
438  pbllocal = zpbl(i)
439 
440  if ( pbllocal .LE. zz(i,lm) ) then
441  pbllocal = zz(i,lm)
442  endif
443 
444  do k = 2, lm !This is equivalent to 1->LM-1 but we move all 0:72 elements
445  kh(i,k) = 0.0
446  km(i,k) = 0.0
447  du(i,k) = 0.0
448  ri(i,k) = 0.0
449 
450  dz = (zz(i,k-1) - zz(i,k))
451  tm = (pv(i,k-1) + pv(i,k))*0.5
452  dt = (pv(i,k-1) - pv(i,k))
453  du(i,k) = (uu(i,k-1) - uu(i,k))**2 + (vv(i,k-1) - vv(i,k))**2
454 
455  !Limits distance between layer centers and vertical shear at edges.
456  dz = max(dz, minthick)
457  du(i,k) = sqrt(du(i,k))/dz
458 
459  !Calc Richardson
460  ri(i,k) = grav*(dt/dz)/(tm*( max(du(i,k), minshear)**2))
461 
462  !Blackadar (1962) length scale
463  lambdam_x = max( 0.1 * pbllocal * exp( -(ze(i,k) / zkmenv )**2 ) , lambdam2 )
464  lambdah_x = max( 0.1 * pbllocal * exp( -(ze(i,k) / zkhenv )**2 ) , lambdah2 )
465 
466  alm = almfac * ( karman*ze(i,k)/( 1.0 + karman*(ze(i,k)/lambdam_x) ) )**2
467  alh = alhfac * ( karman*ze(i,k)/( 1.0 + karman*(ze(i,k)/lambdah_x) ) )**2
468 
469  alh_diag(i,k) = sqrt( alh )
470 
471  !Unstable convectve boundary layer
472  if ( ri(i,k) < 0.0 ) then
473  ps = ( (zz(i,k-1)/zz(i,k))**(1./3.) - 1.0 ) ** 3
474  ps = alh*sqrt( ps/(ze(i,k)*(dz**3)) )
475  ps = ri(i,k)/(1.0 + (3.0*louis*louis)*ps*sqrt(-ri(i,k)))
476 
477  kh(i,k) = 1.0 - (louis*3.0)*ps
478  km(i,k) = 1.0 - (louis*2.0)*ps
479  end if
480 
481  !Stable boundary layer
482  if ( ri(i,k) >= 0.0 ) then
483  ps = sqrt(1.0 + louis *ri(i,k) )
484 
485  kh(i,k) = 1.0 / (1.0 + (louis*3.0)*ri(i,k)*ps)
486  km(i,k) = ps / (ps + (louis*2.0)*ri(i,k) )
487  end if
488 
489  !Dimensionalize Kz and limit diffusvity
490  alm = du(i,k)*alm
491  alh = du(i,k)*alh
492 
493  km(i,k) = min(km(i,k)*alm, akhmmax)
494  kh(i,k) = min(kh(i,k)*alh, akhmmax)
495  kmls_diag(i,k) = km(i,k)
496  khls_diag(i,k) = kh(i,k)
497 
498  end do !Loop over levels
499 
500  end do !Loop over columns.
501 
502 end subroutine louis_diff
503 
504 subroutine tridiag_setup(IRUN,LM,DT,KPBLMIN,ZFULL,PFULL,RDZ,DMI,PHALF,&
505  TV,CT,CQ,CU,T,Q,TH,U,V,DIFF_T,DIFF_M,&
506  AKQ,AKS,AKV,BKQ,BKS,BKV,CKQ,CKS,CKV,EKV,ZPBL)
508  IMPLICIT NONE
509 
510  !INPUTS
511  integer, intent(IN) :: IRUN,LM,KPBLMIN
512  real(kind_real), intent(IN) :: DT
513  real(kind_real), intent(IN), dimension(IRUN,LM) :: T,Q,TH,U,V,ZFULL,PFULL,DMI,TV
514  real(kind_real), intent(IN), dimension(IRUN,LM-1) :: RDZ
515  real(kind_real), intent(IN), dimension(IRUN,LM+1) :: PHALF
516  real(kind_real), intent(IN), dimension(IRUN ) :: CT, CQ, CU
517 
518  !INOUTS
519  real(kind_real), intent(INOUT), dimension(IRUN,LM+1) :: DIFF_T, DIFF_M
520 
521  !OUTPUTS
522  real(kind_real), intent(OUT), dimension(IRUN,LM) :: AKQ, AKS, AKV
523  real(kind_real), intent(OUT), dimension(IRUN,LM) :: BKQ, BKS, BKV
524  real(kind_real), intent(OUT), dimension(IRUN,LM) :: CKQ, CKS, CKV
525  real(kind_real), intent(OUT), dimension(IRUN,LM) :: EKV
526  real(kind_real), intent(OUT), dimension(IRUN) :: ZPBL
527 
528  !LOCALS
529  real(kind_real), dimension(LM+1) :: temparray
530  integer :: I,L,locmax
531  real(kind_real) :: maxkh,minlval,thetavs,thetavh,uv2h
532  real(kind_real), parameter :: tcri_crit = 0.25 !PBL-top diagnostic
533 
534  real(kind_real), dimension(LM ) :: tcrib
535 
536  do i = 1, irun
537 
538  !Update zpbl
539  zpbl(i) = 10.e15
540  do l=lm,2,-1
541  if ( (diff_t(i,l) < 2.) .and. (diff_t(i,l+1) >= 2.) .and. (zpbl(i) == 10.e15 ) ) then
542  zpbl(i) = zfull(i,l)
543  end if
544  end do
545  if ( zpbl(i) .eq. 10.e15 ) then
546  zpbl(i) = zfull(i,lm)
547  endif
548  zpbl(i) = min(zpbl(i),zfull(i,kpblmin))
549 
550  !Second difference coefficients for scalars; RDZ is RHO/DZ, DMI is (G DT)/DP
551  do l = 1, lm
552  if (l <= lm-1) then
553  cks(i,l) = -diff_t(i,l+1) * rdz(i,l)
554  if (l == 1) then
555  aks(i,l) = 0.0
556  endif
557  aks(i,l+1) = cks(i,l) * dmi(i,l+1)
558  cks(i,l) = cks(i,l) * dmi(i,l)
559  end if
560 
561  if (l == lm) then
562  cks(i,l) = -ct(i) * dmi(i,l)
563  endif
564 
565  !Fill DIFF_T at level LM+1 with CT * RDZ for diagnostic output
566  if (l == lm) then
567  diff_t(i,l+1) = ct(i) * (phalf(i,l+1)/(rgas * tv(i,l))) / zfull(i,l)
568  endif
569 
570  !Water vapor can differ at the surface
571  ckq(i,l) = cks(i,l)
572  akq(i,l) = aks(i,l)
573  if (l == lm) then
574  ckq(i,l) = -cq(i) * dmi(i,l)
575  endif
576 
577  !Second difference coefficients for winds
578  !EKV is saved to use in the frictional heating calc.
579  if (l <= lm-1) then
580  ekv(i,l) = -diff_m(i,l+1) * rdz(i,l)
581  if (l == 1) then
582  akv(i,l) = 0.0
583  endif
584  akv(i,l+1) = ekv(i,l) * dmi(i,l+1)
585  ckv(i,l) = ekv(i,l) * dmi(i,l)
586  ekv(i,l) = -grav * ekv(i,l)
587  end if
588 
589  if (l == lm) then
590  ckv(i,l) = - cu(i) * dmi(i,l)
591  ekv(i,l) = grav * cu(i)
592  end if
593 
594  !Fill DIFF_M at level LM+1 with CU * RDZ for diagnostic output
595  if (l == lm) then
596  diff_m(i,l+1) = cu(i) * (phalf(i,l+1)/(rgas * tv(i,l))) / zfull(i,l)
597  endif
598 
599  !Setup the tridiagonal matrix
600  bks(i,l) = 1.00 - (aks(i,l)+cks(i,l))
601  bkq(i,l) = 1.00 - (akq(i,l)+ckq(i,l))
602  bkv(i,l) = 1.00 - (akv(i,l)+ckv(i,l))
603 
604  end do
605 
606  end do
607 
608 
609 end subroutine tridiag_setup
610 
611 
612 subroutine orodrag(IRUN,LM,DT,LAMBDA_B,C_B,FKV,BKV,U,V,ZFULL,VARFLT,PHALF)
614  !Subroutine to compute orograpic drag, Beljaars (2003).
615 
616  IMPLICIT NONE
617 
618  !INPUTS
619  integer, intent(IN) :: IRUN, LM
620  real(kind_real), intent(IN) :: DT, LAMBDA_B, C_B
621  real(kind_real), intent(IN), dimension(IRUN) :: VARFLT
622  real(kind_real), intent(IN), dimension(IRUN,LM) :: U, V, ZFULL
623  real(kind_real), intent(IN), dimension(IRUN,LM+1) :: PHALF
624 
625  !INOUTS
626  real(kind_real), intent(INOUT), dimension(IRUN,LM) :: BKV
627 
628  !OUTPUTS
629  real(kind_real), intent(OUT), dimension(IRUN,LM) :: FKV
630 
631  !LOCALS
632  integer :: I, L
633  real(kind_real) :: FKV_temp
634 
635  do i = 1, irun
636  do l=lm,1,-1
637 
638  fkv(i,l) = 0.0
639 
640  if (zfull(i,l) < 4.0*lambda_b) then
641  fkv_temp = zfull(i,l)*(1.0/lambda_b)
642  fkv_temp = varflt(i) * exp(-fkv_temp*sqrt(fkv_temp))*(fkv_temp**(-1.2))
643  fkv_temp = (c_b/lambda_b)*min( sqrt(u(i,l)**2+v(i,l)**2),5.0 )*fkv_temp
644 
645  bkv(i,l) = bkv(i,l) + dt*fkv_temp
646  fkv(i,l) = fkv_temp * (phalf(i,l+1)-phalf(i,l))
647  end if
648  end do
649 
650  end do
651 
652 end subroutine orodrag
653 
654 
655 subroutine lock_diff( ncol,nlev,tdtlw_in_dev,u_star_dev,b_star_dev,frland_dev,t_dev,qv_dev, &
656  qit_dev,qlt_dev,u_dev,v_dev,zfull_dev,pfull_dev,zhalf_dev,phalf_dev, &
657  !INOUTS
658  diff_m_dev,diff_t_dev, &
659  !Constants
660  prandtlsfc_const,prandtlrad_const,beta_surf_const,beta_rad_const, &
661  tpfac_sfc_const,entrate_sfc_const,pceff_sfc_const,khradfac_const,khsfcfac_const,radlw_dep,&
662  ESTBLX )
664  IMPLICIT NONE
665 
666  !INPUTS
667  integer, intent(in) :: ncol,nlev
668  real(kind_real), intent(in) :: ESTBLX(:)
669  real(kind_real), intent(in), dimension(ncol) :: u_star_dev,b_star_dev,frland_dev
670  real(kind_real), intent(in), dimension(ncol,nlev) :: tdtlw_in_dev,t_dev,qv_dev,qit_dev,qlt_dev
671  real(kind_real), intent(in), dimension(ncol,nlev) :: u_dev,v_dev,zfull_dev,pfull_dev
672  real(kind_real), intent(in), dimension(ncol,1:nlev+1) :: zhalf_dev, phalf_dev ! 0:72 in GC, 1:73 here.
673  real(kind_real), intent(in) :: prandtlsfc_const,prandtlrad_const,beta_surf_const,beta_rad_const
674  real(kind_real), intent(in) :: khradfac_const,tpfac_sfc_const,entrate_sfc_const
675  real(kind_real), intent(in) :: pceff_sfc_const,khsfcfac_const
676 
677  !INOUTS
678  real(kind_real), intent(inout), dimension(ncol,1:nlev+1) :: diff_m_dev,diff_t_dev
679 
680  !LOCALS
681  real(kind_real), parameter :: akmax = 1.e4, zcldtopmax = 3.e3, ramp = 20.
682  integer :: i,j,k,ibot,itmp,ipbl,kmax,kcldtop,kcldbot,kcldtop2,radlw_dep
683  logical :: used,keeplook,do_jump_exit
684  real(kind_real) :: maxradf, tmpradf,stab
685  real(kind_real) :: maxqdot, tmpqdot,wentrmax
686  real(kind_real) :: maxinv, qlcrit,ql00,qlm1,Abuoy,Ashear
687  real(kind_real) :: wentr_tmp,hlf,vbulkshr,vbulk_scale
688  real(kind_real) :: k_entr_tmp,tmpjump,critjump,radperturb,buoypert
689  real(kind_real) :: tmp1, tmp2, slmixture
690  real(kind_real) :: vsurf3, vshear3,vrad3, vbr3,dsiems
691  real(kind_real) :: dslvcptmp,ztmp
692  real(kind_real) :: zradtop
693  real(kind_real) :: vrad,svpcp,chis,vbrv
694  real(kind_real) :: vsurf, qs_dummy, ptmp
695  real(kind_real) :: wentr_rad,wentr_pbl,wentr_brv
696  real(kind_real) :: convpbl, radpbl
697  real(kind_real), dimension(nlev) :: slv,density,qc,slvcp,hleff,radfq,pblfq,k_m_troen,k_t_troen,k_rad,dqs
698 
699  !Moved to local as not needed in outputs, but still used in calculations
700  real(kind_real), dimension(ncol,1:nlev+1) :: k_m_entr_dev,k_t_entr_dev
701  real(kind_real), dimension(ncol) :: zsml_dev,zradml_dev,zcloud_dev,zradbase_dev
702 
703  qlcrit = 1.0e-6
704  abuoy = 0.23
705  ashear = 25.0
706  wentrmax = 0.05
707 
708  ibot = nlev
709 
710  do i = 1, ncol
711 
712  zradml_dev(i) = 0.0
713  zcloud_dev(i) = 0.0
714  zradbase_dev(i) = 0.0
715  zsml_dev(i) = 0.0 ! note that this must be zero, indicates stable surface layer is used in gravity wave drag scheme
716 
717  zradtop = 0.0
718  convpbl = 0.0
719  wentr_pbl = 0.0
720  vsurf = 0.0
721  radpbl = 0.0
722  svpcp = 0.0
723  vrad = 0.0
724  wentr_rad = 0.0
725 
726  do k = 1, nlev
727  pblfq(k) = 0.0
728  k_t_troen(k) = 0.0
729  k_m_troen(k) = 0.0
730  radfq(k) = 0.0
731  k_rad(k) = 0.0
732  k_t_entr_dev(i,k) = 0.0
733  k_m_entr_dev(i,k) = 0.0
734 
735  end do
736 
737  !For GPU we must zero out even the LM+1'th position
738 
739  k_t_entr_dev(i,nlev+1) = 0.0
740  k_m_entr_dev(i,nlev+1) = 0.0
741 
742  !set up specific humidities and static energies and compute airdensity
743  do k = 1, nlev
744  if ( t_dev(i,k) <= tice-ramp ) then
745  hleff(k) = alhs
746  else if ( (t_dev(i,k) > tice-ramp) .and. (t_dev(i,k) < tice) ) then
747  hleff(k) = ( (t_dev(i,k)-tice+ramp)*alhl + (tice -t_dev(i,k) )*alhs ) / ramp
748  else
749  hleff(k) = alhl
750  end if
751 
752  !Compute sat specific humidity and deriv, Qs not actually needed
753  !dqs(k) = dqsat(t_dev(i,k), pfull_dev(i,k), qsat=qs(k), pascals=.true. )
754  !dqs(k) = dqsat(t_dev(i,k), pfull_dev(i,k), qsat=qs_dummy, pascals=.true. )
755 
756  ptmp = pfull_dev(i,k)*0.01
757  call dqsat_sub_sca(dqs(k),qs_dummy,t_dev(i,k),ptmp,estblx)
758 
759  !Compute total cloud condensate - qc. These are grid box mean values.
760  !qc(k) = 0.0 !(qlls_dev(i,k) + qils_dev(i,k))
761  qc(k) = (qit_dev(i,k) + qlt_dev(i,k))
762 
763  !Compute liquid static energy.
764  slv(k) = cp*t_dev(i,k)*(1+vireps*qv_dev(i,k)-qc(k)) + grav*zfull_dev(i,k) - hleff(k)*qc(k)
765 
766  density(k) = pfull_dev(i,k)/(rgas*(t_dev(i,k) *(1.+vireps*qv_dev(i,k)-qc(k))))
767 
768  end do
769 
770  !Reset indices
771  ipbl = -1
772  kcldtop = -1
773 
774  !Surface driven convective layers (if b_star_dev > 0., that is,upward surface buoyancy flux)
775  if (b_star_dev(i) .gt. 0.) then
776 
777  !Find depth of surface driven mixing by raising a parcel from the surface with some excess buoyancy to its level
778  !of neutral buoyancy. Note the use slv as the density variable permits one to goes through phase changes to find parcel top
779  call mpbl_depth(i,ncol,nlev,tpfac_sfc_const,entrate_sfc_const,pceff_sfc_const, &
780  t_dev,qv_dev,u_dev,v_dev,zfull_dev,pfull_dev,b_star_dev,u_star_dev,ipbl,zsml_dev,&
781  estblx)
782 
783  !Define velocity scales vsurf and vshear
784  vsurf3 = u_star_dev(i)*b_star_dev(i)*zsml_dev(i) !cubed
785  vshear3 = ashear*u_star_dev(i)*u_star_dev(i)*u_star_dev(i)
786 
787  vsurf = vsurf3**(1./3.)
788 
789  !Define velocity scale vbulkshr
790  vbulkshr = sqrt( ( u_dev(i,ipbl)-u_dev(i,ibot) )**2 + ( v_dev(i,ipbl)-v_dev(i,ibot) )**2 ) / zsml_dev(i)
791  vbulk_scale = 3.0 / 1000. ! Non-local (PBL-deep) shear scale
792 
793  !Following Lock et al. 2000, limit height of surface well mixed layer if interior stable interface is
794  !found. An interior stable interface is diagnosed if the slope between 2 full levels is greater than critjump
795  critjump = 2.0
796  if (ipbl .lt. ibot) then
797  do k = ibot, ipbl+1, -1
798  tmpjump =(slv(k-1)-slv(k))/cp
799  if (tmpjump .gt. critjump) then
800  ipbl = k
801  zsml_dev(i) = zhalf_dev(i,ipbl)
802  exit
803  end if
804  enddo
805  end if
806 
807  !Compute entrainment rate
808  tmp1 = grav*max(0.1,(slv(ipbl-1)-slv(ipbl))/ cp)/(slv(ipbl)/cp)
809  tmp2 = ((vsurf3+vshear3)**(2./3.)) / zsml_dev(i)
810 
811  wentr_tmp = min( wentrmax, max(0., (beta_surf_const * (vsurf3 + vshear3)/zsml_dev(i))/(tmp1+tmp2) ) )
812 
813  !Fudgey adjustment of entrainment to reduce it for shallow boundary layers, increase for deep ones
814  if ( zsml_dev(i) .lt. 1600. ) then
815  wentr_tmp = wentr_tmp * ( zsml_dev(i) / 800. )
816  else
817  wentr_tmp = 2.*wentr_tmp
818  endif
819 
820  !More fudgey adjustment of entrainment.
821  k_entr_tmp = wentr_tmp*(zfull_dev(i,ipbl-1)-zfull_dev(i,ipbl))
822  k_entr_tmp = min( k_entr_tmp, akmax )
823 
824  do k = ipbl, ibot
825  pblfq(k) = 1.
826  end do
827  convpbl = 1.
828  wentr_pbl = wentr_tmp
829  k_t_troen(ipbl) = k_entr_tmp
830  k_m_troen(ipbl) = k_entr_tmp
831  k_t_entr_dev(i,ipbl) = k_t_entr_dev(i,ipbl) + k_entr_tmp
832  k_m_entr_dev(i,ipbl) = k_m_entr_dev(i,ipbl) + k_entr_tmp
833 
834  !Compute diffusion coefficients in the interior of the PBL
835 
836  if (ipbl .lt. ibot) then
837 
838  call diffusivity_pbl2(i, ncol, nlev,zsml_dev,khsfcfac_const, k_entr_tmp,vsurf,&
839  frland_dev,zhalf_dev,k_m_troen,k_t_troen)
840 
841  do k = ipbl+1, ibot
842  k_t_entr_dev(i,k) = k_t_entr_dev(i,k) + k_t_troen(k)
843  k_m_entr_dev(i,k) = k_m_entr_dev(i,k) + k_m_troen(k)*prandtlsfc_const
844  end do
845 
846  end if
847 
848  end if
849 
850 
851  !NEGATIVELY BUOYANT PLUMES DRIVEN BY LW RADIATIVE COOLING AND/OR BUOYANCY REVERSAL
852  !This part is done only if a level kcldtop can be found below zcldtopmax
853 
854  kmax = ibot+1
855  do k = 1, ibot
856  if ( zhalf_dev(i,k) < zcldtopmax) then
857  kmax = k
858  exit
859  end if
860  end do
861 
862  !Find cloud top and bottom using GRID BOX MEAN or IN-CLOUD value of qc. Decision occurs where qc is calculated
863  kcldtop = ibot+1
864  do k = ibot,kmax,-1
865  qlm1 = qc(k-1) ! qc one level UP
866  ql00 = qc(k)
867  stab = slv(k-1) - slv(k)
868  if ( ( ql00 .ge. qlcrit ) .and. ( qlm1 .lt. qlcrit) .and. (stab .gt. 0.) ) then
869  kcldtop = k
870  exit
871  end if
872  end do
873 
874  !if (kcldtop .ge. ibot+1) then
875  if (kcldtop .lt. ibot+1) then
876  !Only do this is above is true, else skip to the end
877 
878  kcldtop2=min( kcldtop+1,nlev)
879  ! Look one level further down in case first guess is a thin diffusive veil
880  if ( (qc(kcldtop) .lt. 10*qlcrit ) .and. (qc(kcldtop2) .ge. 10*qc(kcldtop) ) ) then
881  kcldtop=kcldtop2
882  endif
883 
884  kcldbot = ibot+1
885  do k = ibot,kcldtop,-1
886  qlm1 = qc(k-1) ! qc one level UP
887  ql00 = qc(k)
888  if ( ( ql00 .lt. qlcrit ) .and. ( qlm1 .ge. qlcrit) ) then
889  kcldbot = k
890  exit
891  end if
892  end do
893 
894  if (radlw_dep .eq. 1) then
895 
896  !if (kcldtop .eq. kcldbot) then
897  if (kcldtop .ne. kcldbot) then
898  !Only do this is above is true, else skip to the end
899 
900  !With diffusion of ql, qi "cloud top" found via these quantities may be above radiation max
901  kcldtop2=min( kcldtop+2,nlev)
902  maxradf = maxval( -1.*tdtlw_in_dev(i,kcldtop:kcldtop2) )
903  maxradf = maxradf*cp*( (phalf_dev(i,kcldtop+1)-phalf_dev(i,kcldtop)) / grav )
904  maxradf = max( maxradf , 0. ) ! do not consider cloud tops that are heating
905 
906  !Calculate optimal mixing fraction (chis) for buoyancy reversal. Use effective heat of evap/subl. Ignore diffs across cldtop
907  hlf = hleff(kcldtop)
908 
909  tmp1 = ( slv(kcldtop-1) - hlf*qc(kcldtop-1) ) - (slv(kcldtop) - hlf*qc(kcldtop) )
910  tmp1 = dqs(kcldtop)*tmp1/cp
911 
912  tmp2 = ( qv_dev(i,kcldtop-1) + qc(kcldtop-1) ) - ( qv_dev(i,kcldtop) + qc(kcldtop) )
913 
914  chis = -qc(kcldtop)*( 1 + hlf * dqs(kcldtop) / cp )
915 
916  if ( ( tmp2 - tmp1 ) >= 0.0 ) then
917  chis = 0.
918  else
919  chis = chis / ( tmp2 - tmp1 )
920  endif
921 
922  if ( chis .gt. 1.0 ) then
923  chis=1.0
924  endif
925 
926  slmixture = ( 1.0-chis ) * ( slv(kcldtop) - hlf*qc(kcldtop) ) + chis * ( slv(kcldtop-1) - hlf*qc(kcldtop-1) )
927 
928  !Compute temperature of parcel at cloud top, svpcp.
929  svpcp = slmixture /cp
930 
931  buoypert = ( slmixture - slv(kcldtop) )/cp
932 
933  !Calculate my best guess at the LCs' D parameter attributed to Siems et al.
934  stab = slv(kcldtop-1) - slv(kcldtop)
935  if (stab .eq. 0.) then
936  dsiems = ( slv(kcldtop) - slmixture ) ! / 1.0 ! arbitrary, needs to be re-thought
937  else
938  dsiems = ( slv(kcldtop) - slmixture ) / stab
939  endif
940  dsiems = min( dsiems, 10. )
941  dsiems = max( dsiems, 0. )
942  zradtop = zhalf_dev(i,kcldtop)
943 
944  !Find depth of radiatively driven convection
945  !Expose radperturb and other funny business outside of radml_depth
946  radperturb = min( maxradf/100. , 0.3 ) ! dim. argument based on 100m deep cloud over 1000s
947  do_jump_exit = .true.
948  critjump = 0.3
949  svpcp = svpcp - radperturb
950 
951  slvcp = slv/cp
952 
953  if (kcldtop .lt. ibot) then
954  call radml_depth(i,ncol,nlev,kcldtop,ibot,svpcp,zradtop,critjump,do_jump_exit,&
955  slvcp,zfull_dev,zhalf_dev,zradbase_dev,zradml_dev )
956  else
957  zradbase_dev(i) = 0.0
958  zradml_dev(i) = zradtop
959  end if
960 
961  zcloud_dev(i) = zhalf_dev(i,kcldtop) - zhalf_dev(i,kcldbot)
962 
963  !if (zradml_dev(i) .le. 0.0 ) then
964  if (zradml_dev(i) .gt. 0.0 ) then
965  !Only do this is above is true, else skip to the end
966 
967  !Compute radiation driven scale
968  vrad3 = grav*zradml_dev(i)*maxradf/density(kcldtop)/slv(kcldtop)
969 
970  !tmp1 here should be the buoyancy jump at cloud top SAK has it w/ resp to parcel property - svpcp. Im not sure about that.
971  tmp1 = grav*max(0.1,((slv(kcldtop-1)/cp)-svpcp))/(slv(kcldtop)/cp)
972 
973  !Straightforward buoyancy jump across cloud top
974  tmp1 = grav*max( 0.1, ( slv(kcldtop-1)-slv(kcldtop) )/cp ) / ( slv(kcldtop) /cp )
975 
976  !Compute buoy rev driven scale
977  vbr3 = ( max( tmp1*zcloud_dev(i), 0.)**3 )
978  vbr3 = abuoy*(chis**2)*max(dsiems,0.)*sqrt( vbr3 )
979 
980  !Adjust velocity scales to prevent jumps near zradtop=zcldtopmax
981  if ( zradtop .gt. zcldtopmax-500. ) then
982  vrad3 = vrad3*(zcldtopmax - zradtop)/500.
983  vbr3 = vbr3 *(zcldtopmax - zradtop)/500.
984  endif
985  vrad3=max( vrad3, 0. ) ! these really should not be needed
986  vbr3 =max( vbr3, 0. )
987 
988  vrad = vrad3 ** (1./3.)
989  vbrv = vbr3**(1./3.)
990 
991  tmp2 = ( vrad**2 + vbrv**2 ) / zradml_dev(i)
992  wentr_rad = min(wentrmax,beta_rad_const*(vrad3+vbr3)/zradml_dev(i)/(tmp1+tmp2))
993 
994  wentr_brv = beta_rad_const*vbr3/zradml_dev(i)/(tmp1+tmp2)
995 
996  !Fudgey adjustment of entrainment to reduce it for shallow boundary layers, increase for deep ones
997  if ( zradtop .lt. 500. ) then
998  wentr_rad = 0.00
999  endif
1000  if (( zradtop .gt. 500.) .and. (zradtop .le. 800. )) then
1001  wentr_rad = wentr_rad * ( zradtop-500.) / 300.
1002  endif
1003 
1004  if ( zradtop .lt. 2400. ) then
1005  wentr_rad = wentr_rad * ( zradtop / 800. )
1006  else
1007  wentr_rad = 3.*wentr_rad
1008  endif
1009 
1010  k_entr_tmp = min( akmax, wentr_rad*(zfull_dev(i,kcldtop-1)-zfull_dev(i,kcldtop)) )
1011 
1012  radfq(kcldtop) = 1.
1013  radpbl = 1.
1014  k_rad(kcldtop) = k_entr_tmp
1015  k_t_entr_dev(i,kcldtop) = k_t_entr_dev(i,kcldtop) + k_entr_tmp
1016  k_m_entr_dev(i,kcldtop) = k_m_entr_dev(i,kcldtop) + k_entr_tmp
1017 
1018  !Handle case of radiatively driven top being the same top as surface driven top
1019  if (ipbl .eq. kcldtop .and. ipbl .gt. 0) then
1020 
1021  tmp2 = ((vbr3+vrad3+vsurf3+vshear3)**(2./3.)) / zradml_dev(i)
1022 
1023  wentr_rad = min( wentrmax, max(0., ((beta_surf_const *(vsurf3 + vshear3) + &
1024  beta_rad_const*(vrad3+vbr3) )/ zradml_dev(i))/(tmp1+tmp2) ) )
1025  wentr_pbl = wentr_rad
1026 
1027  k_entr_tmp = min( akmax, wentr_rad*(zfull_dev(i,kcldtop-1)-zfull_dev(i,kcldtop)) )
1028 
1029  pblfq(ipbl) = 1.
1030  radfq(kcldtop) = 1.
1031  radpbl = 1.
1032  k_rad(kcldtop) = k_entr_tmp
1033  k_t_troen(ipbl) = k_entr_tmp
1034  k_m_troen(ipbl) = k_entr_tmp
1035  k_t_entr_dev(i,kcldtop) = k_entr_tmp
1036  k_m_entr_dev(i,kcldtop) = k_entr_tmp
1037 
1038  end if
1039 
1040  !If there are any interior layers to calculate diffusivity
1041  if ( kcldtop .lt. ibot ) then
1042 
1043  do k = kcldtop+1,ibot
1044 
1045  ztmp = max(0.,(zhalf_dev(i,k)-zradbase_dev(i))/zradml_dev(i) )
1046 
1047  if (ztmp.gt.0.) then
1048 
1049  radfq(k) = 1.
1050  k_entr_tmp = khradfac_const*karman*( vrad+vbrv )*ztmp*zradml_dev(i)*ztmp*((1.-ztmp)**0.5)
1051  k_entr_tmp = min( k_entr_tmp, akmax )
1052  k_rad(k) = k_entr_tmp
1053  k_t_entr_dev(i,k) = k_t_entr_dev(i,k) + k_entr_tmp
1054  k_m_entr_dev(i,k) = k_m_entr_dev(i,k) + k_entr_tmp*prandtlrad_const
1055 
1056  end if
1057  enddo
1058 
1059  end if
1060 
1061  !Handle special case of zradbase_dev < zsml_dev, in this case there should be no entrainment from the surface.
1062  if (zradbase_dev(i) .lt. zsml_dev(i) .and. convpbl .eq. 1. .and. ipbl .gt. kcldtop) then
1063  wentr_pbl = 0.
1064  pblfq(ipbl) = 0.
1065  k_t_entr_dev(i,ipbl) = k_t_entr_dev(i,ipbl) - k_t_troen(ipbl)
1066  k_m_entr_dev(i,ipbl) = k_m_entr_dev(i,ipbl) - k_m_troen(ipbl)
1067  k_t_troen(ipbl) = 0.
1068  k_m_troen(ipbl) = 0.
1069  end if
1070 
1071  endif
1072 
1073  endif !kcldtop .ne. kcldbot
1074 
1075  endif !radlw_dep
1076 
1077  endif
1078 
1079  !Modify diffusivity coefficients using MAX( A , B )
1080  do k = 2, ibot
1081  diff_t_dev(i,k) = max( k_t_entr_dev(i,k), diff_t_dev(i,k) )
1082  diff_m_dev(i,k) = max( k_m_entr_dev(i,k), diff_m_dev(i,k) )
1083  k_t_entr_dev(i,k) = max( k_t_entr_dev(i,k), 0.0 )
1084  k_m_entr_dev(i,k) = max( k_m_entr_dev(i,k), 0.0 )
1085  enddo
1086 
1087 
1088  end do
1089 
1090 end subroutine lock_diff
1091 
1092 
1093 !=======================================================================
1094 subroutine mpbl_depth(i,ncol,nlev,tpfac, entrate, pceff, t, q, u, v, z, p, b_star, u_star , ipbl, ztop, ESTBLX)
1096  !Subroutine to calculate pbl depth
1097 
1098  IMPLICIT NONE
1099 
1100  !INPUTS
1101  integer, intent(in) :: i, nlev, ncol
1102  real(kind_real), intent(in) :: ESTBLX(:)
1103  real(kind_real), intent(in), dimension(ncol,nlev) :: t, z, q, p, u, v
1104  real(kind_real), intent(in), dimension(ncol) :: b_star, u_star
1105  real(kind_real), intent(in) :: tpfac, entrate, pceff
1106 
1107  !OUTPUTS
1108  integer, intent(out) :: ipbl
1109  real(kind_real), intent(out),dimension(ncol) :: ztop
1110 
1111  !LOCALS
1112  real(kind_real) :: tep,z1,z2,t1,t2,qp,pp,qsp,dqp,dqsp,u1,v1,u2,v2,du
1113  real(kind_real) :: ws,k_t_ref,entfr, tpfac_x, entrate_x,vscale,ptmp
1114  integer :: k
1115 
1116  !Calculate surface parcel properties
1117  tep = t(i,nlev)
1118  qp = q(i,nlev)
1119 
1120  !Wind dependence of plume character.
1121  vscale = 0.25 / 100. ! change of .25 m s-1 in 100 m
1122 
1123  !tpfac scales up bstar by inv. ratio of heat-bubble area to stagnant area
1124  tep = tep * (1.+ tpfac * b_star(i)/grav)
1125 
1126  !Search for level where this is exceeded
1127  t1 = t(i,nlev)
1128  v1 = v(i,nlev)
1129  u1 = u(i,nlev)
1130  z1 = z(i,nlev)
1131  ztop(i) = z1
1132 
1133  do k = nlev-1 , 2, -1
1134  z2 = z(i,k)
1135  t2 = t(i,k)
1136  u2 = u(i,k)
1137  v2 = v(i,k)
1138  pp = p(i,k)
1139 
1140  du = sqrt( ( u2 - u1 )**2 + ( v2 - v1 )**2 ) / (z2-z1)
1141  du = min(du,1.0e-8)
1142 
1143  entrate_x = entrate * ( 1.0 + du / vscale )
1144 
1145  entfr= min( entrate_x*(z2-z1), 0.99 )
1146 
1147  qp = qp + entfr*(q(i,k)-qp)
1148 
1149  !Dry adiabatic ascent through one layer. Static energy conserved.
1150  tep = tep - grav*( z2-z1 )/cp
1151 
1152  !Environmental air entrained
1153  tep = tep + entfr*(t(i,k)-tep)
1154 
1155  !dqsp = dqsat(tep , pp , qsat=qsp, pascals=.true. )
1156  ptmp = pp*0.01
1157  call dqsat_sub_sca(dqsp,qsp,tep,ptmp,estblx)
1158 
1159  dqp = max( qp - qsp, 0. )/(1.+(alhl/cp)*dqsp )
1160  qp = qp - dqp
1161  !"Precipitation efficiency" basically means fraction of condensation heating that gets applied to parcel
1162  tep = tep + pceff * alhl * dqp/cp
1163 
1164  !If parcel temperature (tep) colder than env (t2) OR if entrainment too big, declare this the PBL top
1165  if ( (t2 .ge. tep) .or. ( entfr .ge. 0.9899 ) ) then
1166  ztop(i) = 0.5*(z2+z1)
1167  ipbl = k+1
1168  exit
1169  end if
1170 
1171  z1 = z2
1172  t1 = t2
1173  u1 = u2
1174  v1 = v2
1175 
1176  enddo
1177 
1178 end subroutine mpbl_depth
1179 
1180 subroutine radml_depth(i, ncol, nlev, toplev, botlev, svp, zt, critjump, do_jump_exit, t, zf, zh, zb, zml)
1182  !Subroutine to calculate bottom and depth of radiatively driven mixed layer
1183 
1184  IMPLICIT NONE
1185 
1186  !INPUTS
1187  integer, intent(in) :: i, toplev, botlev, ncol, nlev
1188  real(kind_real), intent(in) :: svp, zt, critjump
1189  real(kind_real), intent(in), dimension(nlev) :: t
1190  real(kind_real), intent(in), dimension(ncol,nlev) :: zf
1191  real(kind_real), intent(in), dimension(ncol,nlev+1) :: zh
1192  logical, intent(in) :: do_jump_exit
1193 
1194  !OUTPUTS
1195  real(kind_real), intent(out), dimension(ncol) :: zb, zml
1196 
1197  !LOCALS
1198  real(kind_real) :: svpar,h1,h2,t1,t2,entrate,entfr
1199  integer :: k
1200 
1201  !Initialize zml
1202  zml(i) = 0.
1203 
1204  !Calculate cloud top parcel properties
1205  svpar = svp
1206  h1 = zf(i,toplev)
1207  t1 = t(toplev)
1208  entrate = 0.2/200.
1209 
1210  !Search for level where parcel is warmer than env. First cut out if parcel is already warmer than cloudtop.
1211  if (t1.lt.svpar) then
1212  zb(i) = h1
1213  zml(i) = 0.00
1214  return !udh - get rid of this if linearising
1215  endif
1216 
1217  !If above is false keep looking
1218  do k = 1,botlev
1219  if (k > toplev) then
1220  h2 = zf(i,k)
1221  t2 = t(k)
1222 
1223  if (t2.lt.svpar) then
1224  if ( abs(t1 - t2 ) .gt. 0.2 ) then
1225  zb(i) = h2 + (h1 - h2)*(svpar - t2)/(t1 - t2)
1226  zb(i) = max( zb(i) , 0. ) ! final protection against interp problems
1227  else
1228  zb(i) = h2
1229  endif
1230  zml(i) = zt - zb(i)
1231  return !dh get rid of this if linearising
1232  end if
1233 
1234  if (do_jump_exit .and. (t1-t2) .gt. critjump .and. k .gt. toplev+1) then
1235  zb(i) = zh(i,k)
1236  zml(i) = zt - zb(i)
1237  return !dh get rid of this if linearising
1238  end if
1239 
1240  entfr = min( entrate*(h1-h2), 1.0 )
1241  svpar = svpar + entfr*(t2-svpar)
1242 
1243  h1 = h2
1244  t1 = t2
1245 
1246  end if
1247 
1248  enddo
1249 
1250  zb(i) = 0.
1251  zml(i) = zt
1252 
1253 end subroutine radml_depth
1254 
1255 subroutine diffusivity_pbl2(i, ncol, lm, h, kfac, k_ent, vsurf, frland, zm, k_m, k_t)
1257  !Subroutine to return the vertical K-profile of diffusion coefficients for the surface driven convective mixed layer.
1258 
1259  IMPLICIT NONE
1260 
1261  !INPUTS
1262  integer, intent(in) :: i, lm, ncol
1263  real(kind_real), intent(in), dimension(ncol) :: h, frland
1264  real(kind_real), intent(in) :: k_ent, vsurf, kfac
1265  real(kind_real), intent(in), dimension(ncol,1:lm+1) :: zm
1266 
1267  !OUTPUTS
1268  real(kind_real), intent(out), dimension(lm) :: k_m, k_t
1269 
1270  !LOCALS
1271  real(kind_real) :: EE, hin, kfacx
1272  integer :: k, kk
1273 
1274  !Kluge. Raise KHs over land
1275  if ( frland(i) < 0.5 ) then
1276  kfacx = kfac
1277  else
1278  kfacx = kfac*2.0
1279  endif
1280 
1281  hin = 0.0 ! 200. ! "Organization" scale for plume (m).
1282 
1283  do k = 1, lm
1284  k_m(k) = 0.0
1285  k_t(k) = 0.0
1286  end do
1287 
1288  if ( vsurf*h(i) .gt. 0. ) then
1289  ee = 1.0 - sqrt( k_ent / ( kfacx * karman * vsurf * h(i) ) )
1290  ee = max( ee , 0.7 ) ! If EE is too small, then punt, as LCs
1291  do k = 1, lm
1292  if ( ( zm(i,k) .le. h(i) ) .and. ( zm(i,k) .gt. hin ) ) then
1293  k_t(k) = kfacx * karman * vsurf * ( zm(i,k)-hin ) * ( 1. - ee*( (zm(i,k)-hin)/(h(i)-hin) ))**2
1294  end if
1295  end do
1296  endif
1297 
1298  do k = 1, lm
1299  k_m(k) = k_t(k)
1300  end do
1301 
1302 end subroutine diffusivity_pbl2
1303 
1304 subroutine esinit(ESTBLX)
1305 !Initialise look-up table
1306 
1307  IMPLICIT NONE
1308 
1309  !OUTPUT
1310  real(kind_real), dimension(TABLESIZE) :: ESTBLX
1311 
1312  !LOCALS
1313  real(kind_real), parameter :: ZEROC = 273.16, tmix = -20.0
1314 
1315  real(kind_real), dimension(TABLESIZE) :: ESTBLE, ESTBLW
1316 
1317  integer :: I
1318  real(kind_real) :: T, DELTA_T
1319 
1320  delta_t = 1.0/degsubs
1321 
1322  do i=1,tablesize
1323 
1324  t = (i-1)*delta_t + tmintbl
1325 
1326  if(t>zeroc) then
1327  call qsatlqu0(estble(i),t)
1328  else
1329  call qsatice0(estble(i),t)
1330  end if
1331 
1332  call qsatlqu0(estblw(i),t)
1333 
1334  t = t-zeroc
1335  if(t>=tmix .and. t<0.0) then
1336  estblx(i) = ( t/tmix )*( estble(i) - estblw(i) ) + estblw(i)
1337  else
1338  estblx(i) = estble(i)
1339  end if
1340 
1341  end do
1342 
1343  end subroutine esinit
1344 
1345 
1346 subroutine qsatlqu0(QS,TL)
1347 !SUPERSATURATED AS LIQUID
1348 
1349  IMPLICIT NONE
1350 
1351  !INPUTS
1352  real(kind_real) :: TL!, TMAXTBL
1353 
1354  !OUTPUTS
1355  real(kind_real) :: QS
1356 
1357  !LOCALS
1358  real(kind_real), parameter :: ZEROC = 273.16
1359  real(kind_real), parameter :: TMINLQU = zeroc - 40.0
1360 
1361  real*8, parameter :: B6 = 6.136820929e-11*100.0
1362  real*8, parameter :: B5 = 2.034080948e-8 *100.0
1363  real*8, parameter :: B4 = 3.031240396e-6 *100.0
1364  real*8, parameter :: B3 = 2.650648471e-4 *100.0
1365  real*8, parameter :: B2 = 1.428945805e-2 *100.0
1366  real*8, parameter :: B1 = 4.436518521e-1 *100.0
1367  real*8, parameter :: B0 = 6.107799961e+0 *100.0
1368 
1369  real(8) :: TX, EX, TI, TT
1370 
1371  tx = tl
1372 
1373  if (tx<tminlqu) then
1374  ti = tminlqu
1375  elseif(tx>tmaxtbl) then
1376  ti = tmaxtbl
1377  else
1378  ti = tx
1379  end if
1380 
1381  tt = ti-zeroc !Starr polynomial fit
1382  ex = (tt*(tt*(tt*(tt*(tt*(tt*b6+b5)+b4)+b3)+b2)+b1)+b0)
1383 
1384  tl = tx
1385  qs = ex
1386 
1387  return
1388 
1389 end subroutine qsatlqu0
1390 
1391 
1392 subroutine qsatice0(QS,TL)
1393 !SUPERSATURATED AS ICE
1394 
1395  IMPLICIT NONE
1396 
1397  !INPUTS
1398  real(kind_real) :: TL
1399 
1400  !OUTPUTS
1401  real(kind_real) :: QS
1402 
1403  !LOCALS
1404  real(kind_real), parameter :: ZEROC = 273.16, tminstr = -95.0
1405  real(kind_real), parameter :: TMINICE = zeroc + tminstr
1406 
1407  real(kind_real), parameter :: TSTARR1 = -75.0, tstarr2 = -65.0, tstarr3 = -50.0, tstarr4 = -40.0
1408 
1409  real*8, parameter :: BI6= 1.838826904e-10*100.0
1410  real*8, parameter :: BI5= 4.838803174e-8 *100.0
1411  real*8, parameter :: BI4= 5.824720280e-6 *100.0
1412  real*8, parameter :: BI3= 4.176223716e-4 *100.0
1413  real*8, parameter :: BI2= 1.886013408e-2 *100.0
1414  real*8, parameter :: BI1= 5.034698970e-1 *100.0
1415  real*8, parameter :: BI0= 6.109177956e+0 *100.0
1416  real*8, parameter :: S16= 0.516000335e-11*100.0
1417  real*8, parameter :: S15= 0.276961083e-8 *100.0
1418  real*8, parameter :: S14= 0.623439266e-6 *100.0
1419  real*8, parameter :: S13= 0.754129933e-4 *100.0
1420  real*8, parameter :: S12= 0.517609116e-2 *100.0
1421  real*8, parameter :: S11= 0.191372282e+0 *100.0
1422  real*8, parameter :: S10= 0.298152339e+1 *100.0
1423  real*8, parameter :: S26= 0.314296723e-10*100.0
1424  real*8, parameter :: S25= 0.132243858e-7 *100.0
1425  real*8, parameter :: S24= 0.236279781e-5 *100.0
1426  real*8, parameter :: S23= 0.230325039e-3 *100.0
1427  real*8, parameter :: S22= 0.129690326e-1 *100.0
1428  real*8, parameter :: S21= 0.401390832e+0 *100.0
1429  real*8, parameter :: S20= 0.535098336e+1 *100.0
1430 
1431  real(kind_real) :: TX, TI, TT, W, EX
1432 
1433  tx = tl
1434 
1435  if (tx<tminice) then
1436  ti = tminice
1437  elseif(tx>zeroc ) then
1438  ti = zeroc
1439  else
1440  ti = tx
1441  end if
1442 
1443  tt = ti - zeroc
1444  if (tt < tstarr1 ) then
1445  ex = (tt*(tt*(tt*(tt*(tt*(tt*s16+s15)+s14)+s13)+s12)+s11)+s10)
1446  elseif(tt >= tstarr1 .and. tt < tstarr2) then
1447  w = (tstarr2 - tt)/(tstarr2-tstarr1)
1448  ex = w *(tt*(tt*(tt*(tt*(tt*(tt*s16+s15)+s14)+s13)+s12)+s11)+s10) &
1449  + (1.-w)*(tt*(tt*(tt*(tt*(tt*(tt*s26+s25)+s24)+s23)+s22)+s21)+s20)
1450  elseif(tt >= tstarr2 .and. tt < tstarr3) then
1451  ex = (tt*(tt*(tt*(tt*(tt*(tt*s26+s25)+s24)+s23)+s22)+s21)+s20)
1452  elseif(tt >= tstarr3 .and. tt < tstarr4) then
1453  w = (tstarr4 - tt)/(tstarr4-tstarr3)
1454  ex = w *(tt*(tt*(tt*(tt*(tt*(tt*s26+s25)+s24)+s23)+s22)+s21)+s20) &
1455  + (1.-w)*(tt*(tt*(tt*(tt*(tt*(tt*bi6+bi5)+bi4)+bi3)+bi2)+bi1)+bi0)
1456  else
1457  ex = (tt*(tt*(tt*(tt*(tt*(tt*bi6+bi5)+bi4)+bi3)+bi2)+bi1)+bi0)
1458  endif
1459 
1460  qs = ex
1461 
1462  return
1463 
1464 end subroutine qsatice0
1465 
1466 subroutine dqsat_sub_sca(DQSi,QSSi,TEMP,PLO,ESTBLX)
1467 !COMPUTES SATURATION VAPOUR PRESSURE QSSi AND GRADIENT w.r.t TEMPERATURE DQSi.
1468 !INPUTS ARE TEMPERATURE AND PLO (PRESSURE AT T-LEVELS)
1469 !VALES ARE COMPUTED FROM LOOK-UP TALBE (PIECEWISE LINEAR)
1470 
1471  IMPLICIT NONE
1472 
1473  !Inputs
1474  real(kind_real) :: TEMP, PLO
1475  real(kind_real) :: ESTBLX(:)
1476 
1477  !Outputs
1478  real(kind_real) :: DQSi, QSSi
1479 
1480  !Locals
1481  real(kind_real), parameter :: MAX_MIXING_RATIO = 1.0
1482  real(kind_real), parameter :: ESFAC = h2omw/airmw
1483 
1484  real(kind_real) :: TL, TT, TI, DQSAT, QSAT, DQQ, QQ, PL, PP, DD
1485  integer :: IT
1486 
1487  tl = temp
1488  pl = plo
1489 
1490  pp = pl*100.0
1491 
1492  if (tl<=tmintbl) then
1493  ti = tmintbl
1494  elseif(tl>=tmaxtbl-.001) then
1495  ti = tmaxtbl-.001
1496  else
1497  ti = tl
1498  end if
1499 
1500  tt = (ti - tmintbl)*degsubs+1
1501  it = int(tt)
1502 
1503  dqq = estblx(it+1) - estblx(it)
1504  qq = (tt-it)*dqq + estblx(it)
1505 
1506  if (pp <= qq) then
1507  qsat = max_mixing_ratio
1508  dqsat = 0.0
1509  else
1510  dd = 1.0/(pp - (1.0-esfac)*qq)
1511  qsat = esfac*qq*dd
1512  dqsat = (esfac*degsubs)*dqq*pp*(dd*dd)
1513  end if
1514 
1515  dqsi = dqsat
1516  qssi = qsat
1517 
1518 end subroutine dqsat_sub_sca
1519 
1520 
1521 
1522 END MODULE bldriver
real(kind=kind_real), parameter, public grav
subroutine dqsat_sub_sca(DQSi, QSSi, TEMP, PLO, ESTBLX)
Definition: bldriver.F90:1467
subroutine esinit(ESTBLX)
Definition: bldriver.F90:1305
real(kind=kind_real), parameter, public p00
subroutine diffusivity_pbl2(i, ncol, lm, h, kfac, k_ent, vsurf, frland, zm, k_m, k_t)
Definition: bldriver.F90:1256
real(kind=kind_real), parameter, public pi
subroutine mpbl_depth(i, ncol, nlev, tpfac, entrate, pceff, t, q, u, v, z, p, b_star, u_star, ipbl, ztop, ESTBLX)
Definition: bldriver.F90:1095
real(kind=kind_real), parameter, public airmw
subroutine qsatlqu0(QS, TL)
Definition: bldriver.F90:1347
subroutine, public bl_driver(IM, JM, LM, DT, U, V, TH, Q, P, QIT, QLT, FRLAND, FROCEAN, VARFLT, ZPBL, CM, CT, CQ, TURBPARAMS, TURBPARAMSI, USTAR, BSTAR, AKS, BKS, CKS, AKQ, BKQ, CKQ, AKV, BKV, CKV, EKV, FKV)
Definition: bldriver.F90:28
subroutine orodrag(IRUN, LM, DT, LAMBDA_B, C_B, FKV, BKV, U, V, ZFULL, VARFLT, PHALF)
Definition: bldriver.F90:613
subroutine preliminary(IRUN, LM, DT, T, QV, PHALF, TH, QIT, QLT, ZFULL, ZHALF, TV, PV, RDZ, DMI, PFULL)
Definition: bldriver.F90:303
subroutine lock_diff(ncol, nlev, tdtlw_in_dev, u_star_dev, b_star_dev, frland_dev, t_dev, qv_dev, qit_dev, qlt_dev, u_dev, v_dev, zfull_dev, pfull_dev, zhalf_dev, phalf_dev, diff_m_dev, diff_t_dev, prandtlsfc_const, prandtlrad_const, beta_surf_const, beta_rad_const, tpfac_sfc_const, entrate_sfc_const, pceff_sfc_const, khradfac_const, khsfcfac_const, radlw_dep, ESTBLX)
Definition: bldriver.F90:663
real(kind_real), parameter tmaxtbl
Definition: bldriver.F90:18
subroutine tridiag_setup(IRUN, LM, DT, KPBLMIN, ZFULL, PFULL, RDZ, DMI, PHALF, TV, CT, CQ, CU, T, Q, TH, U, V, DIFF_T, DIFF_M, AKQ, AKS, AKV, BKQ, BKS, BKV, CKQ, CKS, CKV, EKV, ZPBL)
Definition: bldriver.F90:507
subroutine louis_diff(IRUN, LM, KH, KM, RI, DU, ZPBL, ZZ, ZE, PV, UU, VV, LOUIS, MINSHEAR, MINTHICK, LAMBDAM, LAMBDAM2, LAMBDAH, LAMBDAH2, ZKMENV, ZKHENV, AKHMMAX, ALH_DIAG, KMLS_DIAG, KHLS_DIAG)
Definition: bldriver.F90:375
subroutine radml_depth(i, ncol, nlev, toplev, botlev, svp, zt, critjump, do_jump_exit, t, zf, zh, zb, zml)
Definition: bldriver.F90:1181
integer, parameter tablesize
Definition: bldriver.F90:19
real(kind=kind_real), parameter, public cp
real(kind=kind_real), parameter, public vireps
integer, parameter degsubs
Definition: bldriver.F90:17
real(kind=kind_real), parameter, public tice
#define max(a, b)
Definition: mosaic_util.h:33
subroutine qsatice0(QS, TL)
Definition: bldriver.F90:1393
real(kind=kind_real), parameter, public h2omw
real(kind=kind_real), parameter, public alhs
real(kind=kind_real), parameter, public rgas
#define min(a, b)
Definition: mosaic_util.h:32
real(kind_real), parameter tmintbl
Definition: bldriver.F90:18
real(kind=kind_real), parameter, public karman
real(kind=kind_real), parameter, public kappa
Constants for the FV3 model.
real(kind=kind_real), parameter, public alhl