source: trunk/LMDZ.COMMON/libf/dyn3dpar/vlsplt_p.F @ 1443

Last change on this file since 1443 was 1422, checked in by milmd, 10 years ago

In GENERIC, MARS and COMMON models replace some include files by modules (usefull for decoupling physics with dynamics).

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