/[lmdze]/trunk/phylmd/yamada4.f
ViewVC logotype

Contents of /trunk/phylmd/yamada4.f

Parent Directory Parent Directory | Revision Log Revision Log


Revision 118 - (show annotations)
Thu Dec 18 17:30:24 2014 UTC (9 years, 4 months ago) by guez
File size: 11368 byte(s)
In file grilles_gcm.nc, renamed variable phis to orog, deleted
variable presnivs.

Removed variable bug_ozone from module clesphys.

In procedure ozonecm, moved computation of sint and cost out of the
loops on horizontal position and vertical level. Inverted the order of
the two loops. We can then move all computations from slat to aprim
out of the loop on vertical levels. Created variable slat2, following
LMDZ. Moved the limitation of column-density of ozone in cell at 1e-12
from radlwsw to ozonecm, following LMDZ.

Removed unused arguments u, albsol, rh, cldfra, rneb, diafra, cldliq,
pmflxr, pmflxs, prfl, psfl of phytrac.

In procedure yamada4, for all the arrays, replaced the dimension klon
by ngrid. At the end of the procedure, for the computation of kmn,kn,
kq and q2, changed the upper limit of the loop index from klon to ngrid.

In radlwsw, for the calculation of pozon, removed the factor
paprs(iof+i, 1)/101325, as in LMDZ. In procedure sw, removed the
factor 101325.0/PPSOL(JL), as in LMDZ.

1 module yamada4_m
2
3 IMPLICIT NONE
4
5 private
6 public yamada4
7 real, parameter:: kap = 0.4
8
9 contains
10
11 SUBROUTINE yamada4(ngrid, dt, g, zlev, zlay, u, v, teta, cd, q2, km, kn, kq, &
12 ustar, iflag_pbl)
13
14 ! From LMDZ4/libf/phylmd/yamada4.F, version 1.1 2004/06/22 11:45:36
15
16 use nr_util, only: assert
17 USE dimphy, ONLY: klev
18
19 integer, intent(in):: ngrid
20 REAL, intent(in):: dt ! pas de temps
21 real, intent(in):: g
22
23 REAL zlev(ngrid, klev+1)
24 ! altitude à chaque niveau (interface inférieure de la couche de
25 ! même indice)
26
27 REAL zlay(ngrid, klev) ! altitude au centre de chaque couche
28
29 REAL u(ngrid, klev), v(ngrid, klev)
30 ! vitesse au centre de chaque couche (en entrée : la valeur au
31 ! début du pas de temps)
32
33 REAL, intent(in): teta(ngrid, klev)
34 ! température potentielle au centre de chaque couche (en entrée :
35 ! la valeur au début du pas de temps)
36
37 REAL, intent(in):: cd(:) ! (ngrid) cdrag, valeur au début du pas de temps
38
39 REAL, intent(inout):: q2(ngrid, klev+1)
40 ! $q^2$ au bas de chaque couche
41 ! En entrée : la valeur au début du pas de temps ; en sortie : la
42 ! valeur à la fin du pas de temps.
43
44 REAL km(ngrid, klev+1)
45 ! diffusivité turbulente de quantité de mouvement (au bas de
46 ! chaque couche) (en sortie : la valeur à la fin du pas de temps)
47
48 REAL kn(ngrid, klev+1)
49 ! diffusivité turbulente des scalaires (au bas de chaque couche)
50 ! (en sortie : la valeur à la fin du pas de temps)
51
52 REAL kq(ngrid, klev+1)
53 real ustar(ngrid)
54
55 integer iflag_pbl
56 ! iflag_pbl doit valoir entre 6 et 9
57 ! l = 6, on prend systématiquement une longueur d'équilibre
58 ! iflag_pbl = 6 : MY 2.0
59 ! iflag_pbl = 7 : MY 2.0.Fournier
60 ! iflag_pbl = 8 : MY 2.5
61 ! iflag_pbl = 9 : un test ?
62
63 ! Local:
64
65 real kmin, qmin, pblhmin(ngrid), coriol(ngrid)
66 real qpre
67 REAL unsdz(ngrid, klev)
68 REAL unsdzdec(ngrid, klev+1)
69 REAL kmpre(ngrid, klev+1), tmp2
70 REAL mpre(ngrid, klev+1)
71 real delta(ngrid, klev+1)
72 real aa(ngrid, klev+1), aa0, aa1
73 integer, PARAMETER:: nlev = klev+1
74 logical:: first = .true.
75 integer:: ipas = 0
76 integer ig, k
77 real ri
78 real rif(ngrid, klev+1), sm(ngrid, klev+1), alpha(ngrid, klev)
79 real m2(ngrid, klev+1), dz(ngrid, klev+1), zq, n2(ngrid, klev+1)
80 real dtetadz(ngrid, klev+1)
81 real m2cstat, mcstat, kmcstat
82 real l(ngrid, klev+1)
83 real, save:: l0(ngrid)
84 real sq(ngrid), sqz(ngrid), zz(ngrid, klev+1)
85 integer iter
86 real:: ric = 0.195, rifc = 0.191, b1 = 16.6, kap = 0.4
87 real rino(ngrid, klev+1), smyam(ngrid, klev), styam(ngrid, klev)
88 real lyam(ngrid, klev), knyam(ngrid, klev)
89
90 !-----------------------------------------------------------------------
91
92 call assert(iflag_pbl >= 6 .and. iflag_pbl <= 9, "yamada4")
93
94 ipas = ipas+1
95
96 ! les increments verticaux
97 DO ig = 1, ngrid
98 ! alerte: zlev n'est pas declare a nlev
99 zlev(ig, nlev) = zlay(ig, klev) +(zlay(ig, klev) - zlev(ig, nlev-1))
100 ENDDO
101
102 DO k = 1, klev
103 DO ig = 1, ngrid
104 unsdz(ig, k) = 1.E+0/(zlev(ig, k+1)-zlev(ig, k))
105 ENDDO
106 ENDDO
107
108 DO ig = 1, ngrid
109 unsdzdec(ig, 1) = 1.E+0/(zlay(ig, 1)-zlev(ig, 1))
110 ENDDO
111
112 DO k = 2, klev
113 DO ig = 1, ngrid
114 unsdzdec(ig, k) = 1.E+0/(zlay(ig, k)-zlay(ig, k-1))
115 ENDDO
116 ENDDO
117
118 DO ig = 1, ngrid
119 unsdzdec(ig, klev+1) = 1.E+0/(zlev(ig, klev+1)-zlay(ig, klev))
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, ngrid
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:ngrid, 1:klev) = l(:, 1:klev)
338
339 first = .false.
340
341 end SUBROUTINE yamada4
342
343 !*******************************************************************
344
345 real function frif(ri)
346
347 real, intent(in):: ri
348
349 frif = 0.6588*(ri+0.1776-sqrt(ri*ri-0.3221*ri+0.03156))
350
351 end function frif
352
353 !*******************************************************************
354
355 real function falpha(ri)
356
357 real, intent(in):: ri
358
359 falpha = 1.318*(0.2231-ri)/(0.2341-ri)
360
361 end function falpha
362
363 !*******************************************************************
364
365 real function fsm(ri)
366
367 real, intent(in):: ri
368
369 fsm = 1.96*(0.1912-ri)*(0.2341-ri)/((1.-ri)*(0.2231-ri))
370
371 end function fsm
372
373 !*******************************************************************
374
375 real function fl(zzz, zl0, zq2, zn2)
376
377 real, intent(in):: zzz, zl0, zq2, zn2
378
379 fl = max(min(zl0 * kap * zzz / (kap * zzz + zl0), &
380 0.5 * sqrt(zq2) / sqrt(max(zn2, 1e-10))), 1.)
381
382 end function fl
383
384 end module yamada4_m

  ViewVC Help
Powered by ViewVC 1.1.21