source: LMDZ6/branches/Amaury_dev/libf/phylmd/nonlocal.F90 @ 5151

Last change on this file since 5151 was 5144, checked in by abarral, 7 weeks ago

Put YOMCST.h into modules

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