/[lmdze]/trunk/Sources/phylmd/coefkz.f
ViewVC logotype

Contents of /trunk/Sources/phylmd/coefkz.f

Parent Directory Parent Directory | Revision Log Revision Log


Revision 250 - (show annotations)
Fri Jan 5 18:18:53 2018 UTC (6 years, 4 months ago) by guez
File size: 7293 byte(s)
Extract part of clmain into a new procedure coef_diff_turb (following LMDZ).

1 module coefkz_m
2
3 IMPLICIT none
4
5 contains
6
7 SUBROUTINE coefkz(nsrf, paprs, pplay, ts, u, v, t, q, zgeop, coefm, coefh)
8
9 ! Authors: F. Hourdin, M. Forichon, Z. X. Li (LMD/CNRS)
10 ! Date: September 22nd, 1993
11
12 ! Objet : calculer les coefficients d'échange turbulent dans
13 ! l'atmosphère.
14
15 USE clesphys, ONLY: ksta, ksta_ter
16 USE conf_phys_m, ONLY: iflag_pbl
17 USE dimphy, ONLY: klev
18 USE fcttre, ONLY: foede, foeew
19 USE indicesol, ONLY: is_oce
20 USE suphec_m, ONLY: rcpd, rd, retv, rg, rkappa, rlstt, rlvtt, rtt
21 USE yoethf_m, ONLY: r2es, r5ies, r5les, rvtmp2
22
23 integer, intent(in):: nsrf ! indicateur de la nature du sol
24
25 REAL, intent(in):: paprs(:, :) ! (knon, klev + 1)
26 ! pression a chaque intercouche (en Pa)
27
28 real, intent(in):: pplay(:, :) ! (knon, klev)
29 ! pression au milieu de chaque couche (en Pa)
30
31 REAL, intent(in):: ts(:) ! (knon) temperature du sol (en Kelvin)
32 REAL, intent(in):: u(:, :), v(:, :) ! (knon, klev) wind
33 REAL, intent(in):: t(:, :) ! (knon, klev) temperature (K)
34 real, intent(in):: q(:, :) ! (knon, klev) vapeur d'eau (kg/kg)
35 REAL, intent(in):: zgeop(:, :) ! (knon, klev)
36 REAL, intent(out):: coefm(:, 2:) ! (knon, 2:klev) coefficient, vitesse
37
38 real, intent(out):: coefh(:, 2:) ! (knon, 2:klev)
39 ! coefficient, chaleur et humidité
40
41 ! Local:
42
43 INTEGER knon ! nombre de points a traiter
44
45 INTEGER itop(size(ts)) ! (knon)
46 ! numero de couche du sommet de la couche limite
47
48 ! Quelques constantes et options:
49
50 REAL, PARAMETER:: cepdu2 =0.1**2
51 REAL, PARAMETER:: CKAP = 0.4
52 REAL, PARAMETER:: cb = 5.
53 REAL, PARAMETER:: cc = 5.
54 REAL, PARAMETER:: cd = 5.
55 REAL, PARAMETER:: clam = 160.
56 REAL, PARAMETER:: ratqs = 0.05 ! largeur de distribution de vapeur d'eau
57
58 LOGICAL, PARAMETER:: richum = .TRUE.
59 ! utilise le nombre de Richardson humide
60
61 REAL, PARAMETER:: ric = 0.4 ! nombre de Richardson critique
62 REAL, PARAMETER:: prandtl = 0.4
63
64 REAL kstable ! diffusion minimale (situation stable)
65 REAL, PARAMETER:: mixlen = 35. ! constante contrôlant longueur de mélange
66 INTEGER, PARAMETER:: isommet = klev ! sommet de la couche limite
67
68 LOGICAL, PARAMETER:: tvirtu = .TRUE.
69 ! calculer Ri d'une maniere plus performante
70
71 LOGICAL, PARAMETER:: opt_ec = .FALSE.
72 ! formule du Centre Europeen dans l'atmosphere
73
74 INTEGER i, k
75 REAL zmgeom(size(ts))
76 REAL ri(size(ts))
77 REAL l2(size(ts))
78 REAL zdphi, zdu2, ztvd, ztvu, cdn
79 REAL scf
80 REAL zt, zq, zcvm5, zcor, zqs, zfr, zdqs
81 logical zdelta
82 REAL z2geomf, zalh2, alm2, zscfh, scfm
83 REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre
84
85 !--------------------------------------------------------------------
86
87 knon = size(ts)
88
89 ! Prescrire la valeur de contre-gradient
90 if (iflag_pbl.eq.1) then
91 DO k = 3, klev
92 gamt(k) = - 1E-3
93 ENDDO
94 gamt(2) = - 2.5E-3
95 else
96 DO k = 2, klev
97 gamt(k) = 0.0
98 ENDDO
99 ENDIF
100
101 IF (nsrf .NE. is_oce ) THEN
102 kstable = ksta_ter
103 ELSE
104 kstable = ksta
105 ENDIF
106
107 ! Calculer les coefficients turbulents dans l'atmosphere
108
109 itop = isommet
110
111 loop_vertical: DO k = 2, isommet
112 loop_horiz: DO i = 1, knon
113 zdu2 = MAX(cepdu2, (u(i, k) - u(i, k - 1))**2 &
114 + (v(i, k) - v(i, k - 1))**2)
115 zmgeom(i) = zgeop(i, k) - zgeop(i, k - 1)
116 zdphi = zmgeom(i) / 2.0
117 zt = (t(i, k) + t(i, k - 1)) * 0.5
118 zq = (q(i, k) + q(i, k - 1)) * 0.5
119
120 ! calculer Qs et dQs/dT:
121
122 zdelta = RTT >=zt
123 zcvm5 = merge(R5IES * RLSTT, R5LES * RLVTT, zdelta) / RCPD &
124 / (1. + RVTMP2 * zq)
125 zqs = R2ES * FOEEW(zt, zdelta) / pplay(i, k)
126 zqs = MIN(0.5, zqs)
127 zcor = 1./(1. - RETV * zqs)
128 zqs = zqs * zcor
129 zdqs = FOEDE(zt, zdelta, zcvm5, zqs, zcor)
130
131 ! calculer la fraction nuageuse (processus humide):
132
133 zfr = (zq + ratqs * zq - zqs) / (2.0 * ratqs * zq)
134 zfr = MAX(0.0, MIN(1.0, zfr))
135 IF (.NOT.richum) zfr = 0.0
136
137 ! calculer le nombre de Richardson:
138
139 IF (tvirtu) THEN
140 ztvd = (t(i, k) &
141 + zdphi/RCPD/(1. + RVTMP2 * zq) &
142 * ((1. - zfr) + zfr * (1. + RLVTT * zqs/RD/zt)/(1. + zdqs) ) &
143 ) * (1. + RETV * q(i, k))
144 ztvu = (t(i, k - 1) &
145 - zdphi/RCPD/(1. + RVTMP2 * zq) &
146 * ((1. - zfr) + zfr * (1. + RLVTT * zqs/RD/zt)/(1. + zdqs) ) &
147 ) * (1. + RETV * q(i, k - 1))
148 ri(i) = zmgeom(i) * (ztvd - ztvu)/(zdu2 * 0.5 * (ztvd + ztvu))
149 ri(i) = ri(i) &
150 + zmgeom(i) * zmgeom(i)/RG * gamt(k) &
151 * (paprs(i, k)/101325.0)**RKAPPA &
152 /(zdu2 * 0.5 * (ztvd + ztvu))
153 ELSE
154 ! calcul de Ridchardson compatible LMD5
155 ri(i) = (RCPD * (t(i, k) - t(i, k - 1)) &
156 - RD * 0.5 * (t(i, k) + t(i, k - 1))/paprs(i, k) &
157 * (pplay(i, k) - pplay(i, k - 1)) &
158 ) * zmgeom(i)/(zdu2 * 0.5 * RCPD * (t(i, k - 1) + t(i, k)))
159 ri(i) = ri(i) + &
160 zmgeom(i) * zmgeom(i) * gamt(k)/RG &
161 * (paprs(i, k)/101325.0)**RKAPPA &
162 /(zdu2 * 0.5 * (t(i, k - 1) + t(i, k)))
163 ENDIF
164
165 ! finalement, les coefficients d'echange sont obtenus:
166
167 cdn = SQRT(zdu2) / zmgeom(i) * RG
168
169 IF (opt_ec) THEN
170 z2geomf = zgeop(i, k - 1) + zgeop(i, k)
171 alm2 = (0.5 * ckap/RG * z2geomf &
172 /(1. + 0.5 * ckap/rg/clam * z2geomf))**2
173 zalh2 = (0.5 * ckap/rg * z2geomf &
174 /(1. + 0.5 * ckap/RG/(clam * SQRT(1.5 * cd)) * z2geomf))**2
175 IF (ri(i) < 0.) THEN
176 ! situation instable
177 scf = ((zgeop(i, k)/zgeop(i, k - 1))**(1./3.) - 1.)**3 &
178 / (zmgeom(i)/RG)**3 / (zgeop(i, k - 1)/RG)
179 scf = SQRT(- ri(i) * scf)
180 scfm = 1.0 / (1.0 + 3.0 * cb * cc * alm2 * scf)
181 zscfh = 1.0 / (1.0 + 3.0 * cb * cc * zalh2 * scf)
182 coefm(i, k) = cdn * alm2 * (1. - 2. * cb * ri(i) * scfm)
183 coefh(i, k) = cdn * zalh2 * (1. - 3.0 * cb * ri(i) * zscfh)
184 ELSE
185 ! situation stable
186 scf = SQRT(1. + cd * ri(i))
187 coefm(i, k) = cdn * alm2 / (1. + 2. * cb * ri(i) / scf)
188 coefh(i, k) = cdn * zalh2/(1. + 3.0 * cb * ri(i) * scf)
189 ENDIF
190 ELSE
191 l2(i) = (mixlen * MAX(0.0, (paprs(i, k) - paprs(i, itop(i) + 1)) &
192 /(paprs(i, 2) - paprs(i, itop(i) + 1)) ))**2
193 coefm(i, k) = sqrt(max(cdn**2 * (ric - ri(i)) / ric, kstable))
194 coefm(i, k) = l2(i) * coefm(i, k)
195 coefh(i, k) = coefm(i, k) / prandtl ! h et m different
196 ENDIF
197 ENDDO loop_horiz
198 ENDDO loop_vertical
199
200 ! Au-delà du sommet, pas de diffusion turbulente :
201 forall (i = 1: knon)
202 coefh(i, itop(i) + 1:) = 0.
203 coefm(i, itop(i) + 1:) = 0.
204 END forall
205
206 END SUBROUTINE coefkz
207
208 end module coefkz_m

  ViewVC Help
Powered by ViewVC 1.1.21