1 |
guez |
47 |
module coefkz_m |
2 |
guez |
3 |
|
3 |
guez |
40 |
IMPLICIT none |
4 |
guez |
3 |
|
5 |
guez |
47 |
contains |
6 |
guez |
3 |
|
7 |
guez |
47 |
SUBROUTINE coefkz(nsrf, knon, paprs, pplay, ksta, ksta_ter, ts, rugos, u, v, & |
8 |
|
|
t, q, qsurf, pcfm, pcfh) |
9 |
guez |
40 |
|
10 |
guez |
47 |
! Authors: F. Hourdin, M. Forichon, Z.X. Li (LMD/CNRS) |
11 |
|
|
! date: 1993/09/22 |
12 |
|
|
! Objet : calculer le coefficient de frottement du sol ("Cdrag") et les |
13 |
|
|
! coefficients d'échange turbulent dans l'atmosphère. |
14 |
guez |
40 |
|
15 |
guez |
47 |
USE indicesol, ONLY : is_oce |
16 |
|
|
USE dimphy, ONLY : klev, klon, max |
17 |
|
|
USE iniprint, ONLY : prt_level |
18 |
|
|
USE suphec_m, ONLY : rcpd, rd, retv, rg, rkappa, rlstt, rlvtt, rtt |
19 |
|
|
USE yoethf_m, ONLY : r2es, r5ies, r5les, rvtmp2 |
20 |
|
|
USE fcttre, ONLY : dqsatl, dqsats, foede, foeew, qsatl, qsats, thermcep |
21 |
|
|
USE conf_phys_m, ONLY : iflag_pbl |
22 |
guez |
40 |
|
23 |
guez |
47 |
! Arguments: |
24 |
guez |
40 |
|
25 |
guez |
47 |
integer, intent(in):: nsrf ! indicateur de la nature du sol |
26 |
|
|
INTEGER, intent(in):: knon ! nombre de points a traiter |
27 |
guez |
40 |
|
28 |
guez |
47 |
REAL, intent(in):: paprs(klon, klev+1) |
29 |
|
|
! pression a chaque intercouche (en Pa) |
30 |
guez |
40 |
|
31 |
guez |
47 |
real, intent(in):: pplay(klon, klev) |
32 |
|
|
! pression au milieu de chaque couche (en Pa) |
33 |
guez |
40 |
|
34 |
guez |
47 |
REAL, intent(in):: ksta, ksta_ter |
35 |
|
|
REAL, intent(in):: ts(klon) ! temperature du sol (en Kelvin) |
36 |
|
|
REAL, intent(in):: rugos(klon) ! longeur de rugosite (en m) |
37 |
|
|
REAL, intent(in):: u(klon, klev), v(klon, klev) ! wind |
38 |
|
|
REAL, intent(in):: t(klon, klev) ! temperature (K) |
39 |
|
|
real, intent(in):: q(klon, klev) ! vapeur d'eau (kg/kg) |
40 |
|
|
real, intent(in):: qsurf(klon) |
41 |
|
|
REAL, intent(inout):: pcfm(klon, klev) ! coefficient, vitesse |
42 |
|
|
real, intent(inout):: pcfh(klon, klev) ! coefficient, chaleur et humidité |
43 |
guez |
40 |
|
44 |
guez |
47 |
! Local: |
45 |
guez |
40 |
|
46 |
guez |
47 |
INTEGER itop(klon) ! numero de couche du sommet de la couche limite |
47 |
guez |
40 |
|
48 |
guez |
47 |
! Quelques constantes et options: |
49 |
guez |
40 |
|
50 |
guez |
47 |
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 |
|
|
LOGICAL, PARAMETER:: richum = .TRUE. ! utilise le nombre de Richardson humide |
58 |
|
|
REAL, PARAMETER:: ric = 0.4 ! nombre de Richardson critique |
59 |
|
|
REAL, PARAMETER:: prandtl = 0.4 |
60 |
guez |
40 |
|
61 |
guez |
47 |
REAL kstable ! diffusion minimale (situation stable) |
62 |
|
|
REAL, PARAMETER:: mixlen = 35. ! constante controlant longueur de melange |
63 |
|
|
INTEGER, PARAMETER:: isommet = klev ! le sommet de la couche limite |
64 |
guez |
40 |
|
65 |
guez |
47 |
LOGICAL, PARAMETER:: tvirtu = .TRUE. |
66 |
|
|
! calculer Ri d'une maniere plus performante |
67 |
guez |
40 |
|
68 |
guez |
47 |
LOGICAL, PARAMETER:: opt_ec = .FALSE. |
69 |
|
|
! formule du Centre Europeen dans l'atmosphere |
70 |
guez |
40 |
|
71 |
guez |
47 |
INTEGER i, k, kk |
72 |
|
|
REAL zgeop(klon, klev) |
73 |
|
|
REAL zmgeom(klon) |
74 |
|
|
REAL zri(klon) |
75 |
|
|
REAL zl2(klon) |
76 |
guez |
40 |
|
77 |
guez |
47 |
REAL u1(klon), v1(klon), t1(klon), q1(klon), z1(klon) |
78 |
|
|
REAL pcfm1(klon), pcfh1(klon) |
79 |
guez |
40 |
|
80 |
guez |
47 |
REAL zdphi, zdu2, ztvd, ztvu, zcdn |
81 |
|
|
REAL zscf |
82 |
|
|
REAL zt, zq, zdelta, zcvm5, zcor, zqs, zfr, zdqs |
83 |
|
|
REAL z2geomf, zalh2, zalm2, zscfh, zscfm |
84 |
|
|
REAL, PARAMETER:: t_coup = 273.15 |
85 |
|
|
REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre |
86 |
guez |
40 |
|
87 |
guez |
47 |
!-------------------------------------------------------------------- |
88 |
guez |
40 |
|
89 |
guez |
47 |
! Initialiser les sorties |
90 |
|
|
DO k = 1, klev |
91 |
|
|
DO i = 1, knon |
92 |
|
|
pcfm(i, k) = 0. |
93 |
|
|
pcfh(i, k) = 0. |
94 |
|
|
ENDDO |
95 |
|
|
ENDDO |
96 |
|
|
DO i = 1, knon |
97 |
|
|
itop(i) = 0 |
98 |
|
|
ENDDO |
99 |
guez |
40 |
|
100 |
guez |
47 |
! Prescrire la valeur de contre-gradient |
101 |
|
|
if (iflag_pbl.eq.1) then |
102 |
|
|
DO k = 3, klev |
103 |
|
|
gamt(k) = -1.0E-03 |
104 |
|
|
ENDDO |
105 |
|
|
gamt(2) = -2.5E-03 |
106 |
|
|
else |
107 |
|
|
DO k = 2, klev |
108 |
|
|
gamt(k) = 0.0 |
109 |
|
|
ENDDO |
110 |
|
|
ENDIF |
111 |
guez |
40 |
|
112 |
guez |
47 |
IF ( nsrf .NE. is_oce ) THEN |
113 |
|
|
kstable = ksta_ter |
114 |
|
|
ELSE |
115 |
|
|
kstable = ksta |
116 |
|
|
ENDIF |
117 |
guez |
40 |
|
118 |
guez |
47 |
! Calculer les géopotentiels de chaque couche |
119 |
|
|
DO i = 1, knon |
120 |
|
|
zgeop(i, 1) = RD * t(i, 1) / (0.5 * (paprs(i, 1) + pplay(i, 1))) & |
121 |
|
|
* (paprs(i, 1) - pplay(i, 1)) |
122 |
|
|
ENDDO |
123 |
|
|
DO k = 2, klev |
124 |
|
|
DO i = 1, knon |
125 |
|
|
zgeop(i, k) = zgeop(i, k-1) & |
126 |
|
|
+ RD * 0.5*(t(i, k-1)+t(i, k)) / paprs(i, k) & |
127 |
|
|
* (pplay(i, k-1)-pplay(i, k)) |
128 |
|
|
ENDDO |
129 |
|
|
ENDDO |
130 |
guez |
40 |
|
131 |
guez |
47 |
! Calculer le frottement au sol (Cdrag) |
132 |
guez |
40 |
|
133 |
guez |
47 |
DO i = 1, knon |
134 |
|
|
u1(i) = u(i, 1) |
135 |
|
|
v1(i) = v(i, 1) |
136 |
|
|
t1(i) = t(i, 1) |
137 |
|
|
q1(i) = q(i, 1) |
138 |
|
|
z1(i) = zgeop(i, 1) |
139 |
|
|
ENDDO |
140 |
guez |
40 |
|
141 |
guez |
47 |
CALL clcdrag(klon, knon, nsrf, .false., u1, v1, t1, q1, z1, ts, qsurf, & |
142 |
|
|
rugos, pcfm1, pcfh1) |
143 |
guez |
40 |
|
144 |
guez |
47 |
DO i = 1, knon |
145 |
|
|
pcfm(i, 1) = pcfm1(i) |
146 |
|
|
pcfh(i, 1) = pcfh1(i) |
147 |
|
|
ENDDO |
148 |
guez |
40 |
|
149 |
guez |
47 |
! Calculer les coefficients turbulents dans l'atmosphere |
150 |
guez |
40 |
|
151 |
guez |
47 |
DO i = 1, knon |
152 |
|
|
itop(i) = isommet |
153 |
|
|
ENDDO |
154 |
guez |
40 |
|
155 |
guez |
47 |
loop_vertical: DO k = 2, isommet |
156 |
|
|
loop_horiz: DO i = 1, knon |
157 |
|
|
zdu2 = MAX(cepdu2, (u(i, k)-u(i, k-1))**2 & |
158 |
|
|
+(v(i, k)-v(i, k-1))**2) |
159 |
|
|
zmgeom(i) = zgeop(i, k)-zgeop(i, k-1) |
160 |
|
|
zdphi =zmgeom(i) / 2.0 |
161 |
|
|
zt = (t(i, k)+t(i, k-1)) * 0.5 |
162 |
|
|
zq = (q(i, k)+q(i, k-1)) * 0.5 |
163 |
guez |
40 |
|
164 |
guez |
47 |
! calculer Qs et dQs/dT: |
165 |
guez |
40 |
|
166 |
guez |
47 |
IF (thermcep) THEN |
167 |
|
|
zdelta = MAX(0., SIGN(1., RTT-zt)) |
168 |
|
|
zcvm5 = R5LES*RLVTT/RCPD/(1.0+RVTMP2*zq)*(1.-zdelta) & |
169 |
|
|
+ R5IES*RLSTT/RCPD/(1.0+RVTMP2*zq)*zdelta |
170 |
|
|
zqs = R2ES * FOEEW(zt, zdelta) / pplay(i, k) |
171 |
|
|
zqs = MIN(0.5, zqs) |
172 |
|
|
zcor = 1./(1.-RETV*zqs) |
173 |
|
|
zqs = zqs*zcor |
174 |
|
|
zdqs = FOEDE(zt, zdelta, zcvm5, zqs, zcor) |
175 |
|
|
ELSE |
176 |
|
|
IF (zt .LT. t_coup) THEN |
177 |
|
|
zqs = qsats(zt) / pplay(i, k) |
178 |
|
|
zdqs = dqsats(zt, zqs) |
179 |
|
|
ELSE |
180 |
|
|
zqs = qsatl(zt) / pplay(i, k) |
181 |
|
|
zdqs = dqsatl(zt, zqs) |
182 |
|
|
ENDIF |
183 |
|
|
ENDIF |
184 |
guez |
40 |
|
185 |
guez |
47 |
! calculer la fraction nuageuse (processus humide): |
186 |
guez |
40 |
|
187 |
guez |
47 |
zfr = (zq+ratqs*zq-zqs) / (2.0*ratqs*zq) |
188 |
|
|
zfr = MAX(0.0, MIN(1.0, zfr)) |
189 |
|
|
IF (.NOT.richum) zfr = 0.0 |
190 |
guez |
40 |
|
191 |
guez |
47 |
! calculer le nombre de Richardson: |
192 |
guez |
40 |
|
193 |
guez |
47 |
IF (tvirtu) THEN |
194 |
|
|
ztvd =( t(i, k) & |
195 |
|
|
+ zdphi/RCPD/(1.+RVTMP2*zq) & |
196 |
|
|
*( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) & |
197 |
|
|
)*(1.+RETV*q(i, k)) |
198 |
|
|
ztvu =( t(i, k-1) & |
199 |
|
|
- zdphi/RCPD/(1.+RVTMP2*zq) & |
200 |
|
|
*( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) & |
201 |
|
|
)*(1.+RETV*q(i, k-1)) |
202 |
|
|
zri(i) =zmgeom(i)*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu)) |
203 |
|
|
zri(i) = zri(i) & |
204 |
|
|
+ zmgeom(i)*zmgeom(i)/RG*gamt(k) & |
205 |
|
|
*(paprs(i, k)/101325.0)**RKAPPA & |
206 |
|
|
/(zdu2*0.5*(ztvd+ztvu)) |
207 |
|
|
ELSE |
208 |
|
|
! calcul de Ridchardson compatible LMD5 |
209 |
|
|
zri(i) =(RCPD*(t(i, k)-t(i, k-1)) & |
210 |
|
|
-RD*0.5*(t(i, k)+t(i, k-1))/paprs(i, k) & |
211 |
|
|
*(pplay(i, k)-pplay(i, k-1)) & |
212 |
|
|
)*zmgeom(i)/(zdu2*0.5*RCPD*(t(i, k-1)+t(i, k))) |
213 |
|
|
zri(i) = zri(i) + & |
214 |
|
|
zmgeom(i)*zmgeom(i)*gamt(k)/RG & |
215 |
|
|
*(paprs(i, k)/101325.0)**RKAPPA & |
216 |
|
|
/(zdu2*0.5*(t(i, k-1)+t(i, k))) |
217 |
|
|
ENDIF |
218 |
guez |
40 |
|
219 |
guez |
47 |
! finalement, les coefficients d'echange sont obtenus: |
220 |
guez |
40 |
|
221 |
guez |
47 |
zcdn = SQRT(zdu2) / zmgeom(i) * RG |
222 |
guez |
40 |
|
223 |
guez |
47 |
IF (opt_ec) THEN |
224 |
|
|
z2geomf = zgeop(i, k-1)+zgeop(i, k) |
225 |
|
|
zalm2 = (0.5*ckap/RG*z2geomf & |
226 |
|
|
/(1.+0.5*ckap/rg/clam*z2geomf))**2 |
227 |
|
|
zalh2 = (0.5*ckap/rg*z2geomf & |
228 |
|
|
/(1.+0.5*ckap/RG/(clam*SQRT(1.5*cd))*z2geomf))**2 |
229 |
|
|
IF (zri(i).LT.0.0) THEN |
230 |
|
|
! situation instable |
231 |
|
|
zscf = ((zgeop(i, k)/zgeop(i, k-1))**(1./3.)-1.)**3 & |
232 |
|
|
/ (zmgeom(i)/RG)**3 / (zgeop(i, k-1)/RG) |
233 |
|
|
zscf = SQRT(-zri(i)*zscf) |
234 |
|
|
zscfm = 1.0 / (1.0+3.0*cb*cc*zalm2*zscf) |
235 |
|
|
zscfh = 1.0 / (1.0+3.0*cb*cc*zalh2*zscf) |
236 |
|
|
pcfm(i, k) = zcdn*zalm2*(1.-2.0*cb*zri(i)*zscfm) |
237 |
|
|
pcfh(i, k) = zcdn*zalh2*(1.-3.0*cb*zri(i)*zscfh) |
238 |
|
|
ELSE |
239 |
|
|
! situation stable |
240 |
|
|
zscf = SQRT(1.+cd*zri(i)) |
241 |
|
|
pcfm(i, k) = zcdn*zalm2/(1.+2.0*cb*zri(i)/zscf) |
242 |
|
|
pcfh(i, k) = zcdn*zalh2/(1.+3.0*cb*zri(i)*zscf) |
243 |
|
|
ENDIF |
244 |
|
|
ELSE |
245 |
|
|
zl2(i) = (mixlen*MAX(0.0, (paprs(i, k)-paprs(i, itop(i)+1)) & |
246 |
|
|
/(paprs(i, 2)-paprs(i, itop(i)+1)) ))**2 |
247 |
|
|
pcfm(i, k) = sqrt(max(zcdn*zcdn*(ric-zri(i))/ric, kstable)) |
248 |
|
|
pcfm(i, k)= zl2(i)* pcfm(i, k) |
249 |
|
|
pcfh(i, k) = pcfm(i, k) /prandtl ! h et m different |
250 |
|
|
ENDIF |
251 |
|
|
ENDDO loop_horiz |
252 |
|
|
ENDDO loop_vertical |
253 |
guez |
40 |
|
254 |
guez |
47 |
! Au-dela du sommet, pas de diffusion turbulente: |
255 |
guez |
40 |
|
256 |
guez |
47 |
DO i = 1, knon |
257 |
|
|
IF (itop(i)+1 .LE. klev) THEN |
258 |
|
|
DO k = itop(i)+1, klev |
259 |
|
|
pcfh(i, k) = 0. |
260 |
|
|
pcfm(i, k) = 0. |
261 |
|
|
ENDDO |
262 |
|
|
ENDIF |
263 |
|
|
ENDDO |
264 |
guez |
40 |
|
265 |
guez |
47 |
END SUBROUTINE coefkz |
266 |
guez |
40 |
|
267 |
guez |
47 |
end module coefkz_m |