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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 178 - (show annotations)
Fri Mar 11 18:47:26 2016 UTC (8 years, 2 months ago) by guez
File size: 11066 byte(s)
Moved variables date0, deltat, datasz_max, ncvar_ids, point, buff_pos,
buffer, regular from module histcom_var to modules where they are
defined.

Removed procedure ioipslmpp, useless for a sequential program.

Added argument datasz_max to histwrite_real (to avoid circular
dependency with histwrite).

Removed useless variables and computations everywhere.

Changed real litteral constants from default kind to double precision
in lwb, lwu, lwvn, sw1s, swtt, swtt1, swu.

Removed unused arguments: paer of sw, sw1s, sw2s, swclr; pcldsw of
sw1s, sw2s; pdsig, prayl of swr; co2_ppm of clmain, clqh; tsol of
transp_lay; nsrf of screenp; kcrit and kknu of gwstress; pstd of
orosetup.

Added output of relative humidity.

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 \`a chaque niveau (interface inf\'erieure de la couche de
25 ! m\^eme 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\'ee : la valeur au
31 ! d\'ebut du pas de temps)
32
33 REAL, intent(in):: teta(ngrid, klev)
34 ! temp\'erature potentielle au centre de chaque couche (en entr\'ee :
35 ! la valeur au d\'ebut du pas de temps)
36
37 REAL, intent(in):: cd(:) ! (ngrid) cdrag, valeur au d\'ebut du pas de temps
38
39 REAL, intent(inout):: q2(ngrid, klev+1)
40 ! $q^2$ au bas de chaque couche
41 ! En entr\'ee : la valeur au d\'ebut du pas de temps ; en sortie : la
42 ! valeur \`a la fin du pas de temps.
43
44 REAL km(ngrid, klev+1)
45 ! diffusivit\'e turbulente de quantit\'e de mouvement (au bas de
46 ! chaque couche) (en sortie : la valeur \`a la fin du pas de temps)
47
48 REAL kn(ngrid, klev+1)
49 ! diffusivit\'e turbulente des scalaires (au bas de chaque couche)
50 ! (en sortie : la valeur \`a la fin du pas de temps)
51
52 REAL kq(ngrid, klev+1)
53 real ustar(ngrid)
54
55 integer, intent(in):: iflag_pbl
56 ! iflag_pbl doit valoir entre 6 et 9
57 ! l = 6, on prend syst\'ematiquement une longueur d'\'equilibre
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), 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 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
88 !-----------------------------------------------------------------------
89
90 call assert(iflag_pbl >= 6 .and. iflag_pbl <= 9, "yamada4")
91
92 ipas = ipas+1
93
94 ! les increments verticaux
95 DO ig = 1, ngrid
96 ! alerte: zlev n'est pas declare a nlev
97 zlev(ig, nlev) = zlay(ig, klev) +(zlay(ig, klev) - zlev(ig, nlev-1))
98 ENDDO
99
100 DO k = 1, klev
101 DO ig = 1, ngrid
102 unsdz(ig, k) = 1.E+0/(zlev(ig, k+1)-zlev(ig, k))
103 ENDDO
104 ENDDO
105
106 DO ig = 1, ngrid
107 unsdzdec(ig, 1) = 1.E+0/(zlay(ig, 1)-zlev(ig, 1))
108 ENDDO
109
110 DO k = 2, klev
111 DO ig = 1, ngrid
112 unsdzdec(ig, k) = 1.E+0/(zlay(ig, k)-zlay(ig, k-1))
113 ENDDO
114 ENDDO
115
116 DO ig = 1, ngrid
117 unsdzdec(ig, klev+1) = 1.E+0/(zlev(ig, klev+1)-zlay(ig, klev))
118 ENDDO
119
120 do k = 2, klev
121 do ig = 1, ngrid
122 dz(ig, k) = zlay(ig, k)-zlay(ig, k-1)
123 m2(ig, k) = ((u(ig, k)-u(ig, k-1))**2+(v(ig, k)-v(ig, k-1))**2) &
124 /(dz(ig, k)*dz(ig, k))
125 dtetadz(ig, k) = (teta(ig, k)-teta(ig, k-1))/dz(ig, k)
126 n2(ig, k) = g*2.*dtetadz(ig, k)/(teta(ig, k-1)+teta(ig, k))
127 ri = n2(ig, k)/max(m2(ig, k), 1.e-10)
128 if (ri.lt.ric) then
129 rif(ig, k) = frif(ri)
130 else
131 rif(ig, k) = rifc
132 endif
133 if (rif(ig, k).lt.0.16) then
134 alpha(ig, k) = falpha(rif(ig, k))
135 sm(ig, k) = fsm(rif(ig, k))
136 else
137 alpha(ig, k) = 1.12
138 sm(ig, k) = 0.085
139 endif
140 zz(ig, k) = b1*m2(ig, k)*(1.-rif(ig, k))*sm(ig, k)
141 enddo
142 enddo
143
144 ! Au premier appel, on d\'etermine l et q2 de façon it\'erative.
145 ! It\'eration pour d\'eterminer la longueur de m\'elange
146
147 if (first .or. iflag_pbl == 6) then
148 do ig = 1, ngrid
149 l0(ig) = 10.
150 enddo
151 do k = 2, klev-1
152 do ig = 1, ngrid
153 l(ig, k) = l0(ig) * kap * zlev(ig, k) &
154 / (kap * zlev(ig, k) + l0(ig))
155 enddo
156 enddo
157
158 do iter = 1, 10
159 do ig = 1, ngrid
160 sq(ig) = 1e-10
161 sqz(ig) = 1e-10
162 enddo
163 do k = 2, klev-1
164 do ig = 1, ngrid
165 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
166 l(ig, k) = fl(zlev(ig, k), l0(ig), q2(ig, k), n2(ig, k))
167 zq = sqrt(q2(ig, k))
168 sqz(ig) = sqz(ig) + zq * zlev(ig, k) &
169 * (zlay(ig, k) - zlay(ig, k-1))
170 sq(ig) = sq(ig) + zq * (zlay(ig, k) - zlay(ig, k-1))
171 enddo
172 enddo
173 do ig = 1, ngrid
174 l0(ig) = 0.2 * sqz(ig) / sq(ig)
175 enddo
176 enddo
177 endif
178
179 ! Calcul de la longueur de melange.
180
181 ! Mise a jour de l0
182 do ig = 1, ngrid
183 sq(ig) = 1.e-10
184 sqz(ig) = 1.e-10
185 enddo
186 do k = 2, klev-1
187 do ig = 1, ngrid
188 zq = sqrt(q2(ig, k))
189 sqz(ig) = sqz(ig)+zq*zlev(ig, k)*(zlay(ig, k)-zlay(ig, k-1))
190 sq(ig) = sq(ig)+zq*(zlay(ig, k)-zlay(ig, k-1))
191 enddo
192 enddo
193 do ig = 1, ngrid
194 l0(ig) = 0.2*sqz(ig)/sq(ig)
195 enddo
196 ! calcul de l(z)
197 do k = 2, klev
198 do ig = 1, ngrid
199 l(ig, k) = fl(zlev(ig, k), l0(ig), q2(ig, k), n2(ig, k))
200 if (first) then
201 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
202 endif
203 enddo
204 enddo
205
206 ! Yamada 2.0
207 if (iflag_pbl == 6) then
208 do k = 2, klev
209 do ig = 1, ngrid
210 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
211 enddo
212 enddo
213 else if (iflag_pbl == 7) then
214 ! Yamada 2.Fournier
215
216 ! Calcul de l, km, au pas precedent
217 do k = 2, klev
218 do ig = 1, ngrid
219 delta(ig, k) = q2(ig, k) / (l(ig, k)**2 * sm(ig, k))
220 kmpre(ig, k) = l(ig, k) * sqrt(q2(ig, k)) * sm(ig, k)
221 mpre(ig, k) = sqrt(m2(ig, k))
222 enddo
223 enddo
224
225 do k = 2, klev-1
226 do ig = 1, ngrid
227 m2cstat = max(alpha(ig, k)*n2(ig, k)+delta(ig, k)/b1, 1.e-12)
228 mcstat = sqrt(m2cstat)
229
230 ! puis on ecrit la valeur de q qui annule l'equation de m
231 ! supposee en q3
232
233 IF (k == 2) THEN
234 kmcstat = 1.E+0 / mcstat &
235 *(unsdz(ig, k)*kmpre(ig, k+1) &
236 *mpre(ig, k+1) &
237 +unsdz(ig, k-1) &
238 *cd(ig) &
239 *(sqrt(u(ig, 3)**2+v(ig, 3)**2) &
240 -mcstat/unsdzdec(ig, k) &
241 -mpre(ig, k+1)/unsdzdec(ig, k+1))**2) &
242 /(unsdz(ig, k)+unsdz(ig, k-1))
243 ELSE
244 kmcstat = 1.E+0 / mcstat &
245 *(unsdz(ig, k)*kmpre(ig, k+1) &
246 *mpre(ig, k+1) &
247 +unsdz(ig, k-1)*kmpre(ig, k-1) &
248 *mpre(ig, k-1)) &
249 /(unsdz(ig, k)+unsdz(ig, k-1))
250 ENDIF
251 tmp2 = kmcstat / (sm(ig, k) / q2(ig, k)) /l(ig, k)
252 q2(ig, k) = max(tmp2, 1.e-12)**(2./3.)
253 enddo
254 enddo
255 else if (iflag_pbl >= 8) then
256 ! Yamada 2.5 a la Didi
257
258 ! Calcul de l, km, au pas precedent
259 do k = 2, klev
260 do ig = 1, ngrid
261 delta(ig, k) = q2(ig, k)/(l(ig, k)**2*sm(ig, k))
262 if (delta(ig, k).lt.1.e-20) then
263 delta(ig, k) = 1.e-20
264 endif
265 km(ig, k) = l(ig, k)*sqrt(q2(ig, k))*sm(ig, k)
266 aa1 = (m2(ig, k)*(1.-rif(ig, k))-delta(ig, k)/b1)
267 aa(ig, k) = aa1*dt/(delta(ig, k)*l(ig, k))
268 qpre = sqrt(q2(ig, k))
269 if (iflag_pbl == 8) then
270 if (aa(ig, k).gt.0.) then
271 q2(ig, k) = (qpre+aa(ig, k)*qpre*qpre)**2
272 else
273 q2(ig, k) = (qpre/(1.-aa(ig, k)*qpre))**2
274 endif
275 else
276 ! iflag_pbl = 9
277 if (aa(ig, k)*qpre.gt.0.9) then
278 q2(ig, k) = (qpre*10.)**2
279 else
280 q2(ig, k) = (qpre/(1.-aa(ig, k)*qpre))**2
281 endif
282 endif
283 q2(ig, k) = min(max(q2(ig, k), 1.e-10), 1.e4)
284 enddo
285 enddo
286 endif
287
288 ! Calcul des coefficients de m\'elange
289 do k = 2, klev
290 do ig = 1, ngrid
291 zq = sqrt(q2(ig, k))
292 km(ig, k) = l(ig, k)*zq*sm(ig, k)
293 kn(ig, k) = km(ig, k)*alpha(ig, k)
294 kq(ig, k) = l(ig, k)*zq*0.2
295 enddo
296 enddo
297
298 ! Traitement des cas noctrunes avec l'introduction d'une longueur
299 ! minilale.
300
301 ! Traitement particulier pour les cas tres stables.
302 ! D'apres Holtslag Boville.
303
304 do ig = 1, ngrid
305 coriol(ig) = 1.e-4
306 pblhmin(ig) = 0.07*ustar(ig)/max(abs(coriol(ig)), 2.546e-5)
307 enddo
308
309 print *, 'pblhmin ', pblhmin
310 do k = 2, klev
311 do ig = 1, ngrid
312 if (teta(ig, 2).gt.teta(ig, 1)) then
313 qmin = ustar(ig)*(max(1.-zlev(ig, k)/pblhmin(ig), 0.))**2
314 kmin = kap*zlev(ig, k)*qmin
315 else
316 kmin = -1. ! kmin n'est utilise que pour les SL stables.
317 endif
318 if (kn(ig, k).lt.kmin.or.km(ig, k).lt.kmin) then
319 kn(ig, k) = kmin
320 km(ig, k) = kmin
321 kq(ig, k) = kmin
322 ! la longueur de melange est suposee etre l = kap z
323 ! K = l q Sm d'ou q2 = (K/l Sm)**2
324 q2(ig, k) = (qmin/sm(ig, k))**2
325 endif
326 enddo
327 enddo
328
329 first = .false.
330
331 end SUBROUTINE yamada4
332
333 !*******************************************************************
334
335 real function frif(ri)
336
337 real, intent(in):: ri
338
339 frif = 0.6588*(ri+0.1776-sqrt(ri*ri-0.3221*ri+0.03156))
340
341 end function frif
342
343 !*******************************************************************
344
345 real function falpha(ri)
346
347 real, intent(in):: ri
348
349 falpha = 1.318*(0.2231-ri)/(0.2341-ri)
350
351 end function falpha
352
353 !*******************************************************************
354
355 real function fsm(ri)
356
357 real, intent(in):: ri
358
359 fsm = 1.96*(0.1912-ri)*(0.2341-ri)/((1.-ri)*(0.2231-ri))
360
361 end function fsm
362
363 !*******************************************************************
364
365 real function fl(zzz, zl0, zq2, zn2)
366
367 real, intent(in):: zzz, zl0, zq2, zn2
368
369 fl = max(min(zl0 * kap * zzz / (kap * zzz + zl0), &
370 0.5 * sqrt(zq2) / sqrt(max(zn2, 1e-10))), 1.)
371
372 end function fl
373
374 end module yamada4_m

  ViewVC Help
Powered by ViewVC 1.1.21