source: LMDZ5/trunk/libf/dyn3dmem/vlsplt_loc.F @ 2598

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