/[lmdze]/trunk/Sources/phylmd/Thermcell/thermcell.f
ViewVC logotype

Contents of /trunk/Sources/phylmd/Thermcell/thermcell.f

Parent Directory Parent Directory | Revision Log Revision Log


Revision 188 - (show annotations)
Tue Mar 22 16:31:39 2016 UTC (8 years, 2 months ago) by guez
File size: 17396 byte(s)
Removed argument ncum of cv30_unsat, arguments nloc, ncum, nd, na of cv30_yield.

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

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.21