source: LMDZ6/trunk/libf/dyn3d/vlspltqs.F90 @ 5300

Last change on this file since 5300 was 5285, checked in by abarral, 4 days ago

As discussed internally, remove generic ONLY: ... for new _mod_h modules

  • Property copyright set to
    Name of program: LMDZ
    Creation date: 1984
    Version: LMDZ5
    License: CeCILL version 2
    Holder: Laboratoire de m\'et\'eorologie dynamique, CNRS, UMR 8539
    See the license file in the root directory
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.9 KB
Line 
1!
2! $Id: vlspltqs.F90 5285 2024-10-28 13:33:29Z abarral $
3!
4 SUBROUTINE vlspltqs ( q,pente_max,masse,w,pbaru,pbarv,pdt, &
5         p,pk,teta,iq             )
6   USE infotrac, ONLY: nqtot,tracers
7  !
8  ! Auteurs:   P.Le Van, F.Hourdin, F.Forget, F.Codron
9  !
10  !    ********************************************************************
11  !      Shema  d'advection " pseudo amont " .
12  !  + test sur humidite specifique: Q advecte< Qsat aval
13  !               (F. Codron, 10/99)
14  !    ********************************************************************
15  ! q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
16  !
17  ! pente_max facteur de limitation des pentes: 2 en general
18  !                                            0 pour un schema amont
19  ! pbaru,pbarv,w flux de masse en u ,v ,w
20  ! pdt pas de temps
21  !
22  ! teta temperature potentielle, p pression aux interfaces,
23  ! pk exner au milieu des couches necessaire pour calculer Qsat
24  !   --------------------------------------------------------------------
25
26  USE comconst_mod, ONLY: cpp
27  USE logic_mod, ONLY: adv_qsat_liq
28  USE dimensions_mod, ONLY: iim, jjm, llm, ndm
29USE paramet_mod_h
30IMPLICIT NONE
31  !
32
33
34
35  !
36  !   Arguments:
37  !   ----------
38  REAL :: masse(ip1jmp1,llm),pente_max
39  REAL :: pbaru( ip1jmp1,llm ),pbarv( ip1jm,llm)
40  REAL :: q(ip1jmp1,llm,nqtot)
41  REAL :: w(ip1jmp1,llm),pdt
42  REAL :: p(ip1jmp1,llmp1),teta(ip1jmp1,llm),pk(ip1jmp1,llm)
43  INTEGER :: iq ! CRisi
44  !
45  !  Local
46  !   ---------
47  !
48  INTEGER :: i,ij,l,j,ii
49  INTEGER :: ifils,iq2 ! CRisi
50  !
51  REAL :: qsat(ip1jmp1,llm)
52  REAL :: zm(ip1jmp1,llm,nqtot)
53  REAL :: mu(ip1jmp1,llm)
54  REAL :: mv(ip1jm,llm)
55  REAL :: mw(ip1jmp1,llm+1)
56  REAL :: zq(ip1jmp1,llm,nqtot)
57  REAL :: temps1,temps2,temps3
58  REAL :: zzpbar, zzw
59  LOGICAL :: testcpu
60  SAVE testcpu
61  SAVE temps1,temps2,temps3
62
63  REAL :: qmin,qmax
64  DATA qmin,qmax/0.,1.e33/
65  DATA testcpu/.false./
66  DATA temps1,temps2,temps3/0.,0.,0./
67
68  !--pour rapport de melange saturant--
69
70  REAL :: rtt,retv,r2es,r3les,r3ies,r4les,r4ies,play
71  REAL :: ptarg,pdelarg,foeew,zdelta
72  REAL :: tempe(ip1jmp1)
73
74  !    fonction psat(T)
75
76   FOEEW ( PTARG,PDELARG ) = EXP ( &
77         (R3LES*(1.-PDELARG)+R3IES*PDELARG) * (PTARG-RTT) &
78         / (PTARG-(R4LES*(1.-PDELARG)+R4IES*PDELARG)) )
79
80    r2es  = 380.11733
81    r3les = 17.269
82    r3ies = 21.875
83    r4les = 35.86
84    r4ies = 7.66
85    retv = 0.6077667
86    rtt  = 273.16
87
88  !-- Calcul de Qsat en chaque point
89  !-- approximation: au milieu des couches play(l)=(p(l)+p(l+1))/2
90  !   pour eviter une exponentielle.
91    DO l = 1, llm
92     DO ij = 1, ip1jmp1
93      tempe(ij) = teta(ij,l) * pk(ij,l) /cpp
94     ENDDO
95     DO ij = 1, ip1jmp1
96      IF (adv_qsat_liq) THEN
97         zdelta = 0.
98      ELSE
99         zdelta = MAX( 0., SIGN(1., rtt - tempe(ij)) )
100      ENDIF
101      play   = 0.5*(p(ij,l)+p(ij,l+1))
102      qsat(ij,l) = MIN(0.5, r2es* FOEEW(tempe(ij),zdelta) / play )
103      qsat(ij,l) = qsat(ij,l) / ( 1. - retv * qsat(ij,l) )
104     ENDDO
105    ENDDO
106
107   ! PRINT*,'Debut vlsplt version debug sans vlyqs'
108
109    zzpbar = 0.5 * pdt
110    zzw    = pdt
111  DO l=1,llm
112    DO ij = iip2,ip1jm
113        mu(ij,l)=pbaru(ij,l) * zzpbar
114     ENDDO
115     DO ij=1,ip1jm
116        mv(ij,l)=pbarv(ij,l) * zzpbar
117     ENDDO
118     DO ij=1,ip1jmp1
119        mw(ij,l)=w(ij,l) * zzw
120     ENDDO
121  ENDDO
122
123  DO ij=1,ip1jmp1
124     mw(ij,llm+1)=0.
125  ENDDO
126
127  CALL SCOPY(ijp1llm,q(1,1,iq),1,zq(1,1,iq),1)
128  CALL SCOPY(ijp1llm,masse,1,zm(1,1,iq),1)
129  do ifils=1,tracers(iq)%nqDescen
130    iq2=tracers(iq)%iqDescen(ifils)
131    CALL SCOPY(ijp1llm,q(1,1,iq2),1,zq(1,1,iq2),1)
132  enddo
133
134   ! call minmaxq(zq,qmin,qmax,'avant vlxqs     ')
135  call vlxqs(zq,pente_max,zm,mu,qsat,iq)
136
137  ! call minmaxq(zq,qmin,qmax,'avant vlyqs     ')
138
139  call vlyqs(zq,pente_max,zm,mv,qsat,iq)
140
141   ! call minmaxq(zq,qmin,qmax,'avant vlz     ')
142
143  call vlz(zq,pente_max,zm,mw,iq)
144
145  ! call minmaxq(zq,qmin,qmax,'avant vlyqs     ')
146  ! call minmaxq(zm,qmin,qmax,'M avant vlyqs     ')
147
148  call vlyqs(zq,pente_max,zm,mv,qsat,iq)
149
150  ! call minmaxq(zq,qmin,qmax,'avant vlxqs     ')
151  ! call minmaxq(zm,qmin,qmax,'M avant vlxqs     ')
152
153  call vlxqs(zq,pente_max,zm,mu,qsat,iq)
154
155  ! call minmaxq(zq,qmin,qmax,'apres vlxqs     ')
156  ! call minmaxq(zm,qmin,qmax,'M apres vlxqs     ')
157
158
159  DO l=1,llm
160     DO ij=1,ip1jmp1
161       q(ij,l,iq)=zq(ij,l,iq)
162     ENDDO
163     DO ij=1,ip1jm+1,iip1
164        q(ij+iim,l,iq)=q(ij,l,iq)
165     ENDDO
166  ENDDO
167  ! ! CRisi: aussi pour les fils
168  do ifils=1,tracers(iq)%nqDescen
169    iq2=tracers(iq)%iqDescen(ifils)
170    DO l=1,llm
171      DO ij=1,ip1jmp1
172        q(ij,l,iq2)=zq(ij,l,iq2)
173      ENDDO
174      DO ij=1,ip1jm+1,iip1
175        q(ij+iim,l,iq2)=q(ij,l,iq2)
176      ENDDO
177    ENDDO
178  enddo
179  ! !write(*,*) 'vlspltqs 183: fin de la routine'
180
181  RETURN
182END SUBROUTINE vlspltqs
183SUBROUTINE vlxqs(q,pente_max,masse,u_m,qsat,iq)
184  USE infotrac, ONLY : nqtot,tracers ! CRisi
185
186  !
187  ! Auteurs:   P.Le Van, F.Hourdin, F.Forget
188  !
189  !    ********************************************************************
190  ! Shema  d'advection " pseudo amont " .
191  !    ********************************************************************
192  !
193  !   --------------------------------------------------------------------
194  USE dimensions_mod, ONLY: iim, jjm, llm, ndm
195USE paramet_mod_h
196IMPLICIT NONE
197  !
198
199
200  !
201  !
202  !   Arguments:
203  !   ----------
204  REAL :: masse(ip1jmp1,llm,nqtot),pente_max
205  REAL :: u_m( ip1jmp1,llm )
206  REAL :: q(ip1jmp1,llm,nqtot)
207  REAL :: qsat(ip1jmp1,llm)
208  INTEGER :: iq ! CRisi
209  !
210  !  Local
211  !   ---------
212  !
213  INTEGER :: ij,l,j,i,iju,ijq,indu(ip1jmp1),niju
214  INTEGER :: n0,iadvplus(ip1jmp1,llm),nl(llm)
215  !
216  REAL :: new_m,zu_m,zdum(ip1jmp1,llm)
217  REAL :: dxq(ip1jmp1,llm),dxqu(ip1jmp1)
218  REAL :: zz(ip1jmp1)
219  REAL :: adxqu(ip1jmp1),dxqmax(ip1jmp1,llm)
220  REAL :: u_mq(ip1jmp1,llm)
221
222  ! ! CRisi
223  REAL :: masseq(ip1jmp1,llm,nqtot),Ratio(ip1jmp1,llm,nqtot)
224  INTEGER :: ifils,iq2 ! CRisi
225
226  Logical :: first,testcpu
227  SAVE first,testcpu
228
229  REAL :: SSUM
230  REAL :: temps0,temps1,temps2,temps3,temps4,temps5
231  SAVE temps0,temps1,temps2,temps3,temps4,temps5
232
233
234  DATA first,testcpu/.true.,.false./
235
236  IF(first) THEN
237     temps1=0.
238     temps2=0.
239     temps3=0.
240     temps4=0.
241     temps5=0.
242     first=.false.
243  ENDIF
244
245  !   calcul de la pente a droite et a gauche de la maille
246
247
248  IF (pente_max.gt.-1.e-5) THEN
249  ! IF (pente_max.gt.10) THEN
250
251  !   calcul des pentes avec limitation, Van Leer scheme I:
252  !   -----------------------------------------------------
253
254  !   calcul de la pente aux points u
255     DO l = 1, llm
256        DO ij=iip2,ip1jm-1
257           dxqu(ij)=q(ij+1,l,iq)-q(ij,l,iq)
258        ENDDO
259        DO ij=iip1+iip1,ip1jm,iip1
260           dxqu(ij)=dxqu(ij-iim)
261           ! sigu(ij)=sigu(ij-iim)
262        ENDDO
263
264        DO ij=iip2,ip1jm
265           adxqu(ij)=abs(dxqu(ij))
266        ENDDO
267
268  !   calcul de la pente maximum dans la maille en valeur absolue
269
270        DO ij=iip2+1,ip1jm
271           dxqmax(ij,l)=pente_max* &
272                 min(adxqu(ij-1),adxqu(ij))
273  ! limitation subtile
274  !    ,      min(adxqu(ij-1)/sigu(ij-1),adxqu(ij)/(1.-sigu(ij)))
275
276
277        ENDDO
278
279        DO ij=iip1+iip1,ip1jm,iip1
280           dxqmax(ij-iim,l)=dxqmax(ij,l)
281        ENDDO
282
283        DO ij=iip2+1,ip1jm
284#ifdef CRAY
285           dxq(ij,l)= &
286                 cvmgp(dxqu(ij-1)+dxqu(ij),0.,dxqu(ij-1)*dxqu(ij))
287#else
288           IF(dxqu(ij-1)*dxqu(ij).gt.0) THEN
289              dxq(ij,l)=dxqu(ij-1)+dxqu(ij)
290           ELSE
291  !   extremum local
292              dxq(ij,l)=0.
293           ENDIF
294#endif
295           dxq(ij,l)=0.5*dxq(ij,l)
296           dxq(ij,l)= &
297                 sign(min(abs(dxq(ij,l)),dxqmax(ij,l)),dxq(ij,l))
298        ENDDO
299
300     ENDDO ! l=1,llm
301
302  ELSE ! (pente_max.lt.-1.e-5)
303
304  !   Pentes produits:
305  !   ----------------
306
307     DO l = 1, llm
308        DO ij=iip2,ip1jm-1
309           dxqu(ij)=q(ij+1,l,iq)-q(ij,l,iq)
310        ENDDO
311        DO ij=iip1+iip1,ip1jm,iip1
312           dxqu(ij)=dxqu(ij-iim)
313        ENDDO
314
315        DO ij=iip2+1,ip1jm
316           zz(ij)=dxqu(ij-1)*dxqu(ij)
317           zz(ij)=zz(ij)+zz(ij)
318           IF(zz(ij).gt.0) THEN
319              dxq(ij,l)=zz(ij)/(dxqu(ij-1)+dxqu(ij))
320           ELSE
321  !   extremum local
322              dxq(ij,l)=0.
323           ENDIF
324        ENDDO
325
326     ENDDO
327
328  ENDIF ! (pente_max.lt.-1.e-5)
329
330  !   bouclage de la pente en iip1:
331  !   -----------------------------
332
333  DO l=1,llm
334     DO ij=iip1+iip1,ip1jm,iip1
335        dxq(ij-iim,l)=dxq(ij,l)
336     ENDDO
337
338     DO ij=1,ip1jmp1
339        iadvplus(ij,l)=0
340     ENDDO
341
342  ENDDO
343
344
345  !   calcul des flux a gauche et a droite
346
347#ifdef CRAY
348  !--pas encore modification sur Qsat
349  DO l=1,llm
350   DO ij=iip2,ip1jm-1
351      zdum(ij,l)=cvmgp(1.-u_m(ij,l)/masse(ij,l,iq), &
352            1.+u_m(ij,l)/masse(ij+1,l,iq), &
353            u_m(ij,l))
354      zdum(ij,l)=0.5*zdum(ij,l)
355      u_mq(ij,l)=cvmgp( &
356            q(ij,l,iq)+zdum(ij,l)*dxq(ij,l), &
357            q(ij+1,l,iq)-zdum(ij,l)*dxq(ij+1,l), &
358            u_m(ij,l))
359      u_mq(ij,l)=u_m(ij,l)*u_mq(ij,l)
360   ENDDO
361  ENDDO
362#else
363  !   on cumule le flux correspondant a toutes les mailles dont la masse
364  !   au travers de la paroi pENDant le pas de temps.
365  !   le rapport de melange de l'air advecte est min(q_vanleer, Qsat_downwind)
366  DO l=1,llm
367   DO ij=iip2,ip1jm-1
368      IF (u_m(ij,l).gt.0.) THEN
369         zdum(ij,l)=1.-u_m(ij,l)/masse(ij,l,iq)
370         u_mq(ij,l)=u_m(ij,l)* &
371               min(q(ij,l,iq)+0.5*zdum(ij,l)*dxq(ij,l),qsat(ij+1,l))
372      ELSE
373         zdum(ij,l)=1.+u_m(ij,l)/masse(ij+1,l,iq)
374         u_mq(ij,l)=u_m(ij,l)* &
375               min(q(ij+1,l,iq)-0.5*zdum(ij,l)*dxq(ij+1,l),qsat(ij,l))
376      ENDIF
377   ENDDO
378  ENDDO
379#endif
380
381
382  !   detection des points ou on advecte plus que la masse de la
383  !   maille
384  DO l=1,llm
385     DO ij=iip2,ip1jm-1
386        IF(zdum(ij,l).lt.0) THEN
387           iadvplus(ij,l)=1
388           u_mq(ij,l)=0.
389        ENDIF
390     ENDDO
391  ENDDO
392  DO l=1,llm
393   DO ij=iip1+iip1,ip1jm,iip1
394      iadvplus(ij,l)=iadvplus(ij-iim,l)
395   ENDDO
396  ENDDO
397
398
399
400  !   traitement special pour le cas ou on advecte en longitude plus que le
401  !   contenu de la maille.
402  !   cette partie est mal vectorisee.
403
404  !   pas d'influence de la pression saturante (pour l'instant)
405
406  !  calcul du nombre de maille sur lequel on advecte plus que la maille.
407
408  n0=0
409  DO l=1,llm
410     nl(l)=0
411     DO ij=iip2,ip1jm
412        nl(l)=nl(l)+iadvplus(ij,l)
413     ENDDO
414     n0=n0+nl(l)
415  ENDDO
416
417  IF(n0.gt.0) THEN
418  !cc      PRINT*,'Nombre de points pour lesquels on advect plus que le'
419  !cc     &       ,'contenu de la maille : ',n0
420
421     DO l=1,llm
422        IF(nl(l).gt.0) THEN
423           iju=0
424  !   indicage des mailles concernees par le traitement special
425           DO ij=iip2,ip1jm
426              IF(iadvplus(ij,l).eq.1.and.mod(ij,iip1).ne.0) THEN
427                 iju=iju+1
428                 indu(iju)=ij
429              ENDIF
430           ENDDO
431           niju=iju
432           ! PRINT*,'niju,nl',niju,nl(l)
433
434  !  traitement des mailles
435           DO iju=1,niju
436              ij=indu(iju)
437              j=(ij-1)/iip1+1
438              zu_m=u_m(ij,l)
439              u_mq(ij,l)=0.
440              IF(zu_m.gt.0.) THEN
441                 ijq=ij
442                 i=ijq-(j-1)*iip1
443  !   accumulation pour les mailles completements advectees
444                 do while(zu_m.gt.masse(ijq,l,iq))
445                    u_mq(ij,l)=u_mq(ij,l)+q(ijq,l,iq) &
446                          *masse(ijq,l,iq)
447                    zu_m=zu_m-masse(ijq,l,iq)
448                    i=mod(i-2+iim,iim)+1
449                    ijq=(j-1)*iip1+i
450                 ENDDO
451  !   ajout de la maille non completement advectee
452                 u_mq(ij,l)=u_mq(ij,l)+zu_m* &
453                       (q(ijq,l,iq)+0.5*(1.-zu_m/masse(ijq,l,iq)) &
454                       *dxq(ijq,l))
455              ELSE
456                 ijq=ij+1
457                 i=ijq-(j-1)*iip1
458  !   accumulation pour les mailles completements advectees
459                 do while(-zu_m.gt.masse(ijq,l,iq))
460                    u_mq(ij,l)=u_mq(ij,l)-q(ijq,l,iq) &
461                          *masse(ijq,l,iq)
462                    zu_m=zu_m+masse(ijq,l,iq)
463                    i=mod(i,iim)+1
464                    ijq=(j-1)*iip1+i
465                 ENDDO
466  !   ajout de la maille non completement advectee
467                 u_mq(ij,l)=u_mq(ij,l)+zu_m*(q(ijq,l,iq)- &
468                       0.5*(1.+zu_m/masse(ijq,l,iq))*dxq(ijq,l))
469              ENDIF
470           ENDDO
471        ENDIF
472     ENDDO
473  ENDIF  ! n0.gt.0
474
475
476
477  !   bouclage en latitude
478
479  DO l=1,llm
480    DO ij=iip1+iip1,ip1jm,iip1
481       u_mq(ij,l)=u_mq(ij-iim,l)
482    ENDDO
483  ENDDO
484
485  ! CRisi: appel récursif de l'advection sur les fils.
486  ! Il faut faire ça avant d'avoir mis à jour q et masse
487  ! !write(*,*) 'vlspltqs 326: iq,nqChildren(iq)=',iq,
488  ! &                 tracers(iq)%nqChildren
489
490  do ifils=1,tracers(iq)%nqDescen
491    iq2=tracers(iq)%iqDescen(ifils)
492    DO l=1,llm
493      DO ij=iip2,ip1jm
494      ! ! On a besoin de q et masse seulement entre iip2 et ip1jm
495        masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
496        Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
497      enddo
498    enddo
499  enddo
500  do ifils=1,tracers(iq)%nqChildren
501    iq2=tracers(iq)%iqDescen(ifils)
502    call vlx(Ratio,pente_max,masseq,u_mq,iq2)
503  enddo
504  ! end CRisi
505
506  !   calcul des tendances
507
508  DO l=1,llm
509     DO ij=iip2+1,ip1jm
510        new_m=masse(ij,l,iq)+u_m(ij-1,l)-u_m(ij,l)
511        q(ij,l,iq)=(q(ij,l,iq)*masse(ij,l,iq)+ &
512              u_mq(ij-1,l)-u_mq(ij,l)) &
513              /new_m
514        masse(ij,l,iq)=new_m
515     ENDDO
516  !   Modif Fred 22 03 96 correction d'un bug (les scopy ci-dessous)
517     DO ij=iip1+iip1,ip1jm,iip1
518        q(ij-iim,l,iq)=q(ij,l,iq)
519        masse(ij-iim,l,iq)=masse(ij,l,iq)
520     ENDDO
521  ENDDO
522
523  ! ! retablir les fils en rapport de melange par rapport a l'air:
524  ! ! On calcule q entre iip2+1,ip1jm -> on fait pareil pour ratio
525  ! ! puis on boucle en longitude
526  do ifils=1,tracers(iq)%nqDescen
527    iq2=tracers(iq)%iqDescen(ifils)
528    DO l=1,llm
529      DO ij=iip2+1,ip1jm
530        q(ij,l,iq2)=q(ij,l,iq)*Ratio(ij,l,iq2)
531      enddo
532      DO ij=iip1+iip1,ip1jm,iip1
533        q(ij-iim,l,iq2)=q(ij,l,iq2)
534      enddo
535    enddo
536  enddo
537
538  ! CALL SCOPY((jjm-1)*llm,q(iip1+iip1,1),iip1,q(iip2,1),iip1)
539  ! CALL SCOPY((jjm-1)*llm,masse(iip1+iip1,1),iip1,masse(iip2,1),iip1)
540
541
542  RETURN
543END SUBROUTINE vlxqs
544SUBROUTINE vlyqs(q,pente_max,masse,masse_adv_v,qsat,iq)
545  USE comgeom_mod_h
546  USE infotrac, ONLY : nqtot,tracers ! CRisi
547  !
548  ! Auteurs:   P.Le Van, F.Hourdin, F.Forget
549  !
550  !    ********************************************************************
551  ! Shema  d'advection " pseudo amont " .
552  !    ********************************************************************
553  ! q,masse_adv_v,w sont des arguments d'entree  pour le s-pg ....
554  !     qsat           est   un argument de sortie pour le s-pg ....
555  !
556  !
557  !   --------------------------------------------------------------------
558
559  USE comconst_mod, ONLY: pi
560
561  USE dimensions_mod, ONLY: iim, jjm, llm, ndm
562USE paramet_mod_h
563IMPLICIT NONE
564  !
565
566
567  !
568  !
569  !   Arguments:
570  !   ----------
571  REAL :: masse(ip1jmp1,llm,nqtot),pente_max
572  REAL :: masse_adv_v( ip1jm,llm)
573  REAL :: q(ip1jmp1,llm,nqtot)
574  REAL :: qsat(ip1jmp1,llm)
575  INTEGER :: iq ! CRisi
576  !
577  !  Local
578  !   ---------
579  !
580  INTEGER :: i,ij,l
581  !
582  REAL :: airej2,airejjm,airescb(iim),airesch(iim)
583  REAL :: dyq(ip1jmp1,llm),dyqv(ip1jm)
584  REAL :: adyqv(ip1jm),dyqmax(ip1jmp1)
585  REAL :: qbyv(ip1jm,llm)
586
587  REAL :: qpns,qpsn,dyn1,dys1,dyn2,dys2,newmasse,fn,fs
588  ! REAL newq,oldmasse
589  Logical :: first,testcpu
590  REAL :: temps0,temps1,temps2,temps3,temps4,temps5
591  SAVE temps0,temps1,temps2,temps3,temps4,temps5
592  SAVE first,testcpu
593
594  REAL :: convpn,convps,convmpn,convmps
595  REAL :: sinlon(iip1),sinlondlon(iip1)
596  REAL :: coslon(iip1),coslondlon(iip1)
597  SAVE sinlon,coslon,sinlondlon,coslondlon
598  SAVE airej2,airejjm
599
600  REAL :: masseq(ip1jmp1,llm,nqtot),Ratio(ip1jmp1,llm,nqtot) ! CRisi
601  INTEGER :: ifils,iq2 ! CRisi
602  !
603  !
604  REAL :: SSUM
605
606  DATA first,testcpu/.true.,.false./
607  DATA temps0,temps1,temps2,temps3,temps4,temps5/0.,0.,0.,0.,0.,0./
608
609  IF(first) THEN
610     PRINT*,'Shema  Amont nouveau  appele dans  Vanleer   '
611     first=.false.
612     do i=2,iip1
613        coslon(i)=cos(rlonv(i))
614        sinlon(i)=sin(rlonv(i))
615        coslondlon(i)=coslon(i)*(rlonu(i)-rlonu(i-1))/pi
616        sinlondlon(i)=sinlon(i)*(rlonu(i)-rlonu(i-1))/pi
617     ENDDO
618     coslon(1)=coslon(iip1)
619     coslondlon(1)=coslondlon(iip1)
620     sinlon(1)=sinlon(iip1)
621     sinlondlon(1)=sinlondlon(iip1)
622     airej2 = SSUM( iim, aire(iip2), 1 )
623     airejjm= SSUM( iim, aire(ip1jm -iim), 1 )
624  ENDIF
625
626  !
627
628
629  DO l = 1, llm
630  !
631  !   --------------------------------
632  !  CALCUL EN LATITUDE
633  !   --------------------------------
634
635  !   On commence par calculer la valeur du traceur moyenne sur le premier cercle
636  !   de latitude autour du pole (qpns pour le pole nord et qpsn pour
637  !    le pole nord) qui sera utilisee pour evaluer les pentes au pole.
638
639  DO i = 1, iim
640  airescb(i) = aire(i+ iip1) * q(i+ iip1,l,iq)
641  airesch(i) = aire(i+ ip1jm- iip1) * q(i+ ip1jm- iip1,l,iq)
642  ENDDO
643  qpns   = SSUM( iim,  airescb ,1 ) / airej2
644  qpsn   = SSUM( iim,  airesch ,1 ) / airejjm
645
646  !   calcul des pentes aux points v
647
648  DO ij=1,ip1jm
649     dyqv(ij)=q(ij,l,iq)-q(ij+iip1,l,iq)
650     adyqv(ij)=abs(dyqv(ij))
651  ENDDO
652
653  !   calcul des pentes aux points scalaires
654
655  DO ij=iip2,ip1jm
656     dyq(ij,l)=.5*(dyqv(ij-iip1)+dyqv(ij))
657     dyqmax(ij)=min(adyqv(ij-iip1),adyqv(ij))
658     dyqmax(ij)=pente_max*dyqmax(ij)
659  ENDDO
660
661  !   calcul des pentes aux poles
662
663  DO ij=1,iip1
664     dyq(ij,l)=qpns-q(ij+iip1,l,iq)
665     dyq(ip1jm+ij,l)=q(ip1jm+ij-iip1,l,iq)-qpsn
666  ENDDO
667
668  !   filtrage de la derivee
669  dyn1=0.
670  dys1=0.
671  dyn2=0.
672  dys2=0.
673  DO ij=1,iim
674     dyn1=dyn1+sinlondlon(ij)*dyq(ij,l)
675     dys1=dys1+sinlondlon(ij)*dyq(ip1jm+ij,l)
676     dyn2=dyn2+coslondlon(ij)*dyq(ij,l)
677     dys2=dys2+coslondlon(ij)*dyq(ip1jm+ij,l)
678  ENDDO
679  DO ij=1,iip1
680     dyq(ij,l)=dyn1*sinlon(ij)+dyn2*coslon(ij)
681     dyq(ip1jm+ij,l)=dys1*sinlon(ij)+dys2*coslon(ij)
682  ENDDO
683
684  !   calcul des pentes limites aux poles
685
686  fn=1.
687  fs=1.
688  DO ij=1,iim
689     IF(pente_max*adyqv(ij).lt.abs(dyq(ij,l))) THEN
690        fn=min(pente_max*adyqv(ij)/abs(dyq(ij,l)),fn)
691     ENDIF
692  IF(pente_max*adyqv(ij+ip1jm-iip1).lt.abs(dyq(ij+ip1jm,l))) THEN
693     fs=min(pente_max*adyqv(ij+ip1jm-iip1)/abs(dyq(ij+ip1jm,l)),fs)
694     ENDIF
695  ENDDO
696  DO ij=1,iip1
697     dyq(ij,l)=fn*dyq(ij,l)
698     dyq(ip1jm+ij,l)=fs*dyq(ip1jm+ij,l)
699  ENDDO
700
701  !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
702  !  En memoire de dIFferents tests sur la
703  !  limitation des pentes aux poles.
704  !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
705  ! PRINT*,dyq(1)
706  ! PRINT*,dyqv(iip1+1)
707  ! appn=abs(dyq(1)/dyqv(iip1+1))
708  ! PRINT*,dyq(ip1jm+1)
709  ! PRINT*,dyqv(ip1jm-iip1+1)
710  ! apps=abs(dyq(ip1jm+1)/dyqv(ip1jm-iip1+1))
711  ! DO ij=2,iim
712  !    appn=amax1(abs(dyq(ij)/dyqv(ij)),appn)
713  !    apps=amax1(abs(dyq(ip1jm+ij)/dyqv(ip1jm-iip1+ij)),apps)
714  ! ENDDO
715  ! appn=min(pente_max/appn,1.)
716  ! apps=min(pente_max/apps,1.)
717  !
718  !
719  !   cas ou on a un extremum au pole
720  !
721  ! IF(dyqv(ismin(iim,dyqv,1))*dyqv(ismax(iim,dyqv,1)).le.0.)
722  !    &   appn=0.
723  ! IF(dyqv(ismax(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1)*
724  !    &   dyqv(ismin(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1).le.0.)
725  !    &   apps=0.
726  !
727  !   limitation des pentes aux poles
728  ! DO ij=1,iip1
729  !    dyq(ij)=appn*dyq(ij)
730  !    dyq(ip1jm+ij)=apps*dyq(ip1jm+ij)
731  ! ENDDO
732  !
733  !   test
734  !  DO ij=1,iip1
735  !     dyq(iip1+ij)=0.
736  !     dyq(ip1jm+ij-iip1)=0.
737  !  ENDDO
738  !  DO ij=1,ip1jmp1
739  !     dyq(ij)=dyq(ij)*cos(rlatu((ij-1)/iip1+1))
740  !  ENDDO
741  !
742  ! changement 10 07 96
743  ! IF(dyqv(ismin(iim,dyqv,1))*dyqv(ismax(iim,dyqv,1)).le.0.)
744  !    &   THEN
745  !    DO ij=1,iip1
746  !       dyqmax(ij)=0.
747  !    ENDDO
748  ! ELSE
749  !    DO ij=1,iip1
750  !       dyqmax(ij)=pente_max*abs(dyqv(ij))
751  !    ENDDO
752  ! ENDIF
753  !
754  ! IF(dyqv(ismax(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1)*
755  !    & dyqv(ismin(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1).le.0.)
756  !    &THEN
757  !    DO ij=ip1jm+1,ip1jmp1
758  !       dyqmax(ij)=0.
759  !    ENDDO
760  ! ELSE
761  !    DO ij=ip1jm+1,ip1jmp1
762  !       dyqmax(ij)=pente_max*abs(dyqv(ij-iip1))
763  !    ENDDO
764  ! ENDIF
765  !   fin changement 10 07 96
766  !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
767
768  !   calcul des pentes limitees
769
770  DO ij=iip2,ip1jm
771     IF(dyqv(ij)*dyqv(ij-iip1).gt.0.) THEN
772        dyq(ij,l)=sign(min(abs(dyq(ij,l)),dyqmax(ij)),dyq(ij,l))
773     ELSE
774        dyq(ij,l)=0.
775     ENDIF
776  ENDDO
777
778  ENDDO
779
780  DO l=1,llm
781   DO ij=1,ip1jm
782     IF( masse_adv_v(ij,l).GT.0. ) THEN
783       qbyv(ij,l)= MIN( qsat(ij+iip1,l), q(ij+iip1,l,iq )  + &
784             dyq(ij+iip1,l)*0.5*(1.-masse_adv_v(ij,l) &
785             /masse(ij+iip1,l,iq)))
786     ELSE
787          qbyv(ij,l)= MIN( qsat(ij,l), q(ij,l,iq) - dyq(ij,l) * &
788                0.5*(1.+masse_adv_v(ij,l)/masse(ij,l,iq)) )
789     ENDIF
790      qbyv(ij,l) = masse_adv_v(ij,l)*qbyv(ij,l)
791   ENDDO
792  ENDDO
793
794
795  ! CRisi: appel récursif de l'advection sur les fils.
796  ! Il faut faire ça avant d'avoir mis à jour q et masse
797  ! !write(*,*) 'vlyqs 689: iq,nqChildren(iq)=',iq,
798  ! &              tracers(iq)%nqChildren
799
800  do ifils=1,tracers(iq)%nqDescen
801    iq2=tracers(iq)%iqDescen(ifils)
802    DO l=1,llm
803      DO ij=1,ip1jmp1
804        masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
805        Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
806      enddo
807    enddo
808  enddo
809  do ifils=1,tracers(iq)%nqChildren
810    iq2=tracers(iq)%iqDescen(ifils)
811    ! !write(*,*) 'vlyqs 783: appel rec de vly, iq2=',iq2
812    call vly(Ratio,pente_max,masseq,qbyv,iq2)
813  enddo
814
815  DO l=1,llm
816     DO ij=iip2,ip1jm
817        newmasse=masse(ij,l,iq) &
818              +masse_adv_v(ij,l)-masse_adv_v(ij-iip1,l)
819        q(ij,l,iq)=(q(ij,l,iq)*masse(ij,l,iq)+qbyv(ij,l) &
820              -qbyv(ij-iip1,l))/newmasse
821        masse(ij,l,iq)=newmasse
822     ENDDO
823  !.-. ancienne version
824     convpn=SSUM(iim,qbyv(1,l),1)/apoln
825     convmpn=ssum(iim,masse_adv_v(1,l),1)/apoln
826     DO ij = 1,iip1
827        newmasse=masse(ij,l,iq)+convmpn*aire(ij)
828        q(ij,l,iq)=(q(ij,l,iq)*masse(ij,l,iq)+convpn*aire(ij))/ &
829              newmasse
830        masse(ij,l,iq)=newmasse
831     ENDDO
832     convps  = -SSUM(iim,qbyv(ip1jm-iim,l),1)/apols
833     convmps = -SSUM(iim,masse_adv_v(ip1jm-iim,l),1)/apols
834     DO ij = ip1jm+1,ip1jmp1
835        newmasse=masse(ij,l,iq)+convmps*aire(ij)
836        q(ij,l,iq)=(q(ij,l,iq)*masse(ij,l,iq)+convps*aire(ij))/ &
837              newmasse
838        masse(ij,l,iq)=newmasse
839     ENDDO
840  !.-. fin ancienne version
841
842  !._. nouvelle version
843     ! convpn=SSUM(iim,qbyv(1,l),1)
844     ! convmpn=ssum(iim,masse_adv_v(1,l),1)
845     ! oldmasse=ssum(iim,masse(1,l),1)
846     ! newmasse=oldmasse+convmpn
847     ! newq=(q(1,l)*oldmasse+convpn)/newmasse
848     ! newmasse=newmasse/apoln
849     ! DO ij = 1,iip1
850     !    q(ij,l)=newq
851     !    masse(ij,l,iq)=newmasse*aire(ij)
852     ! ENDDO
853     ! convps=-SSUM(iim,qbyv(ip1jm-iim,l),1)
854     ! convmps=-ssum(iim,masse_adv_v(ip1jm-iim,l),1)
855     ! oldmasse=ssum(iim,masse(ip1jm-iim,l),1)
856     ! newmasse=oldmasse+convmps
857     ! newq=(q(ip1jmp1,l)*oldmasse+convps)/newmasse
858     ! newmasse=newmasse/apols
859     ! DO ij = ip1jm+1,ip1jmp1
860     !    q(ij,l)=newq
861     !    masse(ij,l,iq)=newmasse*aire(ij)
862     ! ENDDO
863  !._. fin nouvelle version
864  ENDDO
865
866  ! !write(*,*) 'vly 866'
867
868  ! retablir les fils en rapport de melange par rapport a l'air:
869  do ifils=1,tracers(iq)%nqDescen
870    iq2=tracers(iq)%iqDescen(ifils)
871    DO l=1,llm
872      DO ij=1,ip1jmp1
873        q(ij,l,iq2)=q(ij,l,iq)*Ratio(ij,l,iq2)
874      enddo
875    enddo
876  enddo
877  ! !write(*,*) 'vly 879'
878
879  RETURN
880END SUBROUTINE vlyqs
Note: See TracBrowser for help on using the repository browser.