source: LMDZ6/branches/PBLSURF_GPUPORT/libf/phylmd/hbtm_mod.f90 @ 5932

Last change on this file since 5932 was 5887, checked in by yann meurdesoif, 7 weeks ago

GPU port of HBTM

YM

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