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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 228 - (show annotations)
Fri Nov 3 12:38:47 2017 UTC (6 years, 6 months ago) by guez
File size: 10295 byte(s)
Bug fix in dynetat0: phisinit to phis.

gcm explodes (stops in hgardfou) in less than one day with iflag_pbl =
7 (Mellor and Yamada 2.0 Fournier) and 11 (corresponding to iflag_pbl
= 31 in LMDZ, call to vdif_kcay). So remove those choices. Not much
used in LMDZ either. Remaining useful choices are iflag = 0, 1, 6, 8,
9.

Remove procedure yamada, which was not used.

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(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, assert_eq
17 USE dimphy, ONLY: klev
18
19 REAL, intent(in):: dt ! pas de temps
20 real, intent(in):: g
21
22 REAL zlev(:, :) ! (knon, klev + 1)
23 ! altitude \`a chaque niveau (interface inf\'erieure de la couche de
24 ! m\^eme indice)
25
26 REAL, intent(in):: zlay(:, :) ! (knon, klev) altitude au centre de
27 ! chaque couche
28
29 REAL, intent(in):: u(:, :), v(:, :) ! (knon, 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(:, :) ! (knon, 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(:) ! (knon) cdrag, valeur au d\'ebut du pas de temps
38
39 REAL, intent(inout):: q2(:, :) ! (knon, 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(:, :) ! (knon, 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(:, :) ! (knon, 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(:, :) ! (knon, klev + 1)
53 real, intent(in):: ustar(:) ! (knon)
54
55 integer, intent(in):: iflag_pbl
56 ! iflag_pbl doit valoir 6, 8 ou 9
57 ! l = 6, on prend syst\'ematiquement une longueur d'\'equilibre
58 ! iflag_pbl = 6 : Mellor and Yamada 2.0
59 ! iflag_pbl = 8 : Mellor and Yamada 2.5
60 ! iflag_pbl = 9 : un test ?
61
62 ! Local:
63 integer knon
64 real kmin, qmin
65 real pblhmin(size(cd)), coriol(size(cd)) ! (knon)
66 real qpre
67 REAL unsdz(size(zlay, 1), size(zlay, 2)) ! (knon, klev)
68 REAL unsdzdec(size(zlev, 1), size(zlev, 2)) ! (knon, klev + 1)
69 real delta(size(zlev, 1), size(zlev, 2)) ! (knon, klev + 1)
70 real aa(size(zlev, 1), size(zlev, 2)) ! (knon, klev + 1)
71 real aa1
72 logical:: first = .true.
73 integer:: ipas = 0
74 integer ig, k
75 real ri
76 real, dimension(size(zlev, 1), size(zlev, 2)):: rif, sm ! (knon, klev + 1)
77 real alpha(size(zlay, 1), size(zlay, 2)) ! (knon, klev)
78
79 real, dimension(size(zlev, 1), size(zlev, 2)):: m2, dz, n2
80 ! (knon, klev + 1)
81
82 real zq
83 real dtetadz(size(zlev, 1), size(zlev, 2)) ! (knon, klev + 1)
84 real l(size(zlev, 1), size(zlev, 2)) ! (knon, klev + 1)
85 real l0(size(cd)) ! (knon)
86 real sq(size(cd)), sqz(size(cd)) ! (knon)
87 real zz(size(zlev, 1), size(zlev, 2)) ! (knon, klev + 1)
88 integer iter
89 real:: ric = 0.195, rifc = 0.191, b1 = 16.6
90
91 !-----------------------------------------------------------------------
92
93 call assert(any(iflag_pbl == [6, 8, 9]), "yamada4 iflag_pbl")
94 knon = assert_eq([size(zlev, 1), size(zlay, 1), size(u, 1), size(v, 1), &
95 size(teta, 1), size(cd), size(q2, 1), size(km, 1), size(kn, 1), &
96 size(kq, 1)], "yamada4 knon")
97 call assert(klev == [size(zlev, 2) - 1, size(zlay, 2), size(u, 2), &
98 size(v, 2), size(teta, 2), size(q2, 2) - 1, size(km, 2) - 1, &
99 size(kn, 2) - 1, size(kq, 2) - 1], "yamada4 klev")
100
101 ipas = ipas + 1
102
103 ! les increments verticaux
104 DO ig = 1, knon
105 ! alerte: zlev n'est pas declare a klev + 1
106 zlev(ig, klev + 1) = zlay(ig, klev) + (zlay(ig, klev) - zlev(ig, klev))
107 ENDDO
108
109 DO k = 1, klev
110 DO ig = 1, knon
111 unsdz(ig, k) = 1.E+0/(zlev(ig, k + 1)-zlev(ig, k))
112 ENDDO
113 ENDDO
114
115 DO ig = 1, knon
116 unsdzdec(ig, 1) = 1.E+0/(zlay(ig, 1)-zlev(ig, 1))
117 ENDDO
118
119 DO k = 2, klev
120 DO ig = 1, knon
121 unsdzdec(ig, k) = 1.E+0/(zlay(ig, k)-zlay(ig, k-1))
122 ENDDO
123 ENDDO
124
125 DO ig = 1, knon
126 unsdzdec(ig, klev + 1) = 1.E+0/(zlev(ig, klev + 1)-zlay(ig, klev))
127 ENDDO
128
129 do k = 2, klev
130 do ig = 1, knon
131 dz(ig, k) = zlay(ig, k)-zlay(ig, k-1)
132 m2(ig, k) = ((u(ig, k)-u(ig, k-1))**2 + (v(ig, k)-v(ig, k-1))**2) &
133 /(dz(ig, k)*dz(ig, k))
134 dtetadz(ig, k) = (teta(ig, k)-teta(ig, k-1))/dz(ig, k)
135 n2(ig, k) = g*2.*dtetadz(ig, k)/(teta(ig, k-1) + teta(ig, k))
136 ri = n2(ig, k)/max(m2(ig, k), 1.e-10)
137 if (ri.lt.ric) then
138 rif(ig, k) = frif(ri)
139 else
140 rif(ig, k) = rifc
141 endif
142 if (rif(ig, k).lt.0.16) then
143 alpha(ig, k) = falpha(rif(ig, k))
144 sm(ig, k) = fsm(rif(ig, k))
145 else
146 alpha(ig, k) = 1.12
147 sm(ig, k) = 0.085
148 endif
149 zz(ig, k) = b1*m2(ig, k)*(1.-rif(ig, k))*sm(ig, k)
150 enddo
151 enddo
152
153 ! Au premier appel, on d\'etermine l et q2 de fa\ccon it\'erative.
154 ! It\'eration pour d\'eterminer la longueur de m\'elange
155
156 if (first .or. iflag_pbl == 6) then
157 do ig = 1, knon
158 l0(ig) = 10.
159 enddo
160 do k = 2, klev-1
161 do ig = 1, knon
162 l(ig, k) = l0(ig) * kap * zlev(ig, k) &
163 / (kap * zlev(ig, k) + l0(ig))
164 enddo
165 enddo
166
167 do iter = 1, 10
168 do ig = 1, knon
169 sq(ig) = 1e-10
170 sqz(ig) = 1e-10
171 enddo
172 do k = 2, klev-1
173 do ig = 1, knon
174 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
175 l(ig, k) = fl(zlev(ig, k), l0(ig), q2(ig, k), n2(ig, k))
176 zq = sqrt(q2(ig, k))
177 sqz(ig) = sqz(ig) + zq * zlev(ig, k) &
178 * (zlay(ig, k) - zlay(ig, k-1))
179 sq(ig) = sq(ig) + zq * (zlay(ig, k) - zlay(ig, k-1))
180 enddo
181 enddo
182 do ig = 1, knon
183 l0(ig) = 0.2 * sqz(ig) / sq(ig)
184 enddo
185 enddo
186 endif
187
188 ! Calcul de la longueur de melange.
189
190 ! Mise a jour de l0
191 do ig = 1, knon
192 sq(ig) = 1.e-10
193 sqz(ig) = 1.e-10
194 enddo
195 do k = 2, klev-1
196 do ig = 1, knon
197 zq = sqrt(q2(ig, k))
198 sqz(ig) = sqz(ig) + zq*zlev(ig, k)*(zlay(ig, k)-zlay(ig, k-1))
199 sq(ig) = sq(ig) + zq*(zlay(ig, k)-zlay(ig, k-1))
200 enddo
201 enddo
202 do ig = 1, knon
203 l0(ig) = 0.2*sqz(ig)/sq(ig)
204 enddo
205 ! calcul de l(z)
206 do k = 2, klev
207 do ig = 1, knon
208 l(ig, k) = fl(zlev(ig, k), l0(ig), q2(ig, k), n2(ig, k))
209 if (first) then
210 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
211 endif
212 enddo
213 enddo
214
215 if (iflag_pbl == 6) then
216 ! Yamada 2.0
217 do k = 2, klev
218 do ig = 1, knon
219 q2(ig, k) = l(ig, k)**2 * zz(ig, k)
220 enddo
221 enddo
222 else if (iflag_pbl >= 8) then
223 ! Yamada 2.5 a la Didi
224
225 ! Calcul de l, km, au pas precedent
226 do k = 2, klev
227 do ig = 1, knon
228 delta(ig, k) = q2(ig, k)/(l(ig, k)**2*sm(ig, k))
229 if (delta(ig, k).lt.1.e-20) then
230 delta(ig, k) = 1.e-20
231 endif
232 km(ig, k) = l(ig, k)*sqrt(q2(ig, k))*sm(ig, k)
233 aa1 = (m2(ig, k)*(1.-rif(ig, k))-delta(ig, k)/b1)
234 aa(ig, k) = aa1*dt/(delta(ig, k)*l(ig, k))
235 qpre = sqrt(q2(ig, k))
236 if (iflag_pbl == 8) then
237 if (aa(ig, k).gt.0.) then
238 q2(ig, k) = (qpre + aa(ig, k)*qpre*qpre)**2
239 else
240 q2(ig, k) = (qpre/(1.-aa(ig, k)*qpre))**2
241 endif
242 else
243 ! iflag_pbl = 9
244 if (aa(ig, k)*qpre.gt.0.9) then
245 q2(ig, k) = (qpre*10.)**2
246 else
247 q2(ig, k) = (qpre/(1.-aa(ig, k)*qpre))**2
248 endif
249 endif
250 q2(ig, k) = min(max(q2(ig, k), 1.e-10), 1.e4)
251 enddo
252 enddo
253 endif
254
255 ! Calcul des coefficients de m\'elange
256 do k = 2, klev
257 do ig = 1, knon
258 zq = sqrt(q2(ig, k))
259 km(ig, k) = l(ig, k)*zq*sm(ig, k)
260 kn(ig, k) = km(ig, k)*alpha(ig, k)
261 kq(ig, k) = l(ig, k)*zq*0.2
262 enddo
263 enddo
264
265 ! Traitement des cas noctrunes avec l'introduction d'une longueur
266 ! minilale.
267
268 ! Traitement particulier pour les cas tres stables.
269 ! D'apres Holtslag Boville.
270
271 do ig = 1, knon
272 coriol(ig) = 1.e-4
273 pblhmin(ig) = 0.07*ustar(ig)/max(abs(coriol(ig)), 2.546e-5)
274 enddo
275
276 do k = 2, klev
277 do ig = 1, knon
278 if (teta(ig, 2).gt.teta(ig, 1)) then
279 qmin = ustar(ig)*(max(1.-zlev(ig, k)/pblhmin(ig), 0.))**2
280 kmin = kap*zlev(ig, k)*qmin
281 else
282 kmin = -1. ! kmin n'est utilise que pour les SL stables.
283 endif
284 if (kn(ig, k).lt.kmin.or.km(ig, k).lt.kmin) then
285 kn(ig, k) = kmin
286 km(ig, k) = kmin
287 kq(ig, k) = kmin
288 ! la longueur de melange est suposee etre l = kap z
289 ! K = l q Sm d'ou q2 = (K/l Sm)**2
290 q2(ig, k) = (qmin/sm(ig, k))**2
291 endif
292 enddo
293 enddo
294
295 first = .false.
296
297 end SUBROUTINE yamada4
298
299 !*******************************************************************
300
301 real function frif(ri)
302
303 real, intent(in):: ri
304
305 frif = 0.6588*(ri + 0.1776-sqrt(ri*ri-0.3221*ri + 0.03156))
306
307 end function frif
308
309 !*******************************************************************
310
311 real function falpha(ri)
312
313 real, intent(in):: ri
314
315 falpha = 1.318*(0.2231-ri)/(0.2341-ri)
316
317 end function falpha
318
319 !*******************************************************************
320
321 real function fsm(ri)
322
323 real, intent(in):: ri
324
325 fsm = 1.96*(0.1912-ri)*(0.2341-ri)/((1.-ri)*(0.2231-ri))
326
327 end function fsm
328
329 !*******************************************************************
330
331 real function fl(zzz, zl0, zq2, zn2)
332
333 real, intent(in):: zzz, zl0, zq2, zn2
334
335 fl = max(min(zl0 * kap * zzz / (kap * zzz + zl0), &
336 0.5 * sqrt(zq2) / sqrt(max(zn2, 1e-10))), 1.)
337
338 end function fl
339
340 end module yamada4_m

  ViewVC Help
Powered by ViewVC 1.1.21