/[lmdze]/trunk/libf/phylmd/yamada4.f90
ViewVC logotype

Contents of /trunk/libf/phylmd/yamada4.f90

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (show annotations)
Fri Jul 1 15:00:48 2011 UTC (12 years, 10 months ago) by guez
File size: 11463 byte(s)
Split "thermcell.f" and "cv3_routines.f".
Removed copies of files that are now in "L_util".
Moved "mva9" and "diagetpq" to their own files.
Unified variable names across procedures.

1 module yamada4_m
2
3 IMPLICIT NONE
4
5 real, parameter:: kap = 0.4
6 private
7 public yamada4
8
9 contains
10
11 SUBROUTINE yamada4(ngrid, dt, g, zlev, zlay, u, v, teta, cd, q2, km, kn, &
12 kq, ustar, iflag_pbl)
13
14 ! From LMDZ4/libf/phylmd/yamada4.F, version 1.1 2004/06/22 11:45:36
15
16 USE dimphy, ONLY : klev, klon
17
18 integer ngrid
19 REAL, intent(in):: dt ! pas de temps
20 real, intent(in):: g
21
22 REAL zlev(klon, klev+1)
23 ! altitude à chaque niveau (interface inférieure de la couche de
24 ! même indice)
25
26 REAL zlay(klon, klev) ! altitude au centre de chaque couche
27
28 REAL u(klon, klev), v(klon, klev)
29 ! vitesse au centre de chaque couche (en entrée : la valeur au
30 ! début du pas de temps)
31
32 REAL teta(klon, klev)
33 ! température potentielle au centre de chaque couche (en entrée :
34 ! la valeur au début du pas de temps)
35
36 REAL cd(klon) ! cdrag (en entrée : la valeur au début du pas de temps)
37
38 REAL, intent(inout):: q2(klon, klev+1)
39 ! $q^2$ au bas de chaque couche
40 ! En entrée : la valeur au début du pas de temps ; en sortie : la
41 ! valeur à la fin du pas de temps.
42
43 REAL km(klon, klev+1)
44 ! diffusivité turbulente de quantité de mouvement (au bas de
45 ! chaque couche) (en sortie : la valeur à la fin du pas de temps)
46
47 REAL kn(klon, klev+1)
48 ! diffusivité turbulente des scalaires (au bas de chaque couche)
49 ! (en sortie : la valeur à la fin du pas de temps)
50
51 REAL kq(klon, klev+1)
52 real ustar(klon)
53
54 integer iflag_pbl
55 ! iflag_pbl doit valoir entre 6 et 9
56 ! l = 6, on prend systématiquement une longueur d'équilibre
57 ! iflag_pbl = 6 : MY 2.0
58 ! iflag_pbl = 7 : MY 2.0.Fournier
59 ! iflag_pbl = 8 : MY 2.5
60 ! iflag_pbl = 9 : un test ?
61
62 ! Local:
63
64 real kmin, qmin, pblhmin(klon), coriol(klon)
65 real qpre
66 REAL unsdz(klon, klev)
67 REAL unsdzdec(klon, klev+1)
68 REAL kmpre(klon, klev+1), tmp2
69 REAL mpre(klon, klev+1)
70 real delta(klon, klev+1)
71 real aa(klon, klev+1), aa0, aa1
72 integer, PARAMETER:: nlay = klev
73 integer, PARAMETER:: nlev = klev+1
74 logical:: first = .true.
75 integer:: ipas = 0
76 integer ig, k
77 real ri
78 real rif(klon, klev+1), sm(klon, klev+1), alpha(klon, klev)
79 real m2(klon, klev+1), dz(klon, klev+1), zq, n2(klon, klev+1)
80 real dtetadz(klon, klev+1)
81 real m2cstat, mcstat, kmcstat
82 real l(klon, klev+1)
83 real, save:: l0(klon)
84 real sq(klon), sqz(klon), zz(klon, klev+1)
85 integer iter
86 real:: ric = 0.195, rifc = 0.191, b1 = 16.6, kap = 0.4
87 real rino(klon, klev+1), smyam(klon, klev), styam(klon, klev)
88 real lyam(klon, klev), knyam(klon, klev)
89
90 !-----------------------------------------------------------------------
91
92 if (.not. (iflag_pbl >= 6 .and. iflag_pbl <= 9)) then
93 print *, 'probleme de coherence dans appel a MY'
94 stop 1
95 endif
96
97 ipas = ipas+1
98
99 ! les increments verticaux
100 DO ig = 1, ngrid
101 ! alerte: zlev n'est pas declare a nlev
102 zlev(ig, nlev) = zlay(ig, nlay) +(zlay(ig, nlay) - zlev(ig, nlev-1))
103 ENDDO
104
105 DO k = 1, nlay
106 DO ig = 1, ngrid
107 unsdz(ig, k) = 1.E+0/(zlev(ig, k+1)-zlev(ig, k))
108 ENDDO
109 ENDDO
110 DO ig = 1, ngrid
111 unsdzdec(ig, 1) = 1.E+0/(zlay(ig, 1)-zlev(ig, 1))
112 ENDDO
113 DO k = 2, nlay
114 DO ig = 1, ngrid
115 unsdzdec(ig, k) = 1.E+0/(zlay(ig, k)-zlay(ig, k-1))
116 ENDDO
117 ENDDO
118 DO ig = 1, ngrid
119 unsdzdec(ig, nlay+1) = 1.E+0/(zlev(ig, nlay+1)-zlay(ig, nlay))
120 ENDDO
121
122 do k = 2, klev
123 do ig = 1, ngrid
124 dz(ig, k) = zlay(ig, k)-zlay(ig, k-1)
125 m2(ig, k) = ((u(ig, k)-u(ig, k-1))**2+(v(ig, k)-v(ig, k-1))**2) &
126 /(dz(ig, k)*dz(ig, k))
127 dtetadz(ig, k) = (teta(ig, k)-teta(ig, k-1))/dz(ig, k)
128 n2(ig, k) = g*2.*dtetadz(ig, k)/(teta(ig, k-1)+teta(ig, k))
129 ri = n2(ig, k)/max(m2(ig, k), 1.e-10)
130 if (ri.lt.ric) then
131 rif(ig, k) = frif(ri)
132 else
133 rif(ig, k) = rifc
134 endif
135 if(rif(ig, k).lt.0.16) then
136 alpha(ig, k) = falpha(rif(ig, k))
137 sm(ig, k) = fsm(rif(ig, k))
138 else
139 alpha(ig, k) = 1.12
140 sm(ig, k) = 0.085
141 endif
142 zz(ig, k) = b1*m2(ig, k)*(1.-rif(ig, k))*sm(ig, k)
143 enddo
144 enddo
145
146 ! Au premier appel, on détermine l et q2 de façon itérative.
147 ! Itération pour déterminer la longueur de mélange
148
149 if (first .or. iflag_pbl == 6) then
150 do ig = 1, ngrid
151 l0(ig) = 10.
152 enddo
153 do k = 2, klev-1
154 do ig = 1, ngrid
155 l(ig, k) = l0(ig) * kap * zlev(ig, k) &
156 / (kap * zlev(ig, k) + l0(ig))
157 enddo
158 enddo
159
160 do iter = 1, 10
161 do ig = 1, ngrid
162 sq(ig) = 1e-10
163 sqz(ig) = 1e-10
164 enddo
165 do k = 2, klev-1
166 do ig = 1, ngrid
167 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
168 l(ig, k) = fl(zlev(ig, k), l0(ig), q2(ig, k), n2(ig, k))
169 zq = sqrt(q2(ig, k))
170 sqz(ig) = sqz(ig) + zq * zlev(ig, k) &
171 * (zlay(ig, k) - zlay(ig, k-1))
172 sq(ig) = sq(ig) + zq * (zlay(ig, k) - zlay(ig, k-1))
173 enddo
174 enddo
175 do ig = 1, ngrid
176 l0(ig) = 0.2 * sqz(ig) / sq(ig)
177 enddo
178 enddo
179 endif
180
181 ! Calcul de la longueur de melange.
182
183 ! Mise a jour de l0
184 do ig = 1, ngrid
185 sq(ig) = 1.e-10
186 sqz(ig) = 1.e-10
187 enddo
188 do k = 2, klev-1
189 do ig = 1, ngrid
190 zq = sqrt(q2(ig, k))
191 sqz(ig) = sqz(ig)+zq*zlev(ig, k)*(zlay(ig, k)-zlay(ig, k-1))
192 sq(ig) = sq(ig)+zq*(zlay(ig, k)-zlay(ig, k-1))
193 enddo
194 enddo
195 do ig = 1, ngrid
196 l0(ig) = 0.2*sqz(ig)/sq(ig)
197 enddo
198 ! calcul de l(z)
199 do k = 2, klev
200 do ig = 1, ngrid
201 l(ig, k) = fl(zlev(ig, k), l0(ig), q2(ig, k), n2(ig, k))
202 if(first) then
203 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
204 endif
205 enddo
206 enddo
207
208 ! Yamada 2.0
209 if (iflag_pbl == 6) then
210 do k = 2, klev
211 do ig = 1, ngrid
212 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
213 enddo
214 enddo
215 else if (iflag_pbl == 7) then
216 ! Yamada 2.Fournier
217
218 ! Calcul de l, km, au pas precedent
219 do k = 2, klev
220 do ig = 1, ngrid
221 delta(ig, k) = q2(ig, k) / (l(ig, k)**2 * sm(ig, k))
222 kmpre(ig, k) = l(ig, k) * sqrt(q2(ig, k)) * sm(ig, k)
223 mpre(ig, k) = sqrt(m2(ig, k))
224 enddo
225 enddo
226
227 do k = 2, klev-1
228 do ig = 1, ngrid
229 m2cstat = max(alpha(ig, k)*n2(ig, k)+delta(ig, k)/b1, 1.e-12)
230 mcstat = sqrt(m2cstat)
231
232 ! puis on ecrit la valeur de q qui annule l'equation de m
233 ! supposee en q3
234
235 IF (k == 2) THEN
236 kmcstat = 1.E+0 / mcstat &
237 *(unsdz(ig, k)*kmpre(ig, k+1) &
238 *mpre(ig, k+1) &
239 +unsdz(ig, k-1) &
240 *cd(ig) &
241 *(sqrt(u(ig, 3)**2+v(ig, 3)**2) &
242 -mcstat/unsdzdec(ig, k) &
243 -mpre(ig, k+1)/unsdzdec(ig, k+1))**2) &
244 /(unsdz(ig, k)+unsdz(ig, k-1))
245 ELSE
246 kmcstat = 1.E+0 / mcstat &
247 *(unsdz(ig, k)*kmpre(ig, k+1) &
248 *mpre(ig, k+1) &
249 +unsdz(ig, k-1)*kmpre(ig, k-1) &
250 *mpre(ig, k-1)) &
251 /(unsdz(ig, k)+unsdz(ig, k-1))
252 ENDIF
253 tmp2 = kmcstat / (sm(ig, k) / q2(ig, k)) /l(ig, k)
254 q2(ig, k) = max(tmp2, 1.e-12)**(2./3.)
255 enddo
256 enddo
257 else if (iflag_pbl >= 8) then
258 ! Yamada 2.5 a la Didi
259
260 ! Calcul de l, km, au pas precedent
261 do k = 2, klev
262 do ig = 1, ngrid
263 delta(ig, k) = q2(ig, k)/(l(ig, k)**2*sm(ig, k))
264 if (delta(ig, k).lt.1.e-20) then
265 delta(ig, k) = 1.e-20
266 endif
267 km(ig, k) = l(ig, k)*sqrt(q2(ig, k))*sm(ig, k)
268 aa0 = (m2(ig, k)-alpha(ig, k)*n2(ig, k)-delta(ig, k)/b1)
269 aa1 = (m2(ig, k)*(1.-rif(ig, k))-delta(ig, k)/b1)
270 aa(ig, k) = aa1*dt/(delta(ig, k)*l(ig, k))
271 qpre = sqrt(q2(ig, k))
272 if (iflag_pbl == 8) then
273 if (aa(ig, k).gt.0.) then
274 q2(ig, k) = (qpre+aa(ig, k)*qpre*qpre)**2
275 else
276 q2(ig, k) = (qpre/(1.-aa(ig, k)*qpre))**2
277 endif
278 else
279 ! iflag_pbl = 9
280 if (aa(ig, k)*qpre.gt.0.9) then
281 q2(ig, k) = (qpre*10.)**2
282 else
283 q2(ig, k) = (qpre/(1.-aa(ig, k)*qpre))**2
284 endif
285 endif
286 q2(ig, k) = min(max(q2(ig, k), 1.e-10), 1.e4)
287 enddo
288 enddo
289 endif
290
291 ! Calcul des coefficients de mélange
292 do k = 2, klev
293 do ig = 1, ngrid
294 zq = sqrt(q2(ig, k))
295 km(ig, k) = l(ig, k)*zq*sm(ig, k)
296 kn(ig, k) = km(ig, k)*alpha(ig, k)
297 kq(ig, k) = l(ig, k)*zq*0.2
298 enddo
299 enddo
300
301 ! Traitement des cas noctrunes avec l'introduction d'une longueur
302 ! minilale.
303
304 ! Traitement particulier pour les cas tres stables.
305 ! D'apres Holtslag Boville.
306
307 do ig = 1, ngrid
308 coriol(ig) = 1.e-4
309 pblhmin(ig) = 0.07*ustar(ig)/max(abs(coriol(ig)), 2.546e-5)
310 enddo
311
312 print *, 'pblhmin ', pblhmin
313 do k = 2, klev
314 do ig = 1, klon
315 if (teta(ig, 2).gt.teta(ig, 1)) then
316 qmin = ustar(ig)*(max(1.-zlev(ig, k)/pblhmin(ig), 0.))**2
317 kmin = kap*zlev(ig, k)*qmin
318 else
319 kmin = -1. ! kmin n'est utilise que pour les SL stables.
320 endif
321 if (kn(ig, k).lt.kmin.or.km(ig, k).lt.kmin) then
322 kn(ig, k) = kmin
323 km(ig, k) = kmin
324 kq(ig, k) = kmin
325 ! la longueur de melange est suposee etre l = kap z
326 ! K = l q Sm d'ou q2 = (K/l Sm)**2
327 q2(ig, k) = (qmin/sm(ig, k))**2
328 endif
329 enddo
330 enddo
331
332 ! Diagnostique pour stokage
333
334 rino = rif
335 smyam(:, 1:klev) = sm(:, 1:klev)
336 styam = sm(:, 1:klev)*alpha(:, 1:klev)
337 lyam(1:klon, 1:klev) = l(:, 1:klev)
338 knyam(1:klon, 1:klev) = kn(:, 1:klev)
339
340 first = .false.
341
342 end SUBROUTINE yamada4
343
344 !*******************************************************************
345
346 function frif(ri)
347
348 real frif
349 real, intent(in):: ri
350
351 frif = 0.6588*(ri+0.1776-sqrt(ri*ri-0.3221*ri+0.03156))
352
353 end function frif
354
355 !*******************************************************************
356
357 function falpha(ri)
358
359 real falpha
360 real, intent(in):: ri
361
362 falpha = 1.318*(0.2231-ri)/(0.2341-ri)
363
364 end function falpha
365
366 !*******************************************************************
367
368 function fsm(ri)
369
370 real fsm
371 real, intent(in):: ri
372
373 fsm = 1.96*(0.1912-ri)*(0.2341-ri)/((1.-ri)*(0.2231-ri))
374
375 end function fsm
376
377 !*******************************************************************
378
379 function fl(zzz, zl0, zq2, zn2)
380
381 real fl
382 real, intent(in):: zzz, zl0, zq2, zn2
383
384 fl = max(min(zl0 * kap * zzz / (kap * zzz + zl0), &
385 0.5 * sqrt(zq2) / sqrt(max(zn2, 1e-10))), 1.)
386
387 end function fl
388
389 end module yamada4_m

  ViewVC Help
Powered by ViewVC 1.1.21