GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: phylmd/hbtm_mod.F90 Lines: 189 189 100.0 %
Date: 2023-06-30 12:51:15 Branches: 90 96 93.8 %

Line Branch Exec Source
1
module hbtm_mod
2
3
  IMPLICIT NONE
4
5
contains
6
7
24347798
  SUBROUTINE hbtm(knon, paprs, pplay, t2m, t10m, q2m, q10m, ustar, wstar, &
8
1152
       flux_t, flux_q, u, v, t, q, pblh, cape, eauliq, ctei, pblt, therm, &
9
       trmb1, trmb2, trmb3, plcl)
10
    USE dimphy
11
12
    ! ***************************************************************
13
    ! *                                                             *
14
    ! * HBTM2   D'apres Holstag&Boville et Troen&Mahrt              *
15
    ! *                 JAS 47              BLM                     *
16
    ! * Algorithme These Anne Mathieu                               *
17
    ! * Critere d'Entrainement Peter Duynkerke (JAS 50)             *
18
    ! * written by  : Anne MATHIEU & Alain LAHELLEC, 22/11/99       *
19
    ! * features : implem. exces Mathieu                            *
20
    ! ***************************************************************
21
    ! * mods : decembre 99 passage th a niveau plus bas. voir fixer *
22
    ! * la prise du th a z/Lambda = -.2 (max Ray)                   *
23
    ! * Autre algo : entrainement ~ Theta+v =cste mais comment=>The?*
24
    ! * on peut fixer q a .7qsat(cf non adiab)=>T2 et The2          *
25
    ! * voir aussi //KE pblh = niveau The_e ou l = env.             *
26
    ! ***************************************************************
27
    ! * fin therm a la HBTM passage a forme Mathieu 12/09/2001      *
28
    ! ***************************************************************
29
    ! *
30
31
32
    ! AM Fev 2003
33
    ! Adaptation a LMDZ version couplee
34
35
    ! Pour le moment on fait passer en argument les grdeurs de surface :
36
    ! flux, t,q2m, t,q10m, on va utiliser systematiquement les grdeurs a 2m ms
37
    ! on garde la possibilite de changer si besoin est (jusqu'a present la
38
    ! forme de HB avec le 1er niveau modele etait conservee)
39
40
41
42
43
44
    include "YOMCST.h"
45
    REAL rlvcp, reps
46
    ! Arguments:
47
48
    INTEGER knon ! nombre de points a calculer
49
    ! AM
50
    REAL t2m(klon), t10m(klon) ! temperature a 2 et 10m
51
    REAL q2m(klon), q10m(klon) ! q a 2 et 10m
52
    REAL ustar(klon)
53
    REAL wstar(klon) ! w*, convective velocity scale
54
    REAL paprs(klon, klev+1) ! pression a inter-couche (Pa)
55
    REAL pplay(klon, klev) ! pression au milieu de couche (Pa)
56
    REAL flux_t(klon, klev), flux_q(klon, klev) ! Flux
57
    REAL u(klon, klev) ! vitesse U (m/s)
58
    REAL v(klon, klev) ! vitesse V (m/s)
59
    REAL t(klon, klev) ! temperature (K)
60
    REAL q(klon, klev) ! vapeur d'eau (kg/kg)
61
    ! AM      REAL cd_h(klon) ! coefficient de friction au sol pour chaleur
62
    ! AM      REAL cd_m(klon) ! coefficient de friction au sol pour vitesse
63
64
    INTEGER isommet
65
    ! um      PARAMETER (isommet=klev) ! limite max sommet pbl
66
    REAL, PARAMETER :: vk = 0.35 ! Von Karman => passer a .41 ! cf U.Olgstrom
67
    REAL, PARAMETER :: ricr = 0.4
68
    REAL, PARAMETER :: fak = 8.5 ! b calcul du Prandtl et de dTetas
69
    REAL, PARAMETER :: fakn = 7.2 ! a
70
    REAL, PARAMETER :: onet = 1.0/3.0
71
    REAL, PARAMETER :: t_coup = 273.15
72
    REAL, PARAMETER :: zkmin = 0.01
73
    REAL, PARAMETER :: betam = 15.0 ! pour Phim / h dans la S.L stable
74
    REAL, PARAMETER :: betah = 15.0
75
76
    REAL, PARAMETER :: betas = 5.0
77
    ! Phit dans la S.L. stable (mais 2 formes / z/OBL<>1
78
79
    REAL, PARAMETER :: sffrac = 0.1 ! S.L. = z/h < .1
80
    REAL, PARAMETER :: usmin = 1.E-12
81
    REAL, PARAMETER :: binm = betam*sffrac
82
    REAL, PARAMETER :: binh = betah*sffrac
83
    REAL, PARAMETER :: ccon = fak*sffrac*vk
84
    REAL, PARAMETER :: b1 = 70., b2 = 20.
85
    REAL, PARAMETER :: zref = 2. ! Niveau de ref a 2m peut eventuellement
86
    ! etre choisi a 10m
87
    REAL q_star, t_star
88
    REAL b212, b2sr ! Lambert correlations T' q' avec T* q*
89
90
2304
    REAL z(klon, klev)
91
    ! AM      REAL pcfm(klon,klev), pcfh(klon,klev)
92
    INTEGER i, k, j
93
    REAL zxt
94
    ! AM      REAL zxt, zxq, zxu, zxv, zxmod, taux, tauy
95
    ! AM      REAL zx_alf1, zx_alf2 ! parametres pour extrapolation
96
2304
    REAL khfs(klon) ! surface kinematic heat flux [mK/s]
97
2304
    REAL kqfs(klon) ! sfc kinematic constituent flux [m/s]
98
2304
    REAL heatv(klon) ! surface virtual heat flux
99
2304
    REAL rhino(klon, klev) ! bulk Richardon no. mais en Theta_v
100
2304
    LOGICAL unstbl(klon) ! pts w/unstbl pbl (positive virtual ht flx)
101
2304
    LOGICAL stblev(klon) ! stable pbl with levels within pbl
102
2304
    LOGICAL unslev(klon) ! unstbl pbl with levels within pbl
103
2304
    LOGICAL unssrf(klon) ! unstb pbl w/lvls within srf pbl lyr
104
2304
    LOGICAL unsout(klon) ! unstb pbl w/lvls in outer pbl lyr
105
2304
    LOGICAL check(klon) ! True=>chk if Richardson no.>critcal
106
2304
    LOGICAL omegafl(klon) ! flag de prolongerment cape pour pt Omega
107
    REAL pblh(klon)
108
    REAL pblt(klon)
109
    REAL plcl(klon)
110
    ! AM      REAL cgh(klon,2:klev) ! counter-gradient term for heat [K/m]
111
    ! AM      REAL cgq(klon,2:klev) ! counter-gradient term for constituents
112
    ! AM      REAL cgs(klon,2:klev) ! counter-gradient star (cg/flux)
113
2304
    REAL unsobklen(klon) ! Monin-Obukhov lengh
114
    ! AM      REAL ztvd, ztvu,
115
    REAL zdu2
116
    REAL, intent(out):: therm(:) ! (klon) thermal virtual temperature excess
117
    REAL trmb1(klon), trmb2(klon), trmb3(klon)
118
    ! Algorithme thermique
119
2304
    REAL s(klon, klev) ! [P/Po]^Kappa milieux couches
120
2304
    REAL th_th(klon) ! potential temperature of thermal
121
2304
    REAL the_th(klon) ! equivalent potential temperature of thermal
122
2304
    REAL qt_th(klon) ! total water  of thermal
123
2304
    REAL tbef(klon) ! T thermique niveau precedent
124
2304
    REAL qsatbef(klon)
125
2304
    LOGICAL zsat(klon) ! le thermique est sature
126
    REAL cape(klon) ! Cape du thermique
127
2304
    REAL kape(klon) ! Cape locale
128
    REAL eauliq(klon) ! Eau liqu integr du thermique
129
    REAL ctei(klon) ! Critere d'instab d'entrainmt des nuages de CL
130
    REAL the1, the2, aa, bb, zthvd, zthvu, xintpos, qqsat
131
    ! IM 091204 BEG
132
    REAL a1, a2, a3
133
    ! IM 091204 END
134
    REAL xhis, rnum, denom, th1, th2, thv1, thv2, ql2
135
    REAL dqsat_dt, qsat2, qt1, q2, t1, t2, xnull, delt_the
136
    REAL delt_qt, delt_2, quadsat, spblh, reduc
137
138
2304
    REAL phiminv(klon) ! inverse phi function for momentum
139
2304
    REAL phihinv(klon) ! inverse phi function for heat
140
2304
    REAL wm(klon) ! turbulent velocity scale for momentum
141
2304
    REAL fak1(klon) ! k*ustar*pblh
142
2304
    REAL fak2(klon) ! k*wm*pblh
143
2304
    REAL fak3(klon) ! fakn*wstar/wm
144
2304
    REAL pblk(klon) ! level eddy diffusivity for momentum
145
2304
    REAL pr(klon) ! Prandtl number for eddy diffusivities
146
2304
    REAL zl(klon) ! zmzp / Obukhov length
147
2304
    REAL zh(klon) ! zmzp / pblh
148
2304
    REAL zzh(klon) ! (1-(zmzp/pblh))**2
149
2304
    REAL zm(klon) ! current level height
150
1152
    REAL zp(klon) ! current level height + one level up
151
    REAL zcor, zdelta, zcvm5
152
    ! AM      REAL zxqs
153
    REAL fac, pblmin, zmzp, term
154
155
    include "YOETHF.h"
156
    include "FCTTRE.h"
157
158
159
160
    ! initialisations (Anne)
161
    isommet = klev
162
1146240
    th_th(:) = 0.
163
    q_star = 0
164
    t_star = 0
165
1146240
    therm = 0.
166
167
    b212 = sqrt(b1*b2)
168
    b2sr = sqrt(b2)
169
170
    ! ============================================================
171
    ! Fonctions thermo implicites
172
    ! ============================================================
173
    ! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
174
    ! Tetens : pression partielle de vap d'eau e_sat(T)
175
    ! =================================================
176
    ! ++ e_sat(T) = r2*exp( r3*(T-Tf)/(T-r4) ) id a r2*FOEWE
177
    ! ++ avec :
178
    ! ++ Tf = 273.16 K  (Temp de fusion de la glace)
179
    ! ++ r2 = 611.14 Pa
180
    ! ++ r3 = 17.269 (liquide) 21.875 (solide) adim
181
    ! ++ r4 = 35.86             7.66           Kelvin
182
    ! ++  q_sat = eps*e_sat/(p-(1-eps)*e_sat)
183
    ! ++ deriv� :
184
    ! ++ =========
185
    ! ++                   r3*(Tf-r4)*q_sat(T,p)
186
    ! ++ d_qsat_dT = --------------------------------
187
    ! ++             (T-r4)^2*( 1-(1-eps)*e_sat(T)/p )
188
    ! ++ pour zcvm5=Lv, c'est FOEDE
189
    ! ++ Rq :(1.-REPS)*esarg/Parg id a RETV*Qsat
190
    ! ------------------------------------------------------------------
191
192
    ! Initialisation
193
1152
    rlvcp = rlvtt/rcpd
194
    reps = rd/rv
195
196
197
    ! DO i = 1, klon
198
    ! pcfh(i,1) = cd_h(i)
199
    ! pcfm(i,1) = cd_m(i)
200
    ! ENDDO
201
    ! DO k = 2, klev
202
    ! DO i = 1, klon
203
    ! pcfh(i,k) = zkmin
204
    ! pcfm(i,k) = zkmin
205
    ! cgs(i,k) = 0.0
206
    ! cgh(i,k) = 0.0
207
    ! cgq(i,k) = 0.0
208
    ! ENDDO
209
    ! ENDDO
210
211
    ! Calculer les hauteurs de chaque couche
212
    ! (geopotentielle Int_dp/ro = Int_[Rd.T.dp/p] z = geop/g)
213
    ! pourquoi ne pas utiliser Phi/RG ?
214
473954
    DO i = 1, knon
215
       z(i, 1) = rd*t(i, 1)/(0.5*(paprs(i,1)+pplay(i,1)))&
216
472802
            *(paprs(i,1)-pplay(i,1))/rg
217
473954
       s(i, 1) = (pplay(i,1)/paprs(i,1))**rkappa
218
    END DO
219
    ! s(k) = [pplay(k)/ps]^kappa
220
    ! + + + + + + + + + pplay  <-> s(k)   t  dp=pplay(k-1)-pplay(k)
221
222
    ! -----------------  paprs <-> sig(k)
223
224
    ! + + + + + + + + + pplay  <-> s(k-1)
225
226
227
    ! + + + + + + + + + pplay  <-> s(1)   t  dp=paprs-pplay   z(1)
228
229
    ! -----------------  paprs <-> sig(1)
230
231
44928
    DO k = 2, klev
232
18011404
       DO i = 1, knon
233
          z(i, k) = z(i, k-1) + rd*0.5*(t(i,k-1)+t(i,k))/paprs(i, k)&
234
17966476
               *(pplay(i,k-1)-pplay(i,k))/rg
235
18010252
          s(i, k) = (pplay(i,k)/paprs(i,1))**rkappa
236
       END DO
237
    END DO
238
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
239
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
240
    ! +++  Determination des grandeurs de surface  +++++++++++++++++++++
241
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
242
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
243
473954
    DO i = 1, knon
244
       ! AM         IF (thermcep) THEN
245
       ! AM           zdelta=MAX(0.,SIGN(1.,RTT-tsol(i)))
246
       ! zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
247
       ! zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q(i,1))
248
       ! AM           zxqs= r2es * FOEEW(tsol(i),zdelta)/paprs(i,1)
249
       ! AM           zxqs=MIN(0.5,zxqs)
250
       ! AM           zcor=1./(1.-retv*zxqs)
251
       ! AM           zxqs=zxqs*zcor
252
       ! AM         ELSE
253
       ! AM           IF (tsol(i).LT.t_coup) THEN
254
       ! AM              zxqs = qsats(tsol(i)) / paprs(i,1)
255
       ! AM           ELSE
256
       ! AM              zxqs = qsatl(tsol(i)) / paprs(i,1)
257
       ! AM           ENDIF
258
       ! AM         ENDIF
259
       ! niveau de reference bulk; mais ici, c,a pourrait etre le niveau de ref
260
       ! du thermique
261
       ! AM        zx_alf1 = 1.0
262
       ! AM        zx_alf2 = 1.0 - zx_alf1
263
       ! AM        zxt = (t(i,1)+z(i,1)*RG/RCPD/(1.+RVTMP2*q(i,1)))
264
       ! AM     .        *(1.+RETV*q(i,1))*zx_alf1
265
       ! AM     .      + (t(i,2)+z(i,2)*RG/RCPD/(1.+RVTMP2*q(i,2)))
266
       ! AM     .        *(1.+RETV*q(i,2))*zx_alf2
267
       ! AM        zxu = u(i,1)*zx_alf1+u(i,2)*zx_alf2
268
       ! AM        zxv = v(i,1)*zx_alf1+v(i,2)*zx_alf2
269
       ! AM        zxq = q(i,1)*zx_alf1+q(i,2)*zx_alf2
270
       ! AM
271
       ! AMAM           zxu = u10m(i)
272
       ! AMAM           zxv = v10m(i)
273
       ! AMAM           zxmod = 1.0+SQRT(zxu**2+zxv**2)
274
       ! AM Niveau de ref choisi a 2m
275
472802
       zxt = t2m(i)
276
277
       ! ***************************************************
278
       ! attention, il doit s'agir de <w'theta'>
279
       ! ;Calcul de tcls virtuel et de w'theta'virtuel
280
       ! ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
281
       ! tcls=tcls*(1+.608*qcls)
282
283
       ! ;Pour avoir w'theta',
284
       ! ; il faut diviser par ro.Cp
285
       ! Cp=Cpd*(1+0.84*qcls)
286
       ! fcs=fcs/(ro_surf*Cp)
287
       ! ;On transforme w'theta' en w'thetav'
288
       ! Lv=(2.501-0.00237*(tcls-273.15))*1.E6
289
       ! xle=xle/(ro_surf*Lv)
290
       ! fcsv=fcs+.608*xle*tcls
291
       ! ***************************************************
292
       ! AM        khfs(i) = (tsol(i)*(1.+RETV*q(i,1))-zxt) *zxmod*cd_h(i)
293
       ! AM        kqfs(i) = (zxqs-zxq) *zxmod*cd_h(i) * beta(i)
294
       ! AM
295
       ! dif khfs est deja w't'_v / heatv(i) = khfs(i) + RETV*zxt*kqfs(i)
296
       ! AM calcule de Ro = paprs(i,1)/Rd zxt
297
       ! AM convention >0 vers le bas ds lmdz
298
472802
       khfs(i) = -flux_t(i, 1)*zxt*rd/(rcpd*paprs(i,1))
299
472802
       kqfs(i) = -flux_q(i, 1)*zxt*rd/(paprs(i,1))
300
       ! AM   verifier que khfs et kqfs sont bien de la forme w'l'
301
472802
       heatv(i) = khfs(i) + 0.608*zxt*kqfs(i)
302
       ! a comparer aussi aux sorties de clqh : flux_T/RoCp et flux_q/RoLv
303
       ! AM        heatv(i) = khfs(i)
304
       ! AM ustar est en entree
305
       ! AM        taux = zxu *zxmod*cd_m(i)
306
       ! AM        tauy = zxv *zxmod*cd_m(i)
307
       ! AM        ustar(i) = SQRT(taux**2+tauy**2)
308
       ! AM        ustar(i) = MAX(SQRT(ustar(i)),0.01)
309
       ! Theta et qT du thermique sans exces (interpolin vers surf)
310
       ! chgt de niveau du thermique (jeudi 30/12/1999)
311
       ! (interpolation lineaire avant integration phi_h)
312
       ! AM        qT_th(i) = zxqs*beta(i) + 4./z(i,1)*(q(i,1)-zxqs*beta(i))
313
       ! AM        qT_th(i) = max(qT_th(i),q(i,1))
314
472802
       qt_th(i) = q2m(i)
315
       ! n The_th restera la Theta du thermique sans exces jusqu'a 2eme calcul
316
       ! n reste a regler convention P) pour Theta
317
       ! The_th(i) = tsol(i) + 4./z(i,1)*(t(i,1)-tsol(i))
318
       ! -                      + RLvCp*qT_th(i)
319
       ! AM        Th_th(i) = tsol(i) + 4./z(i,1)*(t(i,1)-tsol(i))
320
473954
       th_th(i) = t2m(i)
321
    END DO
322
323
473954
    DO i = 1, knon
324
472802
       rhino(i, 1) = 0.0 ! Global Richardson
325
472802
       check(i) = .TRUE.
326
472802
       pblh(i) = z(i, 1) ! on initialise pblh a l'altitude du 1er niveau
327
472802
       plcl(i) = 6000.
328
       ! Lambda = -u*^3 / (alpha.g.kvon.<w'Theta'v>
329
472802
       unsobklen(i) = -rg*vk*heatv(i)/(t(i,1)*max(ustar(i),usmin)**3)
330
472802
       trmb1(i) = 0.
331
472802
       trmb2(i) = 0.
332
473954
       trmb3(i) = 0.
333
    END DO
334
335
336
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
337
    ! PBL height calculation:
338
    ! Search for level of pbl. Scan upward until the Richardson number between
339
    ! the first level and the current level exceeds the "critical" value.
340
    ! (bonne idee Nu de separer le Ric et l'exces de temp du thermique)
341
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
342
    fac = 100.0
343
44928
    DO k = 2, isommet
344
18011404
       DO i = 1, knon
345
18010252
          IF (check(i)) THEN
346
             ! pourquoi / niveau 1 (au lieu du sol) et le terme en u*^2 ?
347
             ! test     zdu2 =
348
             ! (u(i,k)-u(i,1))**2+(v(i,k)-v(i,1))**2+fac*ustar(i)**2
349
1880357
             zdu2 = u(i, k)**2 + v(i, k)**2
350
1880357
             zdu2 = max(zdu2, 1.0E-20)
351
             ! Theta_v environnement
352
1880357
             zthvd = t(i, k)/s(i, k)*(1.+retv*q(i,k))
353
354
             ! therm Theta_v sans exces (avec hypothese fausse de H&B, sinon,
355
             ! passer par Theta_e et virpot)
356
             ! zthvu=t(i,1)/s(i,1)*(1.+RETV*q(i,1))
357
             ! AM         zthvu = Th_th(i)*(1.+RETV*q(i,1))
358
1880357
             zthvu = th_th(i)*(1.+retv*qt_th(i))
359
             ! Le Ri par Theta_v
360
             ! AM         rhino(i,k) = (z(i,k)-z(i,1))*RG*(zthvd-zthvu)
361
             ! AM     .               /(zdu2*0.5*(zthvd+zthvu))
362
             ! AM On a nveau de ref a 2m ???
363
             rhino(i, k) = (z(i,k)-zref)*rg*(zthvd-zthvu)/(zdu2*0.5&
364
1880357
                  *(zthvd+zthvu))
365
366
1880357
             IF (rhino(i,k)>=ricr) THEN
367
                pblh(i) = z(i, k-1) + (z(i,k-1)-z(i,k))*(ricr-rhino(i,k-1))&
368
472802
                     /(rhino(i,k-1)-rhino(i,k))
369
                ! test04
370
472802
                pblh(i) = pblh(i) + 100.
371
                pblt(i) = t(i, k-1) + (t(i,k)-t(i,k-1))*(pblh(i)-z(i,k-1))&
372
472802
                     /(z(i,k)- z(i,k-1))
373
472802
                check(i) = .FALSE.
374
             END IF
375
          END IF
376
       END DO
377
    END DO
378
379
380
    ! Set pbl height to maximum value where computation exceeds number of
381
    ! layers allowed
382
383
473954
    DO i = 1, knon
384
473954
       IF (check(i)) pblh(i) = z(i, isommet)
385
    END DO
386
387
    ! Improve estimate of pbl height for the unstable points.
388
    ! Find unstable points (sensible heat flux is upward):
389
390
473954
    DO i = 1, knon
391
473954
       IF (heatv(i)>0.) THEN
392
326839
          unstbl(i) = .TRUE.
393
326839
          check(i) = .TRUE.
394
       ELSE
395
145963
          unstbl(i) = .FALSE.
396
145963
          check(i) = .FALSE.
397
       END IF
398
    END DO
399
400
    ! For the unstable case, compute velocity scale and the
401
    ! convective temperature excess:
402
403
473954
    DO i = 1, knon
404
473954
       IF (check(i)) THEN
405
326839
          phiminv(i) = (1.-binm*pblh(i)*unsobklen(i))**onet
406
          ! ***************************************************
407
          ! Wm ? et W* ? c'est la formule pour z/h < .1
408
          ! ;Calcul de w* ;;
409
          ! ;;;;;;;;;;;;;;;;
410
          ! w_star=((g/tcls)*fcsv*z(ind))^(1/3.) [ou prendre la premiere approx
411
          ! de h)
412
          ! ;; CALCUL DE wm ;;
413
          ! ;;;;;;;;;;;;;;;;;;
414
          ! ; Ici on considerera que l'on est dans la couche de surf jusqu'a
415
          ! 100 m
416
          ! ; On prend svt couche de surface=0.1*h mais on ne connait pas h
417
          ! ;;;;;;;;;;;Dans la couche de surface
418
          ! if (z(ind) le 20) then begin
419
          ! Phim=(1.-15.*(z(ind)/L))^(-1/3.)
420
          ! wm=u_star/Phim
421
          ! ;;;;;;;;;;;En dehors de la couche de surface
422
          ! endif else if (z(ind) gt 20) then begin
423
          ! wm=(u_star^3+c1*w_star^3)^(1/3.)
424
          ! endif
425
          ! ***************************************************
426
326839
          wm(i) = ustar(i)*phiminv(i)
427
          ! ===================================================================
428
          ! valeurs de Dominique Lambert de la campagne SEMAPHORE :
429
          ! <T'^2> = 100.T*^2; <q'^2> = 20.q*^2 a 10m
430
          ! <Tv'^2> = (1+1.2q).100.T* + 1.2Tv.sqrt(20*100).T*.q* +
431
          ! (.608*Tv)^2*20.q*^2;
432
          ! et dTetavS = sqrt(<Tv'^2>) ainsi calculee.
433
          ! avec : T*=<w'T'>_s/w* et q*=<w'q'>/w*
434
          ! !!! on peut donc utiliser w* pour les fluctuations <-> Lambert
435
          ! (leur corellation pourrait dependre de beta par ex)
436
          ! if fcsv(i,j) gt 0 then begin
437
          ! dTetavs=b1*(1.+2.*.608*q_10(i,j))*(fcs(i,j)/wm(i,j))^2+$
438
          ! (.608*Thetav_10(i,j))^2*b2*(xle(i,j)/wm(i,j))^2+$
439
          ! 2.*.608*thetav_10(i,j)*sqrt(b1*b2)*(xle(i,j)/wm(i,j))*(fcs(i,j)
440
          ! /wm(i,j))
441
          ! dqs=b2*(xle(i,j)/wm(i,j))^2
442
          ! theta_s(i,j)=thetav_10(i,j)+sqrt(dTetavs)
443
          ! q_s(i,j)=q_10(i,j)+sqrt(dqs)
444
          ! endif else begin
445
          ! Theta_s(i,j)=thetav_10(i,j)
446
          ! q_s(i,j)=q_10(i,j)
447
          ! endelse
448
          ! ===================================================================
449
450
          ! HBTM        therm(i) = heatv(i)*fak/wm(i)
451
          ! forme Mathieu :
452
326839
          q_star = kqfs(i)/wm(i)
453
326839
          t_star = khfs(i)/wm(i)
454
          ! IM 091204 BEG
455
          IF (1==0) THEN
456
             IF (t_star<0. .OR. q_star<0.) THEN
457
                PRINT *, 'i t_star q_star khfs kqfs wm', i, t_star, q_star, &
458
                     khfs(i), kqfs(i), wm(i)
459
             END IF
460
          END IF
461
          ! IM 091204 END
462
          ! AM Nveau cde ref 2m =>
463
          ! AM        therm(i) = sqrt( b1*(1.+2.*RETV*q(i,1))*t_star**2
464
          ! AM     +             + (RETV*T(i,1))**2*b2*q_star**2
465
          ! AM     +             + 2.*RETV*T(i,1)*b212*q_star*t_star
466
          ! AM     +                 )
467
          ! IM 091204 BEG
468
326839
          a1 = b1*(1.+2.*retv*qt_th(i))*t_star**2
469
326839
          a2 = (retv*th_th(i))**2*b2*q_star*q_star
470
326839
          a3 = 2.*retv*th_th(i)*b212*q_star*t_star
471
326839
          aa = a1 + a2 + a3
472
          IF (1==0) THEN
473
             IF (aa<0.) THEN
474
                PRINT *, 'i a1 a2 a3 aa', i, a1, a2, a3, aa
475
                PRINT *, 'i qT_th Th_th t_star q_star RETV b1 b2 b212', i, &
476
                     qt_th(i), th_th(i), t_star, q_star, retv, b1, b2, b212
477
             END IF
478
          END IF
479
          ! IM 091204 END
480
          therm(i) = sqrt(b1*(1.+2.*retv*qt_th(i))*t_star**2+(retv*th_th( &
481
               i))**2*b2*q_star*q_star &  ! IM 101204  +             +
482
                                ! 2.*RETV*Th_th(i)*b212*q_star*t_star
483
326839
               +max(0.,2.*retv*th_th(i)*b212*q_star*t_star))
484
485
          ! Theta et qT du thermique (forme H&B) avec exces
486
          ! (attention, on ajoute therm(i) qui est virtuelle ...)
487
          ! pourquoi pas sqrt(b1)*t_star ?
488
          ! dqs = b2sr*kqfs(i)/wm(i)
489
326839
          qt_th(i) = qt_th(i) + b2sr*q_star
490
          ! new on differre le calcul de Theta_e
491
          ! The_th(i) = The_th(i) + therm(i) + RLvCp*qT_th(i)
492
          ! ou:    The_th(i) = The_th(i) + sqrt(b1)*khfs(i)/wm(i) +
493
          ! RLvCp*qT_th(i)
494
326839
          rhino(i, 1) = 0.0
495
       END IF
496
    END DO
497
498
    ! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
499
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
500
    ! ++ Improve pblh estimate for unstable conditions using the +++++++
501
    ! ++          convective temperature excess :                +++++++
502
    ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
503
    ! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
504
505
44928
    DO k = 2, isommet
506
18011404
       DO i = 1, knon
507
18010252
          IF (check(i)) THEN
508
             ! test     zdu2 =
509
             ! (u(i,k)-u(i,1))**2+(v(i,k)-v(i,1))**2+fac*ustar(i)**2
510
1606144
             zdu2 = u(i, k)**2 + v(i, k)**2
511
1606144
             zdu2 = max(zdu2, 1.0E-20)
512
             ! Theta_v environnement
513
1606144
             zthvd = t(i, k)/s(i, k)*(1.+retv*q(i,k))
514
515
             ! et therm Theta_v (avec hypothese de constance de H&B,
516
             ! zthvu=(t(i,1)+therm(i))/s(i,1)*(1.+RETV*q(i,1))
517
1606144
             zthvu = th_th(i)*(1.+retv*qt_th(i)) + therm(i)
518
519
520
             ! Le Ri par Theta_v
521
             ! AM Niveau de ref 2m
522
             ! AM         rhino(i,k) = (z(i,k)-z(i,1))*RG*(zthvd-zthvu)
523
             ! AM     .               /(zdu2*0.5*(zthvd+zthvu))
524
             rhino(i, k) = (z(i,k)-zref)*rg*(zthvd-zthvu)/(zdu2*0.5&
525
1606144
                  *(zthvd+zthvu))
526
527
528
1606144
             IF (rhino(i,k)>=ricr) THEN
529
                pblh(i) = z(i, k-1) + (z(i,k-1)-z(i,k))*(ricr-rhino(i,k-1))&
530
326839
                     /(rhino(i,k-1)-rhino(i,k))
531
                ! test04
532
326839
                pblh(i) = pblh(i) + 100.
533
                pblt(i) = t(i, k-1) + (t(i,k)-t(i,k-1))*(pblh(i)-z(i,k-1))&
534
326839
                     /(z(i,k)- z(i,k-1))
535
326839
                check(i) = .FALSE.
536
                ! IM 170305 BEG
537
                IF (1==0) THEN
538
                   ! debug print -120;34       -34-        58 et    0;26 wamp
539
                   IF (i==950 .OR. i==192 .OR. i==624 .OR. i==118) THEN
540
                      PRINT *, ' i,Th_th,Therm,qT :', i, th_th(i), therm(i), &
541
                           qt_th(i)
542
                      q_star = kqfs(i)/wm(i)
543
                      t_star = khfs(i)/wm(i)
544
                      PRINT *, 'q* t*, b1,b2,b212 ', q_star, t_star, &
545
                           b1*(1.+2.*retv*qt_th(i))*t_star**2, &
546
                           (retv*th_th(i))**2*b2*q_star**2, 2.*retv*th_th(i)&
547
                           *b212*q_star *t_star
548
                      PRINT *, 'zdu2 ,100.*ustar(i)**2', zdu2, fac*ustar(i)**2
549
                   END IF
550
                END IF !(1.EQ.0) THEN
551
                ! IM 170305 END
552
                ! q_star = kqfs(i)/wm(i)
553
                ! t_star = khfs(i)/wm(i)
554
                ! trmb1(i) = b1*(1.+2.*RETV*q(i,1))*t_star**2
555
                ! trmb2(i) = (RETV*T(i,1))**2*b2*q_star**2
556
                ! Omega now   trmb3(i) = 2.*RETV*T(i,1)*b212*q_star*t_star
557
             END IF
558
          END IF
559
       END DO
560
    END DO
561
562
    ! Set pbl height to maximum value where computation exceeds number of
563
    ! layers allowed
564
565
473954
    DO i = 1, knon
566
473954
       IF (check(i)) pblh(i) = z(i, isommet)
567
    END DO
568
569
    ! PBL height must be greater than some minimum mechanical mixing depth
570
    ! Several investigators have proposed minimum mechanical mixing depth
571
    ! relationships as a function of the local friction velocity, u*.  We
572
    ! make use of a linear relationship of the form h = c u* where c=700.
573
    ! The scaling arguments that give rise to this relationship most often
574
    ! represent the coefficient c as some constant over the local coriolis
575
    ! parameter.  Here we make use of the experimental results of Koracin
576
    ! and Berkowicz (1988) [BLM, Vol 43] for wich they recommend 0.07/f
577
    ! where f was evaluated at 39.5 N and 52 N.  Thus we use a typical mid
578
    ! latitude value for f so that c = 0.07/f = 700.
579
580
473954
    DO i = 1, knon
581
472802
       pblmin = 700.0*ustar(i)
582
472802
       pblh(i) = max(pblh(i), pblmin)
583
       ! par exemple :
584
473954
       pblt(i) = t(i, 2) + (t(i,3)-t(i,2))*(pblh(i)-z(i,2))/(z(i,3)-z(i,2))
585
    END DO
586
587
    ! ********************************************************************
588
    ! pblh is now available; do preparation for diffusivity calculation :
589
    ! ********************************************************************
590
473954
    DO i = 1, knon
591
472802
       check(i) = .TRUE.
592
472802
       zsat(i) = .FALSE.
593
       ! omegafl utilise pour prolongement CAPE
594
472802
       omegafl(i) = .FALSE.
595
472802
       cape(i) = 0.
596
472802
       kape(i) = 0.
597
472802
       eauliq(i) = 0.
598
472802
       ctei(i) = 0.
599
472802
       pblk(i) = 0.0
600
472802
       fak1(i) = ustar(i)*pblh(i)*vk
601
602
       ! Do additional preparation for unstable cases only, set temperature
603
       ! and moisture perturbations depending on stability.
604
       ! *** Rq: les formule sont prises dans leur forme CS ***
605
472802
       IF (unstbl(i)) THEN
606
          ! AM Niveau de ref du thermique
607
          ! AM          zxt=(t(i,1)-z(i,1)*0.5*RG/RCPD/(1.+RVTMP2*q(i,1)))
608
          ! AM     .         *(1.+RETV*q(i,1))
609
          zxt = (th_th(i)-zref*0.5*rg/rcpd/(1.+rvtmp2*qt_th(i)))* &
610
326839
               (1.+retv*qt_th(i))
611
326839
          phiminv(i) = (1.-binm*pblh(i)*unsobklen(i))**onet
612
326839
          phihinv(i) = sqrt(1.-binh*pblh(i)*unsobklen(i))
613
326839
          wm(i) = ustar(i)*phiminv(i)
614
326839
          fak2(i) = wm(i)*pblh(i)*vk
615
326839
          wstar(i) = (heatv(i)*rg*pblh(i)/zxt)**onet
616
326839
          fak3(i) = fakn*wstar(i)/wm(i)
617
       ELSE
618
145963
          wstar(i) = 0.
619
       END IF
620
       ! Computes Theta_e for thermal (all cases : to be modified)
621
       ! attention ajout therm(i) = virtuelle
622
473954
       the_th(i) = th_th(i) + therm(i) + rlvcp*qt_th(i)
623
       ! ou:    The_th(i) = Th_th(i) + sqrt(b1)*khfs(i)/wm(i) + RLvCp*qT_th(i)
624
    END DO
625
626
    ! Main level loop to compute the diffusivities and
627
    ! counter-gradient terms:
628
629
44928
    DO k = 2, isommet
630
631
       ! Find levels within boundary layer:
632
633
18010252
       DO i = 1, knon
634
17966476
          unslev(i) = .FALSE.
635
17966476
          stblev(i) = .FALSE.
636
17966476
          zm(i) = z(i, k-1)
637
17966476
          zp(i) = z(i, k)
638
          IF (zkmin==0.0 .AND. zp(i)>pblh(i)) zp(i) = pblh(i)
639
18010252
          IF (zm(i)<pblh(i)) THEN
640
2193339
             zmzp = 0.5*(zm(i)+zp(i))
641
             ! debug
642
             ! if (i.EQ.1864) then
643
             ! print*,'i,pblh(1864),obklen(1864)',i,pblh(i),obklen(i)
644
             ! endif
645
646
2193339
             zh(i) = zmzp/pblh(i)
647
2193339
             zl(i) = zmzp*unsobklen(i)
648
2193339
             zzh(i) = 0.
649
2193339
             IF (zh(i)<=1.0) zzh(i) = (1.-zh(i))**2
650
651
             ! stblev for points zm < plbh and stable and neutral
652
             ! unslev for points zm < plbh and unstable
653
654
2193339
             IF (unstbl(i)) THEN
655
1734894
                unslev(i) = .TRUE.
656
             ELSE
657
458445
                stblev(i) = .TRUE.
658
             END IF
659
          END IF
660
       END DO
661
       ! print*,'fin calcul niveaux'
662
663
       ! Stable and neutral points; set diffusivities; counter-gradient
664
       ! terms zero for stable case:
665
666
18010252
       DO i = 1, knon
667
18010252
          IF (stblev(i)) THEN
668
458445
             IF (zl(i)<=1.) THEN
669
151881
                pblk(i) = fak1(i)*zh(i)*zzh(i)/(1.+betas*zl(i))
670
             ELSE
671
306564
                pblk(i) = fak1(i)*zh(i)*zzh(i)/(betas+zl(i))
672
             END IF
673
             ! pcfm(i,k) = pblk(i)
674
             ! pcfh(i,k) = pcfm(i,k)
675
          END IF
676
       END DO
677
678
       ! unssrf, unstable within surface layer of pbl
679
       ! unsout, unstable within outer   layer of pbl
680
681
18010252
       DO i = 1, knon
682
17966476
          unssrf(i) = .FALSE.
683
17966476
          unsout(i) = .FALSE.
684
18010252
          IF (unslev(i)) THEN
685
1734894
             IF (zh(i)<sffrac) THEN
686
252093
                unssrf(i) = .TRUE.
687
             ELSE
688
1482801
                unsout(i) = .TRUE.
689
             END IF
690
          END IF
691
       END DO
692
693
       ! Unstable for surface layer; counter-gradient terms zero
694
695
18010252
       DO i = 1, knon
696
18010252
          IF (unssrf(i)) THEN
697
252093
             term = (1.-betam*zl(i))**onet
698
252093
             pblk(i) = fak1(i)*zh(i)*zzh(i)*term
699
252093
             pr(i) = term/sqrt(1.-betah*zl(i))
700
          END IF
701
       END DO
702
       ! print*,'fin counter-gradient terms zero'
703
704
       ! Unstable for outer layer; counter-gradient terms non-zero:
705
706
18010252
       DO i = 1, knon
707
18010252
          IF (unsout(i)) THEN
708
1482801
             pblk(i) = fak2(i)*zh(i)*zzh(i)
709
             ! cgs(i,k) = fak3(i)/(pblh(i)*wm(i))
710
             ! cgh(i,k) = khfs(i)*cgs(i,k)
711
1482801
             pr(i) = phiminv(i)/phihinv(i) + ccon*fak3(i)/fak
712
             ! cgq(i,k) = kqfs(i)*cgs(i,k)
713
          END IF
714
       END DO
715
       ! print*,'fin counter-gradient terms non zero'
716
717
       ! For all unstable layers, compute diffusivities and ctrgrad ter m
718
719
       ! DO i = 1, knon
720
       ! IF (unslev(i)) THEN
721
       ! pcfm(i,k) = pblk(i)
722
       ! pcfh(i,k) = pblk(i)/pr(i)
723
       ! etc cf original
724
       ! ENDIF
725
       ! ENDDO
726
727
       ! For all layers, compute integral info and CTEI
728
729
18011404
       DO i = 1, knon
730

18010252
          IF (check(i) .OR. omegafl(i)) THEN
731
17966476
             IF (.NOT. zsat(i)) THEN
732
                ! Th2 = The_th(i) - RLvCp*qT_th(i)
733
1292083
                th2 = th_th(i)
734
1292083
                t2 = th2*s(i, k)
735
                ! thermodyn functions
736
1292083
                zdelta = max(0., sign(1.,rtt-t2))
737
1292083
                qqsat = r2es*foeew(t2, zdelta)/pplay(i, k)
738
1292083
                qqsat = min(0.5, qqsat)
739
1292083
                zcor = 1./(1.-retv*qqsat)
740
1292083
                qqsat = qqsat*zcor
741
742
1292083
                IF (qqsat<qt_th(i)) THEN
743
                   ! on calcule lcl
744
472802
                   IF (k==2) THEN
745
231821
                      plcl(i) = z(i, k)
746
                   ELSE
747
                      plcl(i) = z(i, k-1) + (z(i,k-1)-z(i,k))*(qt_th(i)&
748
240981
                           -qsatbef(i))/(qsatbef(i)-qqsat)
749
                   END IF
750
472802
                   zsat(i) = .TRUE.
751
472802
                   tbef(i) = t2
752
                END IF
753
754
1292083
                qsatbef(i) = qqsat ! bug dans la version orig ???
755
             END IF
756
             ! amn ???? cette ligne a deja ete faite normalement ?
757
          END IF
758
          ! print*,'hbtm2 i,k=',i,k
759
       END DO
760
    END DO ! end of level loop
761
    ! IM 170305 BEG
762
    IF (1==0) THEN
763
       PRINT *, 'hbtm2  ok'
764
    END IF !(1.EQ.0) THEN
765
    ! IM 170305 END
766
767
1152
  END SUBROUTINE hbtm
768
769
end module hbtm_mod