/[lmdze]/trunk/phylmd/Thermcell/thermcell.f90
ViewVC logotype

Contents of /trunk/phylmd/Thermcell/thermcell.f90

Parent Directory Parent Directory | Revision Log Revision Log


Revision 340 - (show annotations)
Thu Sep 26 17:29:50 2019 UTC (4 years, 8 months ago) by guez
File size: 17496 byte(s)
Remove `new_oliq` and `ok_stratus`

Remove possibility to choose `new_oliq` false. LMDZ is always used with
`new_oliq` true.

Remove possibility to choose `ok_stratus` true. LMDZ is always used
with `ok_stratus` false.

Encapsulate dqthermcell in a module.

1 module thermcell_m
2
3 IMPLICIT NONE
4
5 contains
6
7 SUBROUTINE thermcell(ngrid, nlay, ptimestep, pplay, pplev, pphi, u, v, pt, &
8 po, pduadj, pdvadj, pdtadj, pdoadj, fm0, entr0)
9
10 ! Calcul du transport vertical dans la couche limite en pr\'esence
11 ! de "thermiques" explicitement repr\'esent\'es. R\'ecriture \`a partir
12 ! d'un listing papier \`a Habas, le 14/02/00. Le thermique est
13 ! suppos\'e homog\`ene et dissip\'e par m\'elange avec son
14 ! environnement. La longueur "l_mix" contr\^ole l'efficacit\'e du
15 ! m\'elange. Le calcul du transport des diff\'erentes esp\`eces se fait
16 ! en prenant en compte :
17 ! 1. un flux de masse montant
18 ! 2. un flux de masse descendant
19 ! 3. un entra\^inement
20 ! 4. un d\'etra\^inement
21
22 USE dimphy, ONLY : klev, klon
23 use dqthermcell_m, only: dqthermcell
24 USE suphec_m, ONLY : rd, rg, rkappa
25
26 INTEGER ngrid, nlay
27 real ptimestep
28 REAL, intent(in):: pplay(ngrid, nlay)
29 real, intent(in):: pplev(ngrid, nlay+1)
30 real, intent(in):: pphi(ngrid, nlay)
31 REAL, intent(in):: u(ngrid, nlay)
32 REAL, intent(in):: v(ngrid, nlay)
33 REAL, intent(in):: pt(ngrid, nlay)
34 REAL po(ngrid, nlay)
35 real pduadj(ngrid, nlay)
36 real pdvadj(ngrid, nlay)
37 real pdtadj(ngrid, nlay)
38 real pdoadj(ngrid, nlay)
39 real fm0(klon, klev+1), entr0(klon, klev)
40
41 ! Local:
42
43 integer idetr
44 save idetr
45 data idetr/3/
46
47 INTEGER ig, k, l, lmaxa(klon), lmix(klon)
48 ! CR: on remplace lmax(klon, klev+1)
49 INTEGER lmax(klon), lmin(klon), lentr(klon)
50 real linter(klon)
51 real zmix(klon), fracazmix(klon)
52
53 real zmax(klon), zw, zw2(klon, klev+1), ztva(klon, klev)
54
55 real zlev(klon, klev+1)
56 REAL zh(klon, klev), zdhadj(klon, klev)
57 REAL ztv(klon, klev)
58 real zu(klon, klev), zv(klon, klev), zo(klon, klev)
59 real zva(klon, klev)
60 real zua(klon, klev)
61 real zoa(klon, klev)
62
63 real zha(klon, klev)
64 real wa_moy(klon, klev+1)
65 real fraca(klon, klev+1)
66 real fracc(klon, klev+1)
67 real zf, zf2
68 real thetath2(klon, klev), wth2(klon, klev)
69 common/comtherm/thetath2, wth2
70
71 real rho(klon, klev), rhobarz(klon, klev+1), masse(klon, klev)
72 real zpspsk(klon, klev)
73
74 real wmax(klon), wmaxa(klon)
75 real fracd(klon, klev+1)
76 real xxx(klon, klev+1)
77 real larg_cons(klon, klev+1)
78 real larg_detr(klon, klev+1)
79 real detr(klon, klev)
80 real fm(klon, klev+1), entr(klon, klev)
81 real fmc(klon, klev+1)
82
83 !CR:nouvelles variables
84 real f_star(klon, klev+1), entr_star(klon, klev)
85 real entr_star_tot(klon), entr_star2(klon)
86 real f(klon)
87 real zlevinter(klon)
88
89 real, parameter:: r_aspect = 4.
90 real, parameter:: l_mix = 10.
91 real, parameter:: tho = 0.
92 integer, parameter:: w2di = 0
93
94 EXTERNAL SCOPY
95
96 !-----------------------------------------------------------------------
97
98 ! initialisation:
99
100 IF(ngrid.NE.klon) THEN
101 PRINT *
102 PRINT *, 'STOP dans convadj'
103 PRINT *, 'ngrid =', ngrid
104 PRINT *, 'klon =', klon
105 ENDIF
106
107 ! incrementation eventuelle de tendances precedentes:
108
109 print *, '0 OK convect8'
110
111 DO l=1, nlay
112 DO ig=1, ngrid
113 zpspsk(ig, l)=(pplay(ig, l)/pplev(ig, 1))**RKAPPA
114 zh(ig, l)=pt(ig, l)/zpspsk(ig, l)
115 zu(ig, l)=u(ig, l)
116 zv(ig, l)=v(ig, l)
117 zo(ig, l)=po(ig, l)
118 ztv(ig, l)=zh(ig, l)*(1.+0.61*zo(ig, l))
119 end DO
120 end DO
121
122 print *, '1 OK convect8'
123
124 ! See notes, "thermcell.txt"
125 ! Calcul des altitudes des couches
126
127 do l=2, nlay
128 do ig=1, ngrid
129 zlev(ig, l)=0.5*(pphi(ig, l)+pphi(ig, l-1))/RG
130 enddo
131 enddo
132 do ig=1, ngrid
133 zlev(ig, 1)=0.
134 zlev(ig, nlay+1)=(2.*pphi(ig, klev)-pphi(ig, klev-1))/RG
135 enddo
136
137 ! Calcul des densites
138
139 do l=1, nlay
140 do ig=1, ngrid
141 rho(ig, l)=pplay(ig, l)/(zpspsk(ig, l)*RD*zh(ig, l))
142 enddo
143 enddo
144
145 do l=2, nlay
146 do ig=1, ngrid
147 rhobarz(ig, l)=0.5*(rho(ig, l)+rho(ig, l-1))
148 enddo
149 enddo
150
151 ! Calcul de w2, quarre de w a partir de la cape
152 ! a partir de w2, on calcule wa, vitesse de l'ascendance
153
154 ! ATTENTION: Dans cette version, pour cause d'economie de memoire,
155 ! w2 est stoke dans wa
156
157 ! ATTENTION: dans convect8, on n'utilise le calcule des wa
158 ! independants par couches que pour calculer l'entrainement
159 ! a la base et la hauteur max de l'ascendance.
160
161 ! Indicages:
162 ! l'ascendance provenant du niveau k traverse l'interface l avec
163 ! une vitesse wa(k, l).
164 ! See notes, "thermcell.txt".
165
166 !CR: ponderation entrainement des couches instables
167 !def des entr_star tels que entr=f*entr_star
168 do l=1, klev
169 do ig=1, ngrid
170 entr_star(ig, l)=0.
171 enddo
172 enddo
173 ! determination de la longueur de la couche d entrainement
174 do ig=1, ngrid
175 lentr(ig)=1
176 enddo
177
178 !on ne considere que les premieres couches instables
179 do k=nlay-2, 1, -1
180 do ig=1, ngrid
181 if (ztv(ig, k).gt.ztv(ig, k+1).and. &
182 ztv(ig, k+1).le.ztv(ig, k+2)) then
183 lentr(ig)=k
184 endif
185 enddo
186 enddo
187
188 ! determination du lmin: couche d ou provient le thermique
189 do ig=1, ngrid
190 lmin(ig)=1
191 enddo
192 do ig=1, ngrid
193 do l=nlay, 2, -1
194 if (ztv(ig, l-1).gt.ztv(ig, l)) then
195 lmin(ig)=l-1
196 endif
197 enddo
198 enddo
199
200 ! definition de l'entrainement des couches
201 do l=1, klev-1
202 do ig=1, ngrid
203 if (ztv(ig, l).gt.ztv(ig, l+1).and. &
204 l.ge.lmin(ig).and.l.le.lentr(ig)) then
205 entr_star(ig, l)=(ztv(ig, l)-ztv(ig, l+1))* &
206 (zlev(ig, l+1)-zlev(ig, l))
207 endif
208 enddo
209 enddo
210 ! pas de thermique si couches 1->5 stables
211 do ig=1, ngrid
212 if (lmin(ig).gt.5) then
213 do l=1, klev
214 entr_star(ig, l)=0.
215 enddo
216 endif
217 enddo
218 ! calcul de l entrainement total
219 do ig=1, ngrid
220 entr_star_tot(ig)=0.
221 enddo
222 do ig=1, ngrid
223 do k=1, klev
224 entr_star_tot(ig)=entr_star_tot(ig)+entr_star(ig, k)
225 enddo
226 enddo
227
228 print *, 'fin calcul entr_star'
229 do k=1, klev
230 do ig=1, ngrid
231 ztva(ig, k)=ztv(ig, k)
232 enddo
233 enddo
234
235 do k=1, klev+1
236 do ig=1, ngrid
237 zw2(ig, k)=0.
238 fmc(ig, k)=0.
239
240 f_star(ig, k)=0.
241
242 larg_cons(ig, k)=0.
243 larg_detr(ig, k)=0.
244 wa_moy(ig, k)=0.
245 enddo
246 enddo
247
248 do ig=1, ngrid
249 linter(ig)=1.
250 lmaxa(ig)=1
251 lmix(ig)=1
252 wmaxa(ig)=0.
253 enddo
254
255 do l=1, nlay-2
256 do ig=1, ngrid
257 if (ztv(ig, l).gt.ztv(ig, l+1) &
258 .and.entr_star(ig, l).gt.1.e-10 &
259 .and.zw2(ig, l).lt.1e-10) then
260 f_star(ig, l+1)=entr_star(ig, l)
261 !test:calcul de dteta
262 zw2(ig, l+1)=2.*RG*(ztv(ig, l)-ztv(ig, l+1))/ztv(ig, l+1) &
263 *(zlev(ig, l+1)-zlev(ig, l)) &
264 *0.4*pphi(ig, l)/(pphi(ig, l+1)-pphi(ig, l))
265 larg_detr(ig, l)=0.
266 else if ((zw2(ig, l).ge.1e-10).and. &
267 (f_star(ig, l)+entr_star(ig, l).gt.1.e-10)) then
268 f_star(ig, l+1)=f_star(ig, l)+entr_star(ig, l)
269 ztva(ig, l)=(f_star(ig, l)*ztva(ig, l-1)+entr_star(ig, l) &
270 *ztv(ig, l))/f_star(ig, l+1)
271 zw2(ig, l+1)=zw2(ig, l)*(f_star(ig, l)/f_star(ig, l+1))**2+ &
272 2.*RG*(ztva(ig, l)-ztv(ig, l))/ztv(ig, l) &
273 *(zlev(ig, l+1)-zlev(ig, l))
274 endif
275 ! determination de zmax continu par interpolation lineaire
276 if (zw2(ig, l+1).lt.0.) then
277 if (abs(zw2(ig, l+1)-zw2(ig, l)).lt.1e-10) then
278 print *, 'pb linter'
279 endif
280 linter(ig)=(l*(zw2(ig, l+1)-zw2(ig, l)) &
281 -zw2(ig, l))/(zw2(ig, l+1)-zw2(ig, l))
282 zw2(ig, l+1)=0.
283 lmaxa(ig)=l
284 else
285 if (zw2(ig, l+1).lt.0.) then
286 print *, 'pb1 zw2<0'
287 endif
288 wa_moy(ig, l+1)=sqrt(zw2(ig, l+1))
289 endif
290 if (wa_moy(ig, l+1).gt.wmaxa(ig)) then
291 ! lmix est le niveau de la couche ou w (wa_moy) est maximum
292 lmix(ig)=l+1
293 wmaxa(ig)=wa_moy(ig, l+1)
294 endif
295 enddo
296 enddo
297 print *, 'fin calcul zw2'
298
299 ! Calcul de la couche correspondant a la hauteur du thermique
300 do ig=1, ngrid
301 lmax(ig)=lentr(ig)
302 enddo
303 do ig=1, ngrid
304 do l=nlay, lentr(ig)+1, -1
305 if (zw2(ig, l).le.1.e-10) then
306 lmax(ig)=l-1
307 endif
308 enddo
309 enddo
310 ! pas de thermique si couches 1->5 stables
311 do ig=1, ngrid
312 if (lmin(ig).gt.5) then
313 lmax(ig)=1
314 lmin(ig)=1
315 endif
316 enddo
317
318 ! Determination de zw2 max
319 do ig=1, ngrid
320 wmax(ig)=0.
321 enddo
322
323 do l=1, nlay
324 do ig=1, ngrid
325 if (l.le.lmax(ig)) then
326 if (zw2(ig, l).lt.0.)then
327 print *, 'pb2 zw2<0'
328 endif
329 zw2(ig, l)=sqrt(zw2(ig, l))
330 wmax(ig)=max(wmax(ig), zw2(ig, l))
331 else
332 zw2(ig, l)=0.
333 endif
334 enddo
335 enddo
336
337 ! Longueur caracteristique correspondant a la hauteur des thermiques.
338 do ig=1, ngrid
339 zmax(ig)=0.
340 zlevinter(ig)=zlev(ig, 1)
341 enddo
342 do ig=1, ngrid
343 ! calcul de zlevinter
344 zlevinter(ig)=(zlev(ig, lmax(ig)+1)-zlev(ig, lmax(ig)))* &
345 linter(ig)+zlev(ig, lmax(ig))-lmax(ig)*(zlev(ig, lmax(ig)+1) &
346 -zlev(ig, lmax(ig)))
347 zmax(ig)=max(zmax(ig), zlevinter(ig)-zlev(ig, lmin(ig)))
348 enddo
349
350 print *, 'avant fermeture'
351 ! Fermeture, determination de f
352 do ig=1, ngrid
353 entr_star2(ig)=0.
354 enddo
355 do ig=1, ngrid
356 if (entr_star_tot(ig).LT.1.e-10) then
357 f(ig)=0.
358 else
359 do k=lmin(ig), lentr(ig)
360 entr_star2(ig)=entr_star2(ig)+entr_star(ig, k)**2 &
361 /(rho(ig, k)*(zlev(ig, k+1)-zlev(ig, k)))
362 enddo
363 ! Nouvelle fermeture
364 f(ig)=wmax(ig)/(max(500., zmax(ig))*r_aspect &
365 *entr_star2(ig))*entr_star_tot(ig)
366 endif
367 enddo
368 print *, 'apres fermeture'
369
370 ! Calcul de l'entrainement
371 do k=1, klev
372 do ig=1, ngrid
373 entr(ig, k)=f(ig)*entr_star(ig, k)
374 enddo
375 enddo
376 ! Calcul des flux
377 do ig=1, ngrid
378 do l=1, lmax(ig)-1
379 fmc(ig, l+1)=fmc(ig, l)+entr(ig, l)
380 enddo
381 enddo
382
383 ! determination de l'indice du debut de la mixed layer ou w decroit
384
385 ! calcul de la largeur de chaque ascendance dans le cas conservatif.
386 ! dans ce cas simple, on suppose que la largeur de l'ascendance provenant
387 ! d'une couche est \'egale \`a la hauteur de la couche alimentante.
388 ! La vitesse maximale dans l'ascendance est aussi prise comme estimation
389 ! de la vitesse d'entrainement horizontal dans la couche alimentante.
390
391 do l=2, nlay
392 do ig=1, ngrid
393 if (l.le.lmaxa(ig)) then
394 zw=max(wa_moy(ig, l), 1.e-10)
395 larg_cons(ig, l)=zmax(ig)*r_aspect &
396 *fmc(ig, l)/(rhobarz(ig, l)*zw)
397 endif
398 enddo
399 enddo
400
401 do l=2, nlay
402 do ig=1, ngrid
403 if (l.le.lmaxa(ig)) then
404 if ((l_mix*zlev(ig, l)).lt.0.)then
405 print *, 'pb l_mix*zlev<0'
406 endif
407 larg_detr(ig, l)=sqrt(l_mix*zlev(ig, l))
408 endif
409 enddo
410 enddo
411
412 ! calcul de la fraction de la maille concern\'ee par l'ascendance en tenant
413 ! compte de l'epluchage du thermique.
414
415 !CR def de zmix continu (profil parabolique des vitesses)
416 do ig=1, ngrid
417 if (lmix(ig).gt.1.) then
418 if (((zw2(ig, lmix(ig)-1)-zw2(ig, lmix(ig))) &
419 *((zlev(ig, lmix(ig)))-(zlev(ig, lmix(ig)+1))) &
420 -(zw2(ig, lmix(ig))-zw2(ig, lmix(ig)+1)) &
421 *((zlev(ig, lmix(ig)-1))-(zlev(ig, lmix(ig))))).gt.1e-10) &
422 then
423
424 zmix(ig)=((zw2(ig, lmix(ig)-1)-zw2(ig, lmix(ig))) &
425 *((zlev(ig, lmix(ig)))**2-(zlev(ig, lmix(ig)+1))**2) &
426 -(zw2(ig, lmix(ig))-zw2(ig, lmix(ig)+1)) &
427 *((zlev(ig, lmix(ig)-1))**2-(zlev(ig, lmix(ig)))**2)) &
428 /(2.*((zw2(ig, lmix(ig)-1)-zw2(ig, lmix(ig))) &
429 *((zlev(ig, lmix(ig)))-(zlev(ig, lmix(ig)+1))) &
430 -(zw2(ig, lmix(ig))-zw2(ig, lmix(ig)+1)) &
431 *((zlev(ig, lmix(ig)-1))-(zlev(ig, lmix(ig))))))
432 else
433 zmix(ig)=zlev(ig, lmix(ig))
434 print *, 'pb zmix'
435 endif
436 else
437 zmix(ig)=0.
438 endif
439
440 if ((zmax(ig)-zmix(ig)).lt.0.) then
441 zmix(ig)=0.99*zmax(ig)
442 endif
443 enddo
444
445 ! calcul du nouveau lmix correspondant
446 do ig=1, ngrid
447 do l=1, klev
448 if (zmix(ig).ge.zlev(ig, l).and. &
449 zmix(ig).lt.zlev(ig, l+1)) then
450 lmix(ig)=l
451 endif
452 enddo
453 enddo
454
455 do l=2, nlay
456 do ig=1, ngrid
457 if(larg_cons(ig, l).gt.1.) then
458 fraca(ig, l)=(larg_cons(ig, l)-larg_detr(ig, l)) &
459 /(r_aspect*zmax(ig))
460 fraca(ig, l)=max(fraca(ig, l), 0.)
461 fraca(ig, l)=min(fraca(ig, l), 0.5)
462 fracd(ig, l)=1.-fraca(ig, l)
463 fracc(ig, l)=larg_cons(ig, l)/(r_aspect*zmax(ig))
464 else
465 fraca(ig, l)=0.
466 fracc(ig, l)=0.
467 fracd(ig, l)=1.
468 endif
469 enddo
470 enddo
471 !CR: calcul de fracazmix
472 do ig=1, ngrid
473 fracazmix(ig)=(fraca(ig, lmix(ig)+1)-fraca(ig, lmix(ig)))/ &
474 (zlev(ig, lmix(ig)+1)-zlev(ig, lmix(ig)))*zmix(ig) &
475 +fraca(ig, lmix(ig))-zlev(ig, lmix(ig))*(fraca(ig, lmix(ig)+1) &
476 -fraca(ig, lmix(ig)))/(zlev(ig, lmix(ig)+1)-zlev(ig, lmix(ig)))
477 enddo
478
479 do l=2, nlay
480 do ig=1, ngrid
481 if(larg_cons(ig, l).gt.1.) then
482 if (l.gt.lmix(ig)) then
483 if (zmax(ig)-zmix(ig).lt.1.e-10) then
484 xxx(ig, l)=(lmaxa(ig)+1.-l)/(lmaxa(ig)+1.-lmix(ig))
485 else
486 xxx(ig, l)=(zmax(ig)-zlev(ig, l))/(zmax(ig)-zmix(ig))
487 endif
488 if (idetr.eq.0) then
489 fraca(ig, l)=fracazmix(ig)
490 else if (idetr.eq.1) then
491 fraca(ig, l)=fracazmix(ig)*xxx(ig, l)
492 else if (idetr.eq.2) then
493 fraca(ig, l)=fracazmix(ig)*(1.-(1.-xxx(ig, l))**2)
494 else
495 fraca(ig, l)=fracazmix(ig)*xxx(ig, l)**2
496 endif
497 fraca(ig, l)=max(fraca(ig, l), 0.)
498 fraca(ig, l)=min(fraca(ig, l), 0.5)
499 fracd(ig, l)=1.-fraca(ig, l)
500 fracc(ig, l)=larg_cons(ig, l)/(r_aspect*zmax(ig))
501 endif
502 endif
503 enddo
504 enddo
505
506 print *, 'fin calcul fraca'
507
508 ! Calcul de fracd, wd
509 ! somme wa - wd = 0
510
511 do ig=1, ngrid
512 fm(ig, 1)=0.
513 fm(ig, nlay+1)=0.
514 enddo
515
516 do l=2, nlay
517 do ig=1, ngrid
518 fm(ig, l)=fraca(ig, l)*wa_moy(ig, l)*rhobarz(ig, l)
519 if (entr(ig, l-1).lt.1e-10.and.fm(ig, l).gt.fm(ig, l-1) &
520 .and.l.gt.lmix(ig)) then
521 fm(ig, l)=fm(ig, l-1)
522 endif
523 enddo
524 do ig=1, ngrid
525 if(fracd(ig, l).lt.0.1) then
526 stop'fracd trop petit'
527 endif
528 enddo
529 enddo
530
531 do l=1, nlay
532 do ig=1, ngrid
533 masse(ig, l)=(pplev(ig, l)-pplev(ig, l+1))/RG
534 enddo
535 enddo
536
537 print *, '12 OK convect8'
538
539 ! calcul du transport vertical
540
541 !CR:redefinition du entr
542 do l=1, nlay
543 do ig=1, ngrid
544 detr(ig, l)=fm(ig, l)+entr(ig, l)-fm(ig, l+1)
545 if (detr(ig, l).lt.0.) then
546 entr(ig, l)=entr(ig, l)-detr(ig, l)
547 detr(ig, l)=0.
548 endif
549 enddo
550 enddo
551
552 if (w2di.eq.1) then
553 fm0=fm0+ptimestep*(fm-fm0)/tho
554 entr0=entr0+ptimestep*(entr-entr0)/tho
555 else
556 fm0=fm
557 entr0=entr
558 endif
559
560 if (1.eq.1) then
561 call dqthermcell(ngrid, nlay, ptimestep, fm0, entr0, masse &
562 , zh, zdhadj, zha)
563 call dqthermcell(ngrid, nlay, ptimestep, fm0, entr0, masse &
564 , zo, pdoadj, zoa)
565 else
566 call dqthermcell2(ngrid, nlay, ptimestep, fm0, entr0, masse, fraca &
567 , zh, zdhadj, zha)
568 call dqthermcell2(ngrid, nlay, ptimestep, fm0, entr0, masse, fraca &
569 , zo, pdoadj, zoa)
570 endif
571
572 if (1.eq.0) then
573 call dvthermcell2(ngrid, nlay, ptimestep, fm0, entr0, masse &
574 , fraca, zmax &
575 , zu, zv, pduadj, pdvadj, zua, zva)
576 else
577 call dqthermcell(ngrid, nlay, ptimestep, fm0, entr0, masse &
578 , zu, pduadj, zua)
579 call dqthermcell(ngrid, nlay, ptimestep, fm0, entr0, masse &
580 , zv, pdvadj, zva)
581 endif
582
583 do l=1, nlay
584 do ig=1, ngrid
585 zf=0.5*(fracc(ig, l)+fracc(ig, l+1))
586 zf2=zf/(1.-zf)
587 thetath2(ig, l)=zf2*(zha(ig, l)-zh(ig, l))**2
588 wth2(ig, l)=zf2*(0.5*(wa_moy(ig, l)+wa_moy(ig, l+1)))**2
589 enddo
590 enddo
591
592 do l=1, nlay
593 do ig=1, ngrid
594 pdtadj(ig, l)=zdhadj(ig, l)*zpspsk(ig, l)
595 enddo
596 enddo
597
598 end SUBROUTINE thermcell
599
600 end module thermcell_m

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.21