source: LMDZ5/trunk/libf/dyn3d/vlsplt.F @ 2597

Last change on this file since 2597 was 2597, checked in by Ehouarn Millour, 8 years ago

Cleanup in the dynamics: get rid of comconst.h, make it a module comconst_mod.
EM

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