source: LMDZ6/branches/Ocean_skin/libf/dyn3d/vlsplt.F @ 4036

Last change on this file since 4036 was 4013, checked in by lguez, 3 years ago

Sync latest trunk changes to Ocean_skin

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