source: LMDZ6/trunk/libf/dyn3d/vlsplt.F @ 4114

Last change on this file since 4114 was 4064, checked in by dcugnet, 3 years ago
  • minor fixes (unused variables suppressed, comas after a WRITE() statement, etc.)
  • parser routines taken from version 7 of https://svn.lmd.jussieu.fr/tracers-parser
  • few changes in infotrac, and few fixes of (at least) the sequential version:
    • uadv and vadv were deallocated twice (fix was lost by mistake just before last commit)
    • in [( dum(im), im=1, nm)] implicit loops, ifort evaluates "dum(im)" even if nm==0,

resulting in a crash, "im" being unitialized.

  • 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: 30.1 KB
Line 
1c
2c $Id: vlsplt.F 4064 2022-01-25 18:14:39Z evignon $
3c
4
5      SUBROUTINE vlsplt(q,pente_max,masse,w,pbaru,pbarv,pdt,iq)
6      USE infotrac, ONLY: nqtot,tracers
7c
8c     Auteurs:   P.Le Van, F.Hourdin, F.Forget
9c
10c    ********************************************************************
11c     Shema  d'advection " pseudo amont " .
12c    ********************************************************************
13c     q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
14c
15c   pente_max facteur de limitation des pentes: 2 en general
16c                                               0 pour un schema amont
17c   pbaru,pbarv,w flux de masse en u ,v ,w
18c   pdt pas de temps
19c
20c   --------------------------------------------------------------------
21      IMPLICIT NONE
22c
23      include "dimensions.h"
24      include "paramet.h"
25
26c
27c   Arguments:
28c   ----------
29      REAL masse(ip1jmp1,llm),pente_max
30c      REAL masse(iip1,jjp1,llm),pente_max
31      REAL pbaru( ip1jmp1,llm ),pbarv( ip1jm,llm)
32      REAL q(ip1jmp1,llm,nqtot)
33c      REAL q(iip1,jjp1,llm)
34      REAL w(ip1jmp1,llm),pdt
35      INTEGER iq ! CRisi
36c
37c      Local
38c   ---------
39c
40      INTEGER ij,l
41c
42      REAL zm(ip1jmp1,llm,nqtot)
43      REAL mu(ip1jmp1,llm)
44      REAL mv(ip1jm,llm)
45      REAL mw(ip1jmp1,llm+1)
46      REAL zq(ip1jmp1,llm,nqtot)
47      REAL zzpbar, zzw
48      INTEGER ifils,iq2 ! CRisi
49
50      REAL qmin,qmax
51      DATA qmin,qmax/0.,1.e33/
52
53        zzpbar = 0.5 * pdt
54        zzw    = pdt
55      DO l=1,llm
56        DO ij = iip2,ip1jm
57            mu(ij,l)=pbaru(ij,l) * zzpbar
58         ENDDO
59         DO ij=1,ip1jm
60            mv(ij,l)=pbarv(ij,l) * zzpbar
61         ENDDO
62         DO ij=1,ip1jmp1
63            mw(ij,l)=w(ij,l) * zzw
64         ENDDO
65      ENDDO
66
67      DO ij=1,ip1jmp1
68         mw(ij,llm+1)=0.
69      ENDDO
70           
71      CALL SCOPY(ijp1llm,q(1,1,iq),1,zq(1,1,iq),1)
72      CALL SCOPY(ijp1llm,masse,1,zm(1,1,iq),1)
73       
74      do ifils=1,tracers(iq)%nqDescen
75        iq2=tracers(iq)%iqDescen(ifils)
76        CALL SCOPY(ijp1llm,q(1,1,iq2),1,zq(1,1,iq2),1)
77      enddo 
78
79cprint*,'Entree vlx1'
80c       call minmaxq(zq,qmin,qmax,'avant vlx     ')
81      call vlx(zq,pente_max,zm,mu,iq)
82cprint*,'Sortie vlx1'
83c       call minmaxq(zq,qmin,qmax,'apres vlx1    ')
84
85c print*,'Entree vly1'
86
87      call vly(zq,pente_max,zm,mv,iq)
88c       call minmaxq(zq,qmin,qmax,'apres vly1     ')
89cprint*,'Sortie vly1'
90      call vlz(zq,pente_max,zm,mw,iq)
91c       call minmaxq(zq,qmin,qmax,'apres vlz     ')
92
93
94      call vly(zq,pente_max,zm,mv,iq)
95c       call minmaxq(zq,qmin,qmax,'apres vly     ')
96
97
98      call vlx(zq,pente_max,zm,mu,iq)
99c       call minmaxq(zq,qmin,qmax,'apres vlx2    ')
100       
101
102      DO l=1,llm
103         DO ij=1,ip1jmp1
104           q(ij,l,iq)=zq(ij,l,iq)
105         ENDDO
106         DO ij=1,ip1jm+1,iip1
107            q(ij+iim,l,iq)=q(ij,l,iq)
108         ENDDO
109      ENDDO
110      ! CRisi: aussi pour les fils
111      do ifils=1,tracers(iq)%nqDescen
112        iq2=tracers(iq)%iqDescen(ifils)
113        DO l=1,llm
114          DO ij=1,ip1jmp1
115            q(ij,l,iq2)=zq(ij,l,iq2)
116          ENDDO
117          DO ij=1,ip1jm+1,iip1
118            q(ij+iim,l,iq2)=q(ij,l,iq2)
119          ENDDO
120        ENDDO
121      enddo
122
123      RETURN
124      END
125      RECURSIVE SUBROUTINE vlx(q,pente_max,masse,u_m,iq)
126      USE infotrac, ONLY : nqtot,tracers, ! CRisi
127     &                     qperemin,masseqmin,ratiomin ! MVals et CRisi
128
129c     Auteurs:   P.Le Van, F.Hourdin, F.Forget
130c
131c    ********************************************************************
132c     Shema  d'advection " pseudo amont " .
133c    ********************************************************************
134c     nq,iq,q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
135c
136c
137c   --------------------------------------------------------------------
138      IMPLICIT NONE
139c
140      include "dimensions.h"
141      include "paramet.h"
142      include "iniprint.h"
143c
144c
145c   Arguments:
146c   ----------
147      REAL masse(ip1jmp1,llm,nqtot),pente_max
148      REAL u_m( ip1jmp1,llm )
149      REAL q(ip1jmp1,llm,nqtot)
150      INTEGER iq ! CRisi
151c
152c      Local
153c   ---------
154c
155      INTEGER ij,l,j,i,iju,ijq,indu(ip1jmp1),niju
156      INTEGER n0,iadvplus(ip1jmp1,llm),nl(llm)
157c
158      REAL new_m,zu_m,zdum(ip1jmp1,llm)
159c      REAL sigu(ip1jmp1)
160      REAL dxq(ip1jmp1,llm),dxqu(ip1jmp1)
161      REAL zz(ip1jmp1)
162      REAL adxqu(ip1jmp1),dxqmax(ip1jmp1,llm)
163      REAL u_mq(ip1jmp1,llm)
164
165      ! CRisi
166      REAL masseq(ip1jmp1,llm,nqtot),Ratio(ip1jmp1,llm,nqtot)
167      INTEGER ifils,iq2 ! CRisi
168
169      Logical first
170      SAVE first
171      DATA first/.true./
172
173c   calcul de la pente a droite et a gauche de la maille
174
175
176      IF (pente_max.gt.-1.e-5) THEN
177c       IF (pente_max.gt.10) THEN
178
179c   calcul des pentes avec limitation, Van Leer scheme I:
180c   -----------------------------------------------------
181
182c   calcul de la pente aux points u
183         DO l = 1, llm
184            DO ij=iip2,ip1jm-1
185               dxqu(ij)=q(ij+1,l,iq)-q(ij,l,iq)
186c              IF(u_m(ij,l).lt.0.) stop'limx n admet pas les U<0'
187c              sigu(ij)=u_m(ij,l)/masse(ij,l,iq)
188            ENDDO
189            DO ij=iip1+iip1,ip1jm,iip1
190               dxqu(ij)=dxqu(ij-iim)
191c              sigu(ij)=sigu(ij-iim)
192            ENDDO
193
194            DO ij=iip2,ip1jm
195               adxqu(ij)=abs(dxqu(ij))
196            ENDDO
197
198c   calcul de la pente maximum dans la maille en valeur absolue
199
200            DO ij=iip2+1,ip1jm
201               dxqmax(ij,l)=pente_max*
202     ,      min(adxqu(ij-1),adxqu(ij))
203c limitation subtile
204c    ,      min(adxqu(ij-1)/sigu(ij-1),adxqu(ij)/(1.-sigu(ij)))
205         
206
207            ENDDO
208
209            DO ij=iip1+iip1,ip1jm,iip1
210               dxqmax(ij-iim,l)=dxqmax(ij,l)
211            ENDDO
212
213            DO ij=iip2+1,ip1jm
214#ifdef CRAY
215               dxq(ij,l)=
216     ,         cvmgp(dxqu(ij-1)+dxqu(ij),0.,dxqu(ij-1)*dxqu(ij))
217#else
218               IF(dxqu(ij-1)*dxqu(ij).gt.0) THEN
219                  dxq(ij,l)=dxqu(ij-1)+dxqu(ij)
220               ELSE
221c   extremum local
222                  dxq(ij,l)=0.
223               ENDIF
224#endif
225               dxq(ij,l)=0.5*dxq(ij,l)
226               dxq(ij,l)=
227     ,         sign(min(abs(dxq(ij,l)),dxqmax(ij,l)),dxq(ij,l))
228            ENDDO
229
230         ENDDO ! l=1,llm
231cprint*,'Ok calcul des pentes'
232
233      ELSE ! (pente_max.lt.-1.e-5)
234
235c   Pentes produits:
236c   ----------------
237
238         DO l = 1, llm
239            DO ij=iip2,ip1jm-1
240               dxqu(ij)=q(ij+1,l,iq)-q(ij,l,iq)
241            ENDDO
242            DO ij=iip1+iip1,ip1jm,iip1
243               dxqu(ij)=dxqu(ij-iim)
244            ENDDO
245
246            DO ij=iip2+1,ip1jm
247               zz(ij)=dxqu(ij-1)*dxqu(ij)
248               zz(ij)=zz(ij)+zz(ij)
249               IF(zz(ij).gt.0) THEN
250                  dxq(ij,l)=zz(ij)/(dxqu(ij-1)+dxqu(ij))
251               ELSE
252c   extremum local
253                  dxq(ij,l)=0.
254               ENDIF
255            ENDDO
256
257         ENDDO
258
259      ENDIF ! (pente_max.lt.-1.e-5)
260
261c   bouclage de la pente en iip1:
262c   -----------------------------
263
264      DO l=1,llm
265         DO ij=iip1+iip1,ip1jm,iip1
266            dxq(ij-iim,l)=dxq(ij,l)
267         ENDDO
268         DO ij=1,ip1jmp1
269            iadvplus(ij,l)=0
270         ENDDO
271
272      ENDDO
273
274c print*,'Bouclage en iip1'
275
276c   calcul des flux a gauche et a droite
277
278#ifdef CRAY
279
280      DO l=1,llm
281       DO ij=iip2,ip1jm-1
282          zdum(ij,l)=cvmgp(1.-u_m(ij,l)/masse(ij,l,iq),
283     ,                     1.+u_m(ij,l)/masse(ij+1,l,iq),
284     ,                     u_m(ij,l))
285          zdum(ij,l)=0.5*zdum(ij,l)
286          u_mq(ij,l)=cvmgp(
287     ,                q(ij,l,iq)+zdum(ij,l)*dxq(ij,l),
288     ,                q(ij+1,l,iq)-zdum(ij,l)*dxq(ij+1,l),
289     ,                u_m(ij,l))
290          u_mq(ij,l)=u_m(ij,l)*u_mq(ij,l)
291       ENDDO
292      ENDDO
293#else
294c   on cumule le flux correspondant a toutes les mailles dont la masse
295c   au travers de la paroi pENDant le pas de temps.
296cprint*,'Cumule ....'
297
298      DO l=1,llm
299       DO ij=iip2,ip1jm-1
300c       print*,'masse(',ij,')=',masse(ij,l,iq)
301          IF (u_m(ij,l).gt.0.) THEN
302             zdum(ij,l)=1.-u_m(ij,l)/masse(ij,l,iq)
303             u_mq(ij,l)=u_m(ij,l)*(q(ij,l,iq)+0.5*zdum(ij,l)*dxq(ij,l))
304          ELSE
305             zdum(ij,l)=1.+u_m(ij,l)/masse(ij+1,l,iq)
306             u_mq(ij,l)=u_m(ij,l)*(q(ij+1,l,iq)
307     &           -0.5*zdum(ij,l)*dxq(ij+1,l))
308          ENDIF
309       ENDDO
310      ENDDO
311#endif
312c       stop
313
314c       go to 9999
315c   detection des points ou on advecte plus que la masse de la
316c   maille
317      DO l=1,llm
318         DO ij=iip2,ip1jm-1
319            IF(zdum(ij,l).lt.0) THEN
320               iadvplus(ij,l)=1
321               u_mq(ij,l)=0.
322            ENDIF
323         ENDDO
324      ENDDO
325cprint*,'Ok test 1'
326      DO l=1,llm
327       DO ij=iip1+iip1,ip1jm,iip1
328          iadvplus(ij,l)=iadvplus(ij-iim,l)
329       ENDDO
330      ENDDO
331c print*,'Ok test 2'
332
333
334c   traitement special pour le cas ou on advecte en longitude plus que le
335c   contenu de la maille.
336c   cette partie est mal vectorisee.
337
338c  calcul du nombre de maille sur lequel on advecte plus que la maille.
339
340      n0=0
341      DO l=1,llm
342         nl(l)=0
343         DO ij=iip2,ip1jm
344            nl(l)=nl(l)+iadvplus(ij,l)
345         ENDDO
346         n0=n0+nl(l)
347      ENDDO
348
349      IF(n0.gt.0) THEN
350      if (prt_level > 2) PRINT *,
351     $        'Nombre de points pour lesquels on advect plus que le'
352     &       ,'contenu de la maille : ',n0
353
354         DO l=1,llm
355            IF(nl(l).gt.0) THEN
356               iju=0
357c   indicage des mailles concernees par le traitement special
358               DO ij=iip2,ip1jm
359                  IF(iadvplus(ij,l).eq.1.and.mod(ij,iip1).ne.0) THEN
360                     iju=iju+1
361                     indu(iju)=ij
362                  ENDIF
363               ENDDO
364               niju=iju
365c              PRINT*,'niju,nl',niju,nl(l)
366
367c  traitement des mailles
368               DO iju=1,niju
369                  ij=indu(iju)
370                  j=(ij-1)/iip1+1
371                  zu_m=u_m(ij,l)
372                  u_mq(ij,l)=0.
373                  IF(zu_m.gt.0.) THEN
374                     ijq=ij
375                     i=ijq-(j-1)*iip1
376c   accumulation pour les mailles completements advectees
377                     do while(zu_m.gt.masse(ijq,l,iq))
378                        u_mq(ij,l)=u_mq(ij,l)+q(ijq,l,iq)
379     &                          *masse(ijq,l,iq)
380                        zu_m=zu_m-masse(ijq,l,iq)
381                        i=mod(i-2+iim,iim)+1
382                        ijq=(j-1)*iip1+i
383                     ENDDO
384c   ajout de la maille non completement advectee
385                     u_mq(ij,l)=u_mq(ij,l)+zu_m*
386     &                  (q(ijq,l,iq)+0.5*(1.-zu_m/masse(ijq,l,iq))
387     &                  *dxq(ijq,l))
388                  ELSE
389                     ijq=ij+1
390                     i=ijq-(j-1)*iip1
391c   accumulation pour les mailles completements advectees
392                     do while(-zu_m.gt.masse(ijq,l,iq))
393                        u_mq(ij,l)=u_mq(ij,l)-q(ijq,l,iq)
394     &                          *masse(ijq,l,iq)
395                        zu_m=zu_m+masse(ijq,l,iq)
396                        i=mod(i,iim)+1
397                        ijq=(j-1)*iip1+i
398                     ENDDO
399c   ajout de la maille non completement advectee
400                     u_mq(ij,l)=u_mq(ij,l)+zu_m*(q(ijq,l,iq)-
401     &               0.5*(1.+zu_m/masse(ijq,l,iq))*dxq(ijq,l))
402                  ENDIF
403               ENDDO
404            ENDIF
405         ENDDO
406      ENDIF  ! n0.gt.0
407c9999    continue
408
409
410c   bouclage en latitude
411cprint*,'cvant bouclage en latitude'
412      DO l=1,llm
413        DO ij=iip1+iip1,ip1jm,iip1
414           u_mq(ij,l)=u_mq(ij-iim,l)
415        ENDDO
416      ENDDO
417
418! CRisi: appel récursif de l'advection sur les fils.
419! Il faut faire ça avant d'avoir mis à jour q et masse
420      !write(*,*) 'vlsplt 326: iq,nqDesc(iq)=',iq,tracers(iq)%nqDescen
421     
422      do ifils=1,tracers(iq)%nqDescen
423        iq2=tracers(iq)%iqDescen(ifils)
424        DO l=1,llm
425          DO ij=iip2,ip1jm
426            ! On a besoin de q et masse seulement entre iip2 et ip1jm
427            !masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
428            !Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
429            !Mvals: veiller a ce qu'on n'ait pas de denominateur nul
430            masseq(ij,l,iq2)=max(masse(ij,l,iq)*q(ij,l,iq),masseqmin)
431            if (q(ij,l,iq).gt.qperemin) then
432              Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
433            else
434              Ratio(ij,l,iq2)=ratiomin
435            endif
436          enddo   
437        enddo
438      enddo
439      do ifils=1,tracers(iq)%nqChilds
440        iq2=tracers(iq)%iqDescen(ifils)
441        call vlx(Ratio,pente_max,masseq,u_mq,iq2)
442      enddo
443! end CRisi
444
445
446c   calcul des tENDances
447
448      DO l=1,llm
449         DO ij=iip2+1,ip1jm
450            !MVals: veiller a ce qu'on ait pas de denominateur nul
451            new_m=max(masse(ij,l,iq)+u_m(ij-1,l)-u_m(ij,l),masseqmin)
452            q(ij,l,iq)=(q(ij,l,iq)*masse(ij,l,iq)+
453     &      u_mq(ij-1,l)-u_mq(ij,l))
454     &      /new_m
455            masse(ij,l,iq)=new_m
456         ENDDO
457c   ModIF Fred 22 03 96 correction d'un bug (les scopy ci-dessous)
458         DO ij=iip1+iip1,ip1jm,iip1
459            q(ij-iim,l,iq)=q(ij,l,iq)
460            masse(ij-iim,l,iq)=masse(ij,l,iq)
461         ENDDO
462      ENDDO
463
464      ! retablir les fils en rapport de melange par rapport a l'air:
465      ! On calcule q entre iip2+1,ip1jm -> on fait pareil pour ratio
466      ! puis on boucle en longitude
467      do ifils=1,tracers(iq)%nqDescen
468        iq2=tracers(iq)%iqDescen(ifils)
469        DO l=1,llm
470          DO ij=iip2+1,ip1jm
471            q(ij,l,iq2)=q(ij,l,iq)*Ratio(ij,l,iq2)           
472          enddo
473          DO ij=iip1+iip1,ip1jm,iip1
474             q(ij-iim,l,iq2)=q(ij,l,iq2)
475          enddo ! DO ij=ijb+iip1-1,ije,iip1
476        enddo !DO l=1,llm
477      enddo
478
479c     CALL SCOPY((jjm-1)*llm,q(iip1+iip1,1),iip1,q(iip2,1),iip1)
480c     CALL SCOPY((jjm-1)*llm,masse(iip1+iip1,1),iip1,masse(iip2,1),iip1)
481
482
483      RETURN
484      END
485      RECURSIVE SUBROUTINE vly(q,pente_max,masse,masse_adv_v,iq)
486      USE infotrac, ONLY : nqtot,tracers, ! CRisi
487     &                     qperemin,masseqmin,ratiomin ! MVals et CRisi
488c
489c     Auteurs:   P.Le Van, F.Hourdin, F.Forget
490c
491c    ********************************************************************
492c     Shema  d'advection " pseudo amont " .
493c    ********************************************************************
494c     q,masse_adv_v,w sont des arguments d'entree  pour le s-pg ....
495c     dq               sont des arguments de sortie pour le s-pg ....
496c
497c
498c   --------------------------------------------------------------------
499      USE comconst_mod, ONLY: pi
500      IMPLICIT NONE
501c
502      include "dimensions.h"
503      include "paramet.h"
504      include "comgeom.h"
505c
506c
507c   Arguments:
508c   ----------
509      REAL masse(ip1jmp1,llm,nqtot),pente_max
510      REAL masse_adv_v( ip1jm,llm)
511      REAL q(ip1jmp1,llm,nqtot)
512      INTEGER iq ! CRisi
513c
514c      Local
515c   ---------
516c
517      INTEGER i,ij,l
518c
519      REAL airej2,airejjm,airescb(iim),airesch(iim)
520      REAL dyq(ip1jmp1,llm),dyqv(ip1jm)
521      REAL adyqv(ip1jm),dyqmax(ip1jmp1)
522      REAL qbyv(ip1jm,llm)
523
524      REAL qpns,qpsn,dyn1,dys1,dyn2,dys2,newmasse,fn,fs
525c     REAL appn apps
526c     REAL newq,oldmasse
527      LOGICAL first
528      SAVE first
529
530      REAL convpn,convps,convmpn,convmps
531      real massepn,masseps,qpn,qps
532      REAL sinlon(iip1),sinlondlon(iip1)
533      REAL coslon(iip1),coslondlon(iip1)
534      SAVE sinlon,coslon,sinlondlon,coslondlon
535      SAVE airej2,airejjm
536
537      REAL masseq(ip1jmp1,llm,nqtot),Ratio(ip1jmp1,llm,nqtot) ! CRisi
538      INTEGER ifils,iq2 ! CRisi
539
540c
541c
542      REAL      SSUM
543
544      DATA first/.true./
545
546      !write(*,*) 'vly 578: entree, iq=',iq
547
548      IF(first) THEN
549         PRINT*,'Shema  Amont nouveau  appele dans  Vanleer   '
550         first=.false.
551         do i=2,iip1
552            coslon(i)=cos(rlonv(i))
553            sinlon(i)=sin(rlonv(i))
554            coslondlon(i)=coslon(i)*(rlonu(i)-rlonu(i-1))/pi
555            sinlondlon(i)=sinlon(i)*(rlonu(i)-rlonu(i-1))/pi
556         ENDDO
557         coslon(1)=coslon(iip1)
558         coslondlon(1)=coslondlon(iip1)
559         sinlon(1)=sinlon(iip1)
560         sinlondlon(1)=sinlondlon(iip1)
561         airej2 = SSUM( iim, aire(iip2), 1 )
562         airejjm= SSUM( iim, aire(ip1jm -iim), 1 )
563      ENDIF
564
565c
566cPRINT*,'CALCUL EN LATITUDE'
567
568      DO l = 1, llm
569c
570c   --------------------------------
571c      CALCUL EN LATITUDE
572c   --------------------------------
573
574c   On commence par calculer la valeur du traceur moyenne sur le premier cercle
575c   de latitude autour du pole (qpns pour le pole nord et qpsn pour
576c    le pole nord) qui sera utilisee pour evaluer les pentes au pole.
577
578      DO i = 1, iim
579      airescb(i) = aire(i+ iip1) * q(i+ iip1,l,iq)
580      airesch(i) = aire(i+ ip1jm- iip1) * q(i+ ip1jm- iip1,l,iq)
581      ENDDO
582      qpns   = SSUM( iim,  airescb ,1 ) / airej2
583      qpsn   = SSUM( iim,  airesch ,1 ) / airejjm
584
585c   calcul des pentes aux points v
586
587      DO ij=1,ip1jm
588         dyqv(ij)=q(ij,l,iq)-q(ij+iip1,l,iq)
589         adyqv(ij)=abs(dyqv(ij))
590      ENDDO
591
592c   calcul des pentes aux points scalaires
593
594      DO ij=iip2,ip1jm
595         dyq(ij,l)=.5*(dyqv(ij-iip1)+dyqv(ij))
596         dyqmax(ij)=min(adyqv(ij-iip1),adyqv(ij))
597         dyqmax(ij)=pente_max*dyqmax(ij)
598      ENDDO
599
600c   calcul des pentes aux poles
601
602      DO ij=1,iip1
603         dyq(ij,l)=qpns-q(ij+iip1,l,iq)
604         dyq(ip1jm+ij,l)=q(ip1jm+ij-iip1,l,iq)-qpsn
605      ENDDO
606
607c   filtrage de la derivee
608      dyn1=0.
609      dys1=0.
610      dyn2=0.
611      dys2=0.
612      DO ij=1,iim
613         dyn1=dyn1+sinlondlon(ij)*dyq(ij,l)
614         dys1=dys1+sinlondlon(ij)*dyq(ip1jm+ij,l)
615         dyn2=dyn2+coslondlon(ij)*dyq(ij,l)
616         dys2=dys2+coslondlon(ij)*dyq(ip1jm+ij,l)
617      ENDDO
618      DO ij=1,iip1
619         dyq(ij,l)=dyn1*sinlon(ij)+dyn2*coslon(ij)
620         dyq(ip1jm+ij,l)=dys1*sinlon(ij)+dys2*coslon(ij)
621      ENDDO
622
623c   calcul des pentes limites aux poles
624
625      goto 8888
626      fn=1.
627      fs=1.
628      DO ij=1,iim
629         IF(pente_max*adyqv(ij).lt.abs(dyq(ij,l))) THEN
630            fn=min(pente_max*adyqv(ij)/abs(dyq(ij,l)),fn)
631         ENDIF
632      IF(pente_max*adyqv(ij+ip1jm-iip1).lt.abs(dyq(ij+ip1jm,l))) THEN
633         fs=min(pente_max*adyqv(ij+ip1jm-iip1)/abs(dyq(ij+ip1jm,l)),fs)
634         ENDIF
635      ENDDO
636      DO ij=1,iip1
637         dyq(ij,l)=fn*dyq(ij,l)
638         dyq(ip1jm+ij,l)=fs*dyq(ip1jm+ij,l)
639      ENDDO
6408888    continue
641      DO ij=1,iip1
642         dyq(ij,l)=0.
643         dyq(ip1jm+ij,l)=0.
644      ENDDO
645
646CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
647C  En memoire de dIFferents tests sur la
648C  limitation des pentes aux poles.
649CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
650C     PRINT*,dyq(1)
651C     PRINT*,dyqv(iip1+1)
652C     appn=abs(dyq(1)/dyqv(iip1+1))
653C     PRINT*,dyq(ip1jm+1)
654C     PRINT*,dyqv(ip1jm-iip1+1)
655C     apps=abs(dyq(ip1jm+1)/dyqv(ip1jm-iip1+1))
656C     DO ij=2,iim
657C        appn=amax1(abs(dyq(ij)/dyqv(ij)),appn)
658C        apps=amax1(abs(dyq(ip1jm+ij)/dyqv(ip1jm-iip1+ij)),apps)
659C     ENDDO
660C     appn=min(pente_max/appn,1.)
661C     apps=min(pente_max/apps,1.)
662C
663C
664C   cas ou on a un extremum au pole
665C
666C     IF(dyqv(ismin(iim,dyqv,1))*dyqv(ismax(iim,dyqv,1)).le.0.)
667C    &   appn=0.
668C     IF(dyqv(ismax(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1)*
669C    &   dyqv(ismin(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1).le.0.)
670C    &   apps=0.
671C
672C   limitation des pentes aux poles
673C     DO ij=1,iip1
674C        dyq(ij)=appn*dyq(ij)
675C        dyq(ip1jm+ij)=apps*dyq(ip1jm+ij)
676C     ENDDO
677C
678C   test
679C      DO ij=1,iip1
680C         dyq(iip1+ij)=0.
681C         dyq(ip1jm+ij-iip1)=0.
682C      ENDDO
683C      DO ij=1,ip1jmp1
684C         dyq(ij)=dyq(ij)*cos(rlatu((ij-1)/iip1+1))
685C      ENDDO
686C
687C changement 10 07 96
688C     IF(dyqv(ismin(iim,dyqv,1))*dyqv(ismax(iim,dyqv,1)).le.0.)
689C    &   THEN
690C        DO ij=1,iip1
691C           dyqmax(ij)=0.
692C        ENDDO
693C     ELSE
694C        DO ij=1,iip1
695C           dyqmax(ij)=pente_max*abs(dyqv(ij))
696C        ENDDO
697C     ENDIF
698C
699C     IF(dyqv(ismax(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1)*
700C    & dyqv(ismin(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1).le.0.)
701C    &THEN
702C        DO ij=ip1jm+1,ip1jmp1
703C           dyqmax(ij)=0.
704C        ENDDO
705C     ELSE
706C        DO ij=ip1jm+1,ip1jmp1
707C           dyqmax(ij)=pente_max*abs(dyqv(ij-iip1))
708C        ENDDO
709C     ENDIF
710C   fin changement 10 07 96
711CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
712
713c   calcul des pentes limitees
714
715      DO ij=iip2,ip1jm
716         IF(dyqv(ij)*dyqv(ij-iip1).gt.0.) THEN
717            dyq(ij,l)=sign(min(abs(dyq(ij,l)),dyqmax(ij)),dyq(ij,l))
718         ELSE
719            dyq(ij,l)=0.
720         ENDIF
721      ENDDO
722
723      ENDDO
724
725      !write(*,*) 'vly 756'
726      DO l=1,llm
727       DO ij=1,ip1jm
728          IF(masse_adv_v(ij,l).gt.0) THEN
729              qbyv(ij,l)=q(ij+iip1,l,iq)+dyq(ij+iip1,l)*
730     ,                   0.5*(1.-masse_adv_v(ij,l)
731     ,                   /masse(ij+iip1,l,iq))
732          ELSE
733              qbyv(ij,l)=q(ij,l,iq)-dyq(ij,l)*
734     ,                   0.5*(1.+masse_adv_v(ij,l)
735     ,                   /masse(ij,l,iq))
736          ENDIF
737          qbyv(ij,l)=masse_adv_v(ij,l)*qbyv(ij,l)
738       ENDDO
739      ENDDO
740
741! CRisi: appel récursif de l'advection sur les fils.
742! Il faut faire ça avant d'avoir mis à jour q et masse
743      !write(*,*) 'vly 689: iq,nqDesc(iq)=',iq,tracers(iq)%nqDescen
744   
745      do ifils=1,tracers(iq)%nqDescen
746        iq2=tracers(iq)%iqDescen(ifils)
747        DO l=1,llm
748          DO ij=1,ip1jmp1
749            ! attention, chaque fils doit avoir son masseq, sinon, le 1er
750            ! fils ecrase le masseq de ses freres.
751            !masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
752            !Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)     
753            !MVals: veiller a ce qu'on n'ait pas de denominateur nul
754            masseq(ij,l,iq2)=max(masse(ij,l,iq)*q(ij,l,iq),masseqmin)
755            if (q(ij,l,iq).gt.qperemin) then
756              Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
757            else
758              Ratio(ij,l,iq2)=ratiomin
759            endif
760          enddo   
761        enddo
762      enddo
763
764      do ifils=1,tracers(iq)%nqDescen
765        iq2=tracers(iq)%iqDescen(ifils)
766        call vly(Ratio,pente_max,masseq,qbyv,iq2)
767      enddo
768
769      DO l=1,llm
770         DO ij=iip2,ip1jm
771            newmasse=masse(ij,l,iq)
772     &      +masse_adv_v(ij,l)-masse_adv_v(ij-iip1,l)
773            q(ij,l,iq)=(q(ij,l,iq)*masse(ij,l,iq)+qbyv(ij,l)
774     &         -qbyv(ij-iip1,l))/newmasse
775            masse(ij,l,iq)=newmasse
776         ENDDO
777c.-. ancienne version
778c        convpn=SSUM(iim,qbyv(1,l),1)/apoln
779c        convmpn=ssum(iim,masse_adv_v(1,l),1)/apoln
780
781         convpn=SSUM(iim,qbyv(1,l),1)
782         convmpn=ssum(iim,masse_adv_v(1,l),1)
783         massepn=ssum(iim,masse(1,l,iq),1)
784         qpn=0.
785         do ij=1,iim
786            qpn=qpn+masse(ij,l,iq)*q(ij,l,iq)
787         enddo
788         qpn=(qpn+convpn)/(massepn+convmpn)
789         do ij=1,iip1
790            q(ij,l,iq)=qpn
791         enddo
792
793c        convps=-SSUM(iim,qbyv(ip1jm-iim,l),1)/apols
794c        convmps=-ssum(iim,masse_adv_v(ip1jm-iim,l),1)/apols
795
796         convps=-SSUM(iim,qbyv(ip1jm-iim,l),1)
797         convmps=-ssum(iim,masse_adv_v(ip1jm-iim,l),1)
798         masseps=ssum(iim, masse(ip1jm+1,l,iq),1)
799         qps=0.
800         do ij = ip1jm+1,ip1jmp1-1
801            qps=qps+masse(ij,l,iq)*q(ij,l,iq)
802         enddo
803         qps=(qps+convps)/(masseps+convmps)
804         do ij=ip1jm+1,ip1jmp1
805            q(ij,l,iq)=qps
806         enddo
807
808c.-. fin ancienne version
809
810c._. nouvelle version
811c        convpn=SSUM(iim,qbyv(1,l),1)
812c        convmpn=ssum(iim,masse_adv_v(1,l),1)
813c        oldmasse=ssum(iim,masse(1,l),1)
814c        newmasse=oldmasse+convmpn
815c        newq=(q(1,l)*oldmasse+convpn)/newmasse
816c        newmasse=newmasse/apoln
817c        DO ij = 1,iip1
818c           q(ij,l)=newq
819c           masse(ij,l,iq)=newmasse*aire(ij)
820c        ENDDO
821c        convps=-SSUM(iim,qbyv(ip1jm-iim,l),1)
822c        convmps=-ssum(iim,masse_adv_v(ip1jm-iim,l),1)
823c        oldmasse=ssum(iim,masse(ip1jm-iim,l),1)
824c        newmasse=oldmasse+convmps
825c        newq=(q(ip1jmp1,l)*oldmasse+convps)/newmasse
826c        newmasse=newmasse/apols
827c        DO ij = ip1jm+1,ip1jmp1
828c           q(ij,l)=newq
829c           masse(ij,l,iq)=newmasse*aire(ij)
830c        ENDDO
831c._. fin nouvelle version
832      ENDDO
833 
834! retablir les fils en rapport de melange par rapport a l'air:
835      do ifils=1,tracers(iq)%nqDescen
836        iq2=tracers(iq)%iqDescen(ifils)
837        DO l=1,llm
838          DO ij=1,ip1jmp1
839            q(ij,l,iq2)=q(ij,l,iq)*Ratio(ij,l,iq2)           
840          enddo
841        enddo
842      enddo
843
844      !write(*,*) 'vly 853: sortie'
845
846      RETURN
847      END
848      RECURSIVE SUBROUTINE vlz(q,pente_max,masse,w,iq)
849      USE infotrac, ONLY : nqtot,tracers, ! CRisi
850     &                     qperemin,masseqmin,ratiomin ! MVals et CRisi
851c
852c     Auteurs:   P.Le Van, F.Hourdin, F.Forget
853c
854c    ********************************************************************
855c     Shema  d'advection " pseudo amont " .
856c    ********************************************************************
857c    q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
858c     dq               sont des arguments de sortie pour le s-pg ....
859c
860c
861c   --------------------------------------------------------------------
862      IMPLICIT NONE
863c
864      include "dimensions.h"
865      include "paramet.h"
866c
867c
868c   Arguments:
869c   ----------
870      REAL masse(ip1jmp1,llm,nqtot),pente_max
871      REAL q(ip1jmp1,llm,nqtot)
872      REAL w(ip1jmp1,llm+1)
873      INTEGER iq
874c
875c      Local
876c   ---------
877c
878      INTEGER ij,l
879c
880      REAL wq(ip1jmp1,llm+1),newmasse
881
882      REAL dzq(ip1jmp1,llm),dzqw(ip1jmp1,llm),adzqw(ip1jmp1,llm),dzqmax
883      REAL sigw
884
885      REAL masseq(ip1jmp1,llm,nqtot),Ratio(ip1jmp1,llm,nqtot) ! CRisi
886      INTEGER ifils,iq2 ! CRisi
887
888      LOGICAL testcpu
889      SAVE testcpu
890
891#ifdef BIDON
892      REAL temps0,temps1,second
893      SAVE temps0,temps1
894
895      DATA testcpu/.false./
896      DATA temps0,temps1/0.,0./
897#endif
898
899c    On oriente tout dans le sens de la pression c'est a dire dans le
900c    sens de W
901
902      !write(*,*) 'vlz 923: entree'
903
904#ifdef BIDON
905      IF(testcpu) THEN
906         temps0=second(0.)
907      ENDIF
908#endif
909      DO l=2,llm
910         DO ij=1,ip1jmp1
911            dzqw(ij,l)=q(ij,l-1,iq)-q(ij,l,iq)
912            adzqw(ij,l)=abs(dzqw(ij,l))
913         ENDDO
914      ENDDO
915
916      DO l=2,llm-1
917         DO ij=1,ip1jmp1
918#ifdef CRAY
919            dzq(ij,l)=0.5*
920     ,      cvmgp(dzqw(ij,l)+dzqw(ij,l+1),0.,dzqw(ij,l)*dzqw(ij,l+1))
921#else
922            IF(dzqw(ij,l)*dzqw(ij,l+1).gt.0.) THEN
923                dzq(ij,l)=0.5*(dzqw(ij,l)+dzqw(ij,l+1))
924            ELSE
925                dzq(ij,l)=0.
926            ENDIF
927#endif
928            dzqmax=pente_max*min(adzqw(ij,l),adzqw(ij,l+1))
929            dzq(ij,l)=sign(min(abs(dzq(ij,l)),dzqmax),dzq(ij,l))
930         ENDDO
931      ENDDO
932
933      !write(*,*) 'vlz 954'
934      DO ij=1,ip1jmp1
935         dzq(ij,1)=0.
936         dzq(ij,llm)=0.
937      ENDDO
938
939#ifdef BIDON
940      IF(testcpu) THEN
941         temps1=temps1+second(0.)-temps0
942      ENDIF
943#endif
944c ---------------------------------------------------------------
945c   .... calcul des termes d'advection verticale  .......
946c ---------------------------------------------------------------
947
948c calcul de  - d( q   * w )/ d(sigma)    qu'on ajoute a  dq pour calculer dq
949
950       !write(*,*) 'vlz 969'
951       DO l = 1,llm-1
952         do  ij = 1,ip1jmp1
953          IF(w(ij,l+1).gt.0.) THEN
954             sigw=w(ij,l+1)/masse(ij,l+1,iq)
955             wq(ij,l+1)=w(ij,l+1)*(q(ij,l+1,iq)
956     &           +0.5*(1.-sigw)*dzq(ij,l+1))
957          ELSE
958             sigw=w(ij,l+1)/masse(ij,l,iq)
959             wq(ij,l+1)=w(ij,l+1)*(q(ij,l,iq)-0.5*(1.+sigw)*dzq(ij,l))
960          ENDIF
961         ENDDO
962       ENDDO
963
964       DO ij=1,ip1jmp1
965          wq(ij,llm+1)=0.
966          wq(ij,1)=0.
967       ENDDO
968
969! CRisi: appel récursif de l'advection sur les fils.
970! Il faut faire ça avant d'avoir mis à jour q et masse
971      !write(*,*) 'vlsplt 942: iq,nqChilds(iq)=',iq,nqChilds(iq)
972      do ifils=1,tracers(iq)%nqDescen
973        iq2=tracers(iq)%iqDescen(ifils)
974        DO l=1,llm
975          DO ij=1,ip1jmp1
976            !masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
977            !Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)       
978            !MVals: veiller a ce qu'on n'ait pas de denominateur nul
979            masseq(ij,l,iq2)=max(masse(ij,l,iq)*q(ij,l,iq),masseqmin)
980            if (q(ij,l,iq).gt.qperemin) then
981              Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
982            else
983              Ratio(ij,l,iq2)=ratiomin
984            endif     
985          enddo   
986        enddo
987      enddo
988       
989      do ifils=1,tracers(iq)%nqChilds
990        iq2=tracers(iq)%iqDescen(ifils)
991        call vlz(Ratio,pente_max,masseq,wq,iq2)
992      enddo
993! end CRisi 
994
995      DO l=1,llm
996         DO ij=1,ip1jmp1
997            newmasse=masse(ij,l,iq)+w(ij,l+1)-w(ij,l)
998            q(ij,l,iq)=(q(ij,l,iq)*masse(ij,l,iq)+wq(ij,l+1)-wq(ij,l))
999     &         /newmasse
1000            masse(ij,l,iq)=newmasse
1001         ENDDO
1002      ENDDO
1003
1004! retablir les fils en rapport de melange par rapport a l'air:
1005      do ifils=1,tracers(iq)%nqDescen
1006        iq2=tracers(iq)%iqDescen(ifils)
1007        DO l=1,llm
1008          DO ij=1,ip1jmp1
1009            q(ij,l,iq2)=q(ij,l,iq)*Ratio(ij,l,iq2)           
1010          enddo
1011        enddo
1012      enddo
1013      !write(*,*) 'vlsplt 1032'
1014
1015      RETURN
1016      END
1017c      SUBROUTINE minmaxq(zq,qmin,qmax,comment)
1018c
1019c#include "dimensions.h"
1020c#include "paramet.h"
1021
1022c      CHARACTER*(*) comment
1023c      real qmin,qmax
1024c      real zq(ip1jmp1,llm)
1025
1026c      INTEGER jadrs(ip1jmp1), jbad, k, i
1027
1028
1029c      DO k = 1, llm
1030c         jbad = 0
1031c         DO i = 1, ip1jmp1
1032c         IF (zq(i,k).GT.qmax .OR. zq(i,k).LT.qmin) THEN
1033c            jbad = jbad + 1
1034c            jadrs(jbad) = i
1035c         ENDIF
1036c         ENDDO
1037c         IF (jbad.GT.0) THEN
1038c         PRINT*, comment
1039c         DO i = 1, jbad
1040cc            PRINT*, "i,k,zq=", jadrs(i),k,zq(jadrs(i),k)
1041c         ENDDO
1042c         ENDIF
1043c      ENDDO
1044
1045c      return
1046c      end
1047      subroutine minmaxq(zq,qmin,qmax,comment)
1048
1049#include "dimensions.h"
1050#include "paramet.h"
1051
1052      character*20 comment
1053      real qmin,qmax
1054      real zq(ip1jmp1,llm)
1055      real zzq(iip1,jjp1,llm)
1056
1057#ifdef isminmax
1058      integer imin,jmin,lmin,ijlmin
1059      integer imax,jmax,lmax,ijlmax
1060
1061      integer ismin,ismax
1062
1063      call scopy (ip1jmp1*llm,zq,1,zzq,1)
1064
1065      ijlmin=ismin(ijp1llm,zq,1)
1066      lmin=(ijlmin-1)/ip1jmp1+1
1067      ijlmin=ijlmin-(lmin-1.)*ip1jmp1
1068      jmin=(ijlmin-1)/iip1+1
1069      imin=ijlmin-(jmin-1.)*iip1
1070      zqmin=zq(ijlmin,lmin)
1071
1072      ijlmax=ismax(ijp1llm,zq,1)
1073      lmax=(ijlmax-1)/ip1jmp1+1
1074      ijlmax=ijlmax-(lmax-1.)*ip1jmp1
1075      jmax=(ijlmax-1)/iip1+1
1076      imax=ijlmax-(jmax-1.)*iip1
1077      zqmax=zq(ijlmax,lmax)
1078
1079       if(zqmin.lt.qmin)
1080c     s     write(*,9999) comment,
1081     s     write(*,*) comment,
1082     s     imin,jmin,lmin,zqmin,zzq(imin,jmin,lmin)
1083       if(zqmax.gt.qmax)
1084c     s     write(*,9999) comment,
1085     s     write(*,*) comment,
1086     s     imax,jmax,lmax,zqmax,zzq(imax,jmax,lmax)
1087
1088#endif
1089      return
1090c9999  format(a20,'  q(',i3,',',i2,',',i2,')=',e12.5,e12.5)
1091      end
1092
1093
1094
Note: See TracBrowser for help on using the repository browser.