GCC Code Coverage Report


Directory: ./
File: phys/nonlocal.f90
Date: 2022-01-11 19:19:34
Exec Total Coverage
Lines: 0 172 0.0%
Branches: 0 92 0.0%

Line Branch Exec Source
1
2 ! $Header$
3
4 ! ======================================================================
5 SUBROUTINE nonlocal(knon, paprs, pplay, tsol, beta, u, v, t, q, cd_h, cd_m, &
6 pcfh, pcfm, cgh, cgq)
7 USE dimphy
8 IMPLICIT NONE
9 ! ======================================================================
10 ! Laurent Li (LMD/CNRS), le 30 septembre 1998
11 ! Couche limite non-locale. Adaptation du code du CCM3.
12 ! Code non teste, donc a ne pas utiliser.
13 ! ======================================================================
14 ! Nonlocal scheme that determines eddy diffusivities based on a
15 ! diagnosed boundary layer height and a turbulent velocity scale.
16 ! Also countergradient effects for heat and moisture are included.
17
18 ! For more information, see Holtslag, A.A.M., and B.A. Boville, 1993:
19 ! Local versus nonlocal boundary-layer diffusion in a global climate
20 ! model. J. of Climate, vol. 6, 1825-1842.
21 ! ======================================================================
22 include "YOMCST.h"
23
24 ! Arguments:
25
26 INTEGER knon ! nombre de points a calculer
27 REAL tsol(klon) ! temperature du sol (K)
28 REAL beta(klon) ! efficacite d'evaporation (entre 0 et 1)
29 REAL paprs(klon, klev+1) ! pression a inter-couche (Pa)
30 REAL pplay(klon, klev) ! pression au milieu de couche (Pa)
31 REAL u(klon, klev) ! vitesse U (m/s)
32 REAL v(klon, klev) ! vitesse V (m/s)
33 REAL t(klon, klev) ! temperature (K)
34 REAL q(klon, klev) ! vapeur d'eau (kg/kg)
35 REAL cd_h(klon) ! coefficient de friction au sol pour chaleur
36 REAL cd_m(klon) ! coefficient de friction au sol pour vitesse
37
38 INTEGER isommet
39 REAL vk
40 PARAMETER (vk=0.40)
41 REAL ricr
42 PARAMETER (ricr=0.4)
43 REAL fak
44 PARAMETER (fak=8.5)
45 REAL fakn
46 PARAMETER (fakn=7.2)
47 REAL onet
48 PARAMETER (onet=1.0/3.0)
49 REAL t_coup
50 PARAMETER (t_coup=273.15)
51 REAL zkmin
52 PARAMETER (zkmin=0.01)
53 REAL betam
54 PARAMETER (betam=15.0)
55 REAL betah
56 PARAMETER (betah=15.0)
57 REAL betas
58 PARAMETER (betas=5.0)
59 REAL sffrac
60 PARAMETER (sffrac=0.1)
61 REAL binm
62 PARAMETER (binm=betam*sffrac)
63 REAL binh
64 PARAMETER (binh=betah*sffrac)
65 REAL ccon
66 PARAMETER (ccon=fak*sffrac*vk)
67
68 REAL z(klon, klev)
69 REAL pcfm(klon, klev), pcfh(klon, klev)
70
71 INTEGER i, k
72 REAL zxt, zxq, zxu, zxv, zxmod, taux, tauy
73 REAL zx_alf1, zx_alf2 ! parametres pour extrapolation
74 REAL khfs(klon) ! surface kinematic heat flux [mK/s]
75 REAL kqfs(klon) ! sfc kinematic constituent flux [m/s]
76 REAL heatv(klon) ! surface virtual heat flux
77 REAL ustar(klon)
78 REAL rino(klon, klev) ! bulk Richardon no. from level to ref lev
79 LOGICAL unstbl(klon) ! pts w/unstbl pbl (positive virtual ht flx)
80 LOGICAL stblev(klon) ! stable pbl with levels within pbl
81 LOGICAL unslev(klon) ! unstbl pbl with levels within pbl
82 LOGICAL unssrf(klon) ! unstb pbl w/lvls within srf pbl lyr
83 LOGICAL unsout(klon) ! unstb pbl w/lvls in outer pbl lyr
84 LOGICAL check(klon) ! True=>chk if Richardson no.>critcal
85 REAL pblh(klon)
86 REAL cgh(klon, 2:klev) ! counter-gradient term for heat [K/m]
87 REAL cgq(klon, 2:klev) ! counter-gradient term for constituents
88 REAL cgs(klon, 2:klev) ! counter-gradient star (cg/flux)
89 REAL obklen(klon)
90 REAL ztvd, ztvu, zdu2
91 REAL therm(klon) ! thermal virtual temperature excess
92 REAL phiminv(klon) ! inverse phi function for momentum
93 REAL phihinv(klon) ! inverse phi function for heat
94 REAL wm(klon) ! turbulent velocity scale for momentum
95 REAL fak1(klon) ! k*ustar*pblh
96 REAL fak2(klon) ! k*wm*pblh
97 REAL fak3(klon) ! fakn*wstr/wm
98 REAL pblk(klon) ! level eddy diffusivity for momentum
99 REAL pr(klon) ! Prandtl number for eddy diffusivities
100 REAL zl(klon) ! zmzp / Obukhov length
101 REAL zh(klon) ! zmzp / pblh
102 REAL zzh(klon) ! (1-(zmzp/pblh))**2
103 REAL wstr(klon) ! w*, convective velocity scale
104 REAL zm(klon) ! current level height
105 REAL zp(klon) ! current level height + one level up
106 REAL zcor, zdelta, zcvm5, zxqs
107 REAL fac, pblmin, zmzp, term
108
109 include "YOETHF.h"
110 include "FCTTRE.h"
111
112 ! Initialisation
113
114 isommet = klev
115
116 DO i = 1, klon
117 pcfh(i, 1) = cd_h(i)
118 pcfm(i, 1) = cd_m(i)
119 END DO
120 DO k = 2, klev
121 DO i = 1, klon
122 pcfh(i, k) = zkmin
123 pcfm(i, k) = zkmin
124 cgs(i, k) = 0.0
125 cgh(i, k) = 0.0
126 cgq(i, k) = 0.0
127 END DO
128 END DO
129
130 ! Calculer les hauteurs de chaque couche
131
132 DO i = 1, knon
133 z(i, 1) = rd*t(i, 1)/(0.5*(paprs(i,1)+pplay(i,1)))*(paprs(i,1)-pplay(i,1) &
134 )/rg
135 END DO
136 DO k = 2, klev
137 DO i = 1, knon
138 z(i, k) = z(i, k-1) + rd*0.5*(t(i,k-1)+t(i,k))/paprs(i, k)*(pplay(i,k-1 &
139 )-pplay(i,k))/rg
140 END DO
141 END DO
142
143 DO i = 1, knon
144 IF (thermcep) THEN
145 zdelta = max(0., sign(1.,rtt-tsol(i)))
146 zcvm5 = r5les*rlvtt*(1.-zdelta) + r5ies*rlstt*zdelta
147 zcvm5 = zcvm5/rcpd/(1.0+rvtmp2*q(i,1))
148 zxqs = r2es*foeew(tsol(i), zdelta)/paprs(i, 1)
149 zxqs = min(0.5, zxqs)
150 zcor = 1./(1.-retv*zxqs)
151 zxqs = zxqs*zcor
152 ELSE
153 IF (tsol(i)<t_coup) THEN
154 zxqs = qsats(tsol(i))/paprs(i, 1)
155 ELSE
156 zxqs = qsatl(tsol(i))/paprs(i, 1)
157 END IF
158 END IF
159 zx_alf1 = 1.0
160 zx_alf2 = 1.0 - zx_alf1
161 zxt = (t(i,1)+z(i,1)*rg/rcpd/(1.+rvtmp2*q(i,1)))*(1.+retv*q(i,1))*zx_alf1 &
162 + (t(i,2)+z(i,2)*rg/rcpd/(1.+rvtmp2*q(i,2)))*(1.+retv*q(i,2))*zx_alf2
163 zxu = u(i, 1)*zx_alf1 + u(i, 2)*zx_alf2
164 zxv = v(i, 1)*zx_alf1 + v(i, 2)*zx_alf2
165 zxq = q(i, 1)*zx_alf1 + q(i, 2)*zx_alf2
166 zxmod = 1.0 + sqrt(zxu**2+zxv**2)
167 khfs(i) = (tsol(i)*(1.+retv*q(i,1))-zxt)*zxmod*cd_h(i)
168 kqfs(i) = (zxqs-zxq)*zxmod*cd_h(i)*beta(i)
169 heatv(i) = khfs(i) + 0.61*zxt*kqfs(i)
170 taux = zxu*zxmod*cd_m(i)
171 tauy = zxv*zxmod*cd_m(i)
172 ustar(i) = sqrt(taux**2+tauy**2)
173 ustar(i) = max(sqrt(ustar(i)), 0.01)
174 END DO
175
176 DO i = 1, knon
177 rino(i, 1) = 0.0
178 check(i) = .TRUE.
179 pblh(i) = z(i, 1)
180 obklen(i) = -t(i, 1)*ustar(i)**3/(rg*vk*heatv(i))
181 END DO
182
183
184 ! PBL height calculation:
185 ! Search for level of pbl. Scan upward until the Richardson number between
186 ! the first level and the current level exceeds the "critical" value.
187
188 fac = 100.0
189 DO k = 1, isommet
190 DO i = 1, knon
191 IF (check(i)) THEN
192 zdu2 = (u(i,k)-u(i,1))**2 + (v(i,k)-v(i,1))**2 + fac*ustar(i)**2
193 zdu2 = max(zdu2, 1.0E-20)
194 ztvd = (t(i,k)+z(i,k)*0.5*rg/rcpd/(1.+rvtmp2*q(i, &
195 k)))*(1.+retv*q(i,k))
196 ztvu = (t(i,1)-z(i,k)*0.5*rg/rcpd/(1.+rvtmp2*q(i, &
197 1)))*(1.+retv*q(i,1))
198 rino(i, k) = (z(i,k)-z(i,1))*rg*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu))
199 IF (rino(i,k)>=ricr) THEN
200 pblh(i) = z(i, k-1) + (z(i,k-1)-z(i,k))*(ricr-rino(i,k-1))/(rino(i, &
201 k-1)-rino(i,k))
202 check(i) = .FALSE.
203 END IF
204 END IF
205 END DO
206 END DO
207
208
209 ! Set pbl height to maximum value where computation exceeds number of
210 ! layers allowed
211
212 DO i = 1, knon
213 IF (check(i)) pblh(i) = z(i, isommet)
214 END DO
215
216 ! Improve estimate of pbl height for the unstable points.
217 ! Find unstable points (sensible heat flux is upward):
218
219 DO i = 1, knon
220 IF (heatv(i)>0.) THEN
221 unstbl(i) = .TRUE.
222 check(i) = .TRUE.
223 ELSE
224 unstbl(i) = .FALSE.
225 check(i) = .FALSE.
226 END IF
227 END DO
228
229 ! For the unstable case, compute velocity scale and the
230 ! convective temperature excess:
231
232 DO i = 1, knon
233 IF (check(i)) THEN
234 phiminv(i) = (1.-binm*pblh(i)/obklen(i))**onet
235 wm(i) = ustar(i)*phiminv(i)
236 therm(i) = heatv(i)*fak/wm(i)
237 rino(i, 1) = 0.0
238 END IF
239 END DO
240
241 ! Improve pblh estimate for unstable conditions using the
242 ! convective temperature excess:
243
244 DO k = 1, isommet
245 DO i = 1, knon
246 IF (check(i)) THEN
247 zdu2 = (u(i,k)-u(i,1))**2 + (v(i,k)-v(i,1))**2 + fac*ustar(i)**2
248 zdu2 = max(zdu2, 1.0E-20)
249 ztvd = (t(i,k)+z(i,k)*0.5*rg/rcpd/(1.+rvtmp2*q(i, &
250 k)))*(1.+retv*q(i,k))
251 ztvu = (t(i,1)+therm(i)-z(i,k)*0.5*rg/rcpd/(1.+rvtmp2*q(i, &
252 1)))*(1.+retv*q(i,1))
253 rino(i, k) = (z(i,k)-z(i,1))*rg*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu))
254 IF (rino(i,k)>=ricr) THEN
255 pblh(i) = z(i, k-1) + (z(i,k-1)-z(i,k))*(ricr-rino(i,k-1))/(rino(i, &
256 k-1)-rino(i,k))
257 check(i) = .FALSE.
258 END IF
259 END IF
260 END DO
261 END DO
262
263 ! Set pbl height to maximum value where computation exceeds number of
264 ! layers allowed
265
266 DO i = 1, knon
267 IF (check(i)) pblh(i) = z(i, isommet)
268 END DO
269
270 ! Points for which pblh exceeds number of pbl layers allowed;
271 ! set to maximum
272
273 DO i = 1, knon
274 IF (check(i)) pblh(i) = z(i, isommet)
275 END DO
276
277 ! PBL height must be greater than some minimum mechanical mixing depth
278 ! Several investigators have proposed minimum mechanical mixing depth
279 ! relationships as a function of the local friction velocity, u*. We
280 ! make use of a linear relationship of the form h = c u* where c=700.
281 ! The scaling arguments that give rise to this relationship most often
282 ! represent the coefficient c as some constant over the local coriolis
283 ! parameter. Here we make use of the experimental results of Koracin
284 ! and Berkowicz (1988) [BLM, Vol 43] for wich they recommend 0.07/f
285 ! where f was evaluated at 39.5 N and 52 N. Thus we use a typical mid
286 ! latitude value for f so that c = 0.07/f = 700.
287
288 DO i = 1, knon
289 pblmin = 700.0*ustar(i)
290 pblh(i) = max(pblh(i), pblmin)
291 END DO
292
293 ! pblh is now available; do preparation for diffusivity calculation:
294
295 DO i = 1, knon
296 pblk(i) = 0.0
297 fak1(i) = ustar(i)*pblh(i)*vk
298
299 ! Do additional preparation for unstable cases only, set temperature
300 ! and moisture perturbations depending on stability.
301
302 IF (unstbl(i)) THEN
303 zxt = (t(i,1)-z(i,1)*0.5*rg/rcpd/(1.+rvtmp2*q(i,1)))*(1.+retv*q(i,1))
304 phiminv(i) = (1.-binm*pblh(i)/obklen(i))**onet
305 phihinv(i) = sqrt(1.-binh*pblh(i)/obklen(i))
306 wm(i) = ustar(i)*phiminv(i)
307 fak2(i) = wm(i)*pblh(i)*vk
308 wstr(i) = (heatv(i)*rg*pblh(i)/zxt)**onet
309 fak3(i) = fakn*wstr(i)/wm(i)
310 END IF
311 END DO
312
313 ! Main level loop to compute the diffusivities and
314 ! counter-gradient terms:
315
316 DO k = 2, isommet
317
318 ! Find levels within boundary layer:
319
320 DO i = 1, knon
321 unslev(i) = .FALSE.
322 stblev(i) = .FALSE.
323 zm(i) = z(i, k-1)
324 zp(i) = z(i, k)
325 IF (zkmin==0.0 .AND. zp(i)>pblh(i)) zp(i) = pblh(i)
326 IF (zm(i)<pblh(i)) THEN
327 zmzp = 0.5*(zm(i)+zp(i))
328 zh(i) = zmzp/pblh(i)
329 zl(i) = zmzp/obklen(i)
330 zzh(i) = 0.
331 IF (zh(i)<=1.0) zzh(i) = (1.-zh(i))**2
332
333 ! stblev for points zm < plbh and stable and neutral
334 ! unslev for points zm < plbh and unstable
335
336 IF (unstbl(i)) THEN
337 unslev(i) = .TRUE.
338 ELSE
339 stblev(i) = .TRUE.
340 END IF
341 END IF
342 END DO
343
344 ! Stable and neutral points; set diffusivities; counter-gradient
345 ! terms zero for stable case:
346
347 DO i = 1, knon
348 IF (stblev(i)) THEN
349 IF (zl(i)<=1.) THEN
350 pblk(i) = fak1(i)*zh(i)*zzh(i)/(1.+betas*zl(i))
351 ELSE
352 pblk(i) = fak1(i)*zh(i)*zzh(i)/(betas+zl(i))
353 END IF
354 pcfm(i, k) = pblk(i)
355 pcfh(i, k) = pcfm(i, k)
356 END IF
357 END DO
358
359 ! unssrf, unstable within surface layer of pbl
360 ! unsout, unstable within outer layer of pbl
361
362 DO i = 1, knon
363 unssrf(i) = .FALSE.
364 unsout(i) = .FALSE.
365 IF (unslev(i)) THEN
366 IF (zh(i)<sffrac) THEN
367 unssrf(i) = .TRUE.
368 ELSE
369 unsout(i) = .TRUE.
370 END IF
371 END IF
372 END DO
373
374 ! Unstable for surface layer; counter-gradient terms zero
375
376 DO i = 1, knon
377 IF (unssrf(i)) THEN
378 term = (1.-betam*zl(i))**onet
379 pblk(i) = fak1(i)*zh(i)*zzh(i)*term
380 pr(i) = term/sqrt(1.-betah*zl(i))
381 END IF
382 END DO
383
384 ! Unstable for outer layer; counter-gradient terms non-zero:
385
386 DO i = 1, knon
387 IF (unsout(i)) THEN
388 pblk(i) = fak2(i)*zh(i)*zzh(i)
389 cgs(i, k) = fak3(i)/(pblh(i)*wm(i))
390 cgh(i, k) = khfs(i)*cgs(i, k)
391 pr(i) = phiminv(i)/phihinv(i) + ccon*fak3(i)/fak
392 cgq(i, k) = kqfs(i)*cgs(i, k)
393 END IF
394 END DO
395
396 ! For all unstable layers, set diffusivities
397
398 DO i = 1, knon
399 IF (unslev(i)) THEN
400 pcfm(i, k) = pblk(i)
401 pcfh(i, k) = pblk(i)/pr(i)
402 END IF
403 END DO
404 END DO ! end of level loop
405
406 RETURN
407 END SUBROUTINE nonlocal
408